├── .gitignore ├── LICENSE ├── README.md ├── ch07 ├── ea_extended │ ├── InspectionExample.php │ └── test.php ├── intelephense │ └── DiagnosticsExample.php ├── phpcpd │ └── src │ │ ├── example.php │ │ ├── example2.php │ │ └── example3.php ├── phpmd │ ├── example.php │ ├── phpmd.baseline.xml │ ├── phpmd.xml │ ├── phpmd_report.html │ └── src │ │ ├── example.php │ │ ├── example2.php │ │ ├── example3.php │ │ └── phpmd_suppress_example.php ├── phpstan │ ├── phpstan-baseline.neon │ ├── phpstan.neon │ └── src │ │ ├── phpstan_example.php │ │ └── phpstan_example2.php └── psalm │ ├── psalm-baseline.xml │ ├── psalm.xml │ └── src │ └── psalm_example.php ├── ch08 ├── pdepend │ └── src │ │ ├── ccn.php │ │ ├── ccn2.php │ │ ├── npath.php │ │ └── npath2.php ├── phploc │ └── src │ │ └── ccn.php └── phpmetrics │ └── src │ └── ccn.php ├── ch09 ├── composer.json └── src │ └── example.php ├── ch10 ├── code_coverage │ ├── .gitignore │ ├── composer.json │ ├── index.php │ ├── phpunit.xml │ ├── src │ │ ├── MyApp.php │ │ ├── MyOtherClass.php │ │ ├── MyRepository.php │ │ └── UntestedClass.php │ └── tests │ │ ├── MyAppTest.php │ │ ├── MyOtherClassTest.php │ │ ├── MyRepositoryTest.php │ │ └── UselessTest.php ├── example-end-to-end-tests │ └── login.spec.js ├── example-integration-tests │ └── IntegrationTestExample.php └── example-unit-tests │ ├── index.php │ ├── src │ ├── MyApp.php │ └── MyRepository.php │ └── tests │ ├── MyClassTest.php │ └── MyRepositoryTest.php ├── ch11 └── example-application │ ├── .github │ └── workflows │ │ └── ci.yml │ ├── README.md │ ├── captainhook.json │ ├── composer.json │ ├── composer.lock │ ├── phpstan.neon │ ├── phpunit.xml │ ├── public │ └── index.php │ ├── src │ ├── Controller │ │ ├── ProductController.php │ │ └── UserController.php │ └── bootstrap.php │ └── tests │ ├── Api │ └── ProductControllerTest.php │ └── Unit │ └── ProductControllerTest.php ├── ch12 └── design-patterns │ ├── .DS_Store │ ├── .gitignore │ ├── README.md │ ├── composer.json │ ├── composer.lock │ └── src │ ├── DependencyInjection │ ├── ConstructorInjection.php │ ├── FileLogger.php │ ├── InstantiationExample.php │ ├── Logger.php │ ├── SetterInjection.php │ └── SetterInjectionFactory.php │ ├── FactoryMethod │ ├── AbstractWriter.php │ ├── CsvEncoder.php │ ├── CsvWriter.php │ ├── Encoder.php │ ├── Example.php │ ├── JsonEncoder.php │ └── JsonWriter.php │ ├── Obvserver │ ├── CustomerAccount.php │ ├── CustomerAccountObserver.php │ ├── MailService.php │ ├── TightlyCoupledExample.php │ └── bootstrap.php │ ├── ServiceLocator │ ├── ServiceLocator.php │ ├── ServiceLocatorExample.php │ └── SomeService.php │ └── Singleton │ └── SingletonExample.php └── ch13 ├── diagrams └── mermaid.md └── openapi ├── .gitignore ├── README.md ├── composer.json ├── openapi-annotations.yaml ├── openapi-attributes.json ├── openapi-attributes.yaml └── src ├── Annotations └── Controller │ └── ProductController.php └── Attributes └── Controller └── ProductController.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Packt 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Clean Code in PHP 4 | 5 | Clean Code in PHP 6 | 7 | This is the code repository for [Clean Code in PHP](https://www.packtpub.com/product/clean-code-in-php/9781804613870), published by Packt. 8 | 9 | **Expert tips and practices to write beautiful, human-friendly, and maintainable PHP** 10 | 11 | ## What is this book about? 12 | PHP is a beginner-friendly language, but also one that is rife with complaints of bad code, yet no clean code books are specific to PHP. Enter Clean Code in PHP. This book is a one-stop guide to learning the theory and best practices of clean code specific to real-world PHP app development environments. 13 | 14 | This book covers the following exciting features: 15 | * Build a solid foundation in clean coding to craft human-readable code 16 | * Understand metrics to determine the quality of your code 17 | * Get to grips with the basics of automated tests 18 | * Implement continuous integration for your PHP applications 19 | * Get an overview of software design patterns to help you write reusable code 20 | * Gain an understanding of coding guidelines and practices for working in teams 21 | 22 | If you feel this book is for you, get your [copy](https://www.amazon.com/Clean-Code-PHP-practices-maintainable/dp/1804613878) today! 23 | 24 | 25 | ## Instructions and Navigations 26 | All of the code is organized into folders. For example, Chapter07. 27 | 28 | The code will look like the following: 29 | ``` 30 | 1) { 8 | return true; 9 | } 10 | 11 | return false; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch07/ea_extended/test.php: -------------------------------------------------------------------------------- 1 | checkGreaterThanOne(5); -------------------------------------------------------------------------------- /ch07/intelephense/DiagnosticsExample.php: -------------------------------------------------------------------------------- 1 | usedAttribute == 2) { 12 | echo $this->usedAttribute; 13 | } 14 | 15 | $testInstance = new TestClass(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch07/phpcpd/src/example.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ch07/phpmd/phpmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | Rule set which contains all codesize and cleancode rules 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch07/phpmd/phpmd_report.html: -------------------------------------------------------------------------------- 1 | 2 | PHPMD Report 3 | 4 |
5 |

PHPMD Report

6 | Generated at 2022-04-27 08:18 7 | with PHP Mess Detector 8 | on PHP 8.0.8 9 | on curtis-desktop 10 |
11 |

2 problems found

Summary

By priority
Count%Priority
2 100.0 % Top (1)
12 |
By rule set
Count%Rule set
2 100.0 % Clean Code Rules
13 |
By name
Count%Rule name
1 50.0 % StaticAccess
1 50.0 % MissingImport
14 |

Details

15 | 21 | Show details ▼ 22 | -------------------------------------------------------------------------------- /ch07/phpmd/src/example.php: -------------------------------------------------------------------------------- 1 | find($id); 30 | } 31 | } -------------------------------------------------------------------------------- /ch07/phpstan/phpstan-baseline.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | ignoreErrors: 3 | - 4 | message: "#^Method Vat\\:\\:getVat\\(\\) should return int but returns float\\.$#" 5 | count: 1 6 | path: src/phpstan_example.php 7 | 8 | - 9 | message: "#^Method OrderPosition\\:\\:getGrossPrice\\(\\) has no return type specified\\.$#" 10 | count: 1 11 | path: src/phpstan_example2.php 12 | 13 | -------------------------------------------------------------------------------- /ch07/phpstan/phpstan.neon: -------------------------------------------------------------------------------- 1 | # includes: 2 | # - phpstan-baseline.neon 3 | parameters: 4 | level: 6 5 | paths: 6 | - src -------------------------------------------------------------------------------- /ch07/phpstan/src/phpstan_example.php: -------------------------------------------------------------------------------- 1 | vat; 10 | } 11 | } 12 | 13 | class OrderPosition 14 | { 15 | public function getGrossPrice(float $netPrice): float 16 | { 17 | $vatModel = new Vat(); 18 | $vat = $vatModel->getVat(); 19 | 20 | return $netPrice * (1 + $vat); 21 | } 22 | } 23 | 24 | $orderPosition = new OrderPosition(); 25 | echo $orderPosition->getGrossPrice(100); -------------------------------------------------------------------------------- /ch07/phpstan/src/phpstan_example2.php: -------------------------------------------------------------------------------- 1 | vat; 10 | } 11 | } 12 | 13 | class OrderPosition 14 | { 15 | public function getGrossPrice(float $netPrice) 16 | { 17 | $vatModel = new Vat(); 18 | $vat = $vatModel->getVat(); 19 | 20 | return $netPrice * (1 + $vat); 21 | } 22 | } 23 | 24 | $orderPosition = new OrderPosition(); 25 | echo $orderPosition->getGrossPrice(100); -------------------------------------------------------------------------------- /ch07/psalm/psalm-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /ch07/psalm/psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | -------------------------------------------------------------------------------- /ch07/psalm/src/psalm_example.php: -------------------------------------------------------------------------------- 1 | vat; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch08/pdepend/src/ccn.php: -------------------------------------------------------------------------------- 1 | $b) { 14 | echo "3"; 15 | } else { 16 | echo "4"; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /ch08/pdepend/src/ccn2.php: -------------------------------------------------------------------------------- 1 | $b) { 14 | echo "3"; 15 | } else { 16 | echo "4"; 17 | } 18 | 19 | if ($a == $b) { 20 | echo "5"; 21 | } else { 22 | echo "6"; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /ch08/pdepend/src/npath.php: -------------------------------------------------------------------------------- 1 | 10) { 9 | echo 1; 10 | } else { 11 | echo 2; 12 | } 13 | if ($a > $b) { 14 | echo 3; 15 | } else { 16 | echo 4; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch08/pdepend/src/npath2.php: -------------------------------------------------------------------------------- 1 | 10) { 8 | echo 1; 9 | } else { 10 | echo 2; 11 | } 12 | if ($a > $b) { 13 | echo 3; 14 | } else { 15 | echo 4; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch08/phploc/src/ccn.php: -------------------------------------------------------------------------------- 1 | vat; 10 | } 11 | } 12 | 13 | class OrderPosition 14 | { 15 | public function getGrossPrice(float $netPrice): float 16 | { 17 | $vatModel = new Vat(); 18 | $vat = $vatModel->getVat(); 19 | 20 | return $netPrice * (1 + $vat); 21 | } 22 | } 23 | 24 | $orderPosition = new OrderPosition(); 25 | echo $orderPosition->getGrossPrice(100); 26 | -------------------------------------------------------------------------------- /ch10/code_coverage/.gitignore: -------------------------------------------------------------------------------- 1 | .phpunit.cache 2 | .phive 3 | reports 4 | -------------------------------------------------------------------------------- /ch10/code_coverage/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "phpunit/phpunit": "^9.5" 4 | }, 5 | "autoload-dev": { 6 | "psr-4": { 7 | "CodeCoverageExample\\": "src/", 8 | "CodeCoverageExampleTest\\": "tests/" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch10/code_coverage/index.php: -------------------------------------------------------------------------------- 1 | run(); -------------------------------------------------------------------------------- /ch10/code_coverage/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | tests 10 | 11 | 12 | 13 | 14 | src 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch10/code_coverage/src/MyApp.php: -------------------------------------------------------------------------------- 1 | myRepository->getData(); 17 | 18 | return $dataArray['value_1'] . $dataArray['value_2']; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch10/code_coverage/src/MyOtherClass.php: -------------------------------------------------------------------------------- 1 | 0) { 12 | return $a + 1; 13 | } 14 | 15 | if ($a === 0) { 16 | return $a; 17 | } 18 | 19 | return $a - 1; 20 | 21 | echo "nothing"; 22 | } 23 | 24 | public function gni() 25 | { 26 | echo "nothing"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch10/code_coverage/src/MyRepository.php: -------------------------------------------------------------------------------- 1 | 'some data...', 13 | 'val2' => 'and some more data' 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch10/code_coverage/src/UntestedClass.php: -------------------------------------------------------------------------------- 1 | myRepository->getData(); 12 | 13 | return $dataArray['value_1'] . $dataArray['value_2']; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch10/code_coverage/tests/MyAppTest.php: -------------------------------------------------------------------------------- 1 | createMock(MyRepository::class); 19 | $repositoryMock 20 | ->expects($this->once()) 21 | ->method('getData') 22 | ->willReturn([ 23 | 'value_1' => 'a', 24 | 'value_2' => 'b' 25 | ]); 26 | 27 | $appTest = new MyApp($repositoryMock); 28 | 29 | $result = $appTest->run(); 30 | 31 | $this->assertEquals('ab', $result); 32 | } 33 | } -------------------------------------------------------------------------------- /ch10/code_coverage/tests/MyOtherClassTest.php: -------------------------------------------------------------------------------- 1 | doSomething(1); 20 | 21 | $this->assertEquals(2, $result); 22 | } 23 | } -------------------------------------------------------------------------------- /ch10/code_coverage/tests/MyRepositoryTest.php: -------------------------------------------------------------------------------- 1 | getData(); 20 | 21 | $this->assertIsArray($result); 22 | $this->assertCount(2, $result); 23 | } 24 | } -------------------------------------------------------------------------------- /ch10/code_coverage/tests/UselessTest.php: -------------------------------------------------------------------------------- 1 | createMock(MyRepository::class); 18 | $repositoryMock 19 | ->method('getData') 20 | ->willReturn([ 21 | 'value_1' => 'a', 22 | 'value_2' => 'b' 23 | ]); 24 | 25 | $this->assertEquals( 26 | [ 27 | 'value_1' => 'a', 28 | 'value_2' => 'b' 29 | ], 30 | $repositoryMock->getData() 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /ch10/example-end-to-end-tests/login.spec.js: -------------------------------------------------------------------------------- 1 | describe('Application Login', function () { 2 | it('successfully logs in', function () { 3 | cy.visit('http://localhost:8000/login') 4 | 5 | cy.get('#username') 6 | .type('test@test.com') 7 | 8 | cy.get('#password') 9 | .type('supersecret') 10 | 11 | cy.get('#submit') 12 | .click() 13 | 14 | cy.url() 15 | .should('contain', 'http://localhost:8000/home') 16 | }) 17 | }) -------------------------------------------------------------------------------- /ch10/example-integration-tests/IntegrationTestExample.php: -------------------------------------------------------------------------------- 1 | setId(123); 11 | $product->setName('USB Coffee Maker'); 12 | $product->save(); 13 | 14 | $this->tester->seeInDatabase( 15 | 'products', 16 | ['id' => 123, 'name' => 'USB Coffee Maker' ] 17 | ); 18 | } 19 | } -------------------------------------------------------------------------------- /ch10/example-unit-tests/index.php: -------------------------------------------------------------------------------- 1 | run(); -------------------------------------------------------------------------------- /ch10/example-unit-tests/src/MyApp.php: -------------------------------------------------------------------------------- 1 | myRepository->getData(); 17 | 18 | return $dataArray['value_1'] . $dataArray['value_2']; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch10/example-unit-tests/src/MyRepository.php: -------------------------------------------------------------------------------- 1 | 'some data...', 13 | 'val2' => 'and some more data' 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch10/example-unit-tests/tests/MyClassTest.php: -------------------------------------------------------------------------------- 1 | createMock(MyRepository::class); 16 | $repositoryMock 17 | ->expects($this->once()) 18 | ->method('getData') 19 | ->willReturn([ 20 | 'value_1' => 'a', 21 | 'value_2' => 'b' 22 | ]); 23 | 24 | $appTest = new MyApp($repositoryMock); 25 | 26 | $result = $appTest->run(); 27 | 28 | $this->assertEquals('ab', $result); 29 | } 30 | } -------------------------------------------------------------------------------- /ch10/example-unit-tests/tests/MyRepositoryTest.php: -------------------------------------------------------------------------------- 1 | getData(); 17 | 18 | $this->assertIsArray($result); 19 | $this->assertCount(2, $result); 20 | } 21 | } -------------------------------------------------------------------------------- /ch11/example-application/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | 10 | jobs: 11 | pipeline: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | ################### 16 | # Stage 1 - Build # 17 | ################### 18 | - name: Checkout latest revision 19 | uses: actions/checkout@v3 20 | 21 | - name: Install PHP 22 | uses: shivammathur/setup-php@v2 23 | with: 24 | php-version: '8.1' 25 | coverage: pcov 26 | 27 | - name: Get composer cache directory 28 | id: composer-cache 29 | run: echo "::set-output name=dir::$(composer config cache-files-dir)" 30 | 31 | - name: Cache dependencies 32 | uses: actions/cache@v2 33 | with: 34 | path: ${{ steps.composer-cache.outputs.dir }} 35 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 36 | restore-keys: ${{ runner.os }}-composer- 37 | 38 | - name: Install composer dependencies 39 | run: composer install 40 | 41 | - name: Start PHP built-in webserver 42 | run: php -S localhost:8000 -t public & 43 | 44 | ########################### 45 | # Stage 2 - Code Analysis # 46 | ########################### 47 | - name: Code Style Fixer 48 | run: vendor/bin/php-cs-fixer fix --dry-run 49 | 50 | - name: Static Code Analysis 51 | run: vendor/bin/phpstan 52 | 53 | ################### 54 | # Stage 3 - Tests # 55 | ################### 56 | - name: Unit Tests 57 | run: vendor/bin/phpunit --testsuite Unit 58 | 59 | - name: Integration Tests 60 | run: vendor/bin/phpunit --testsuite Api 61 | 62 | #################### 63 | # Stage 4 - Deploy # 64 | #################### 65 | - name: Remove dev dependencies 66 | run: composer install --no-dev --optimize-autoloader 67 | 68 | - name: Create release artifact 69 | uses: actions/upload-artifact@v2 70 | with: 71 | name: release 72 | path: | 73 | public/ 74 | src/ 75 | vendor/ 76 | 77 | - name: Create reports artifact 78 | uses: actions/upload-artifact@v2 79 | with: 80 | name: reports 81 | path: reports/ 82 | -------------------------------------------------------------------------------- /ch11/example-application/README.md: -------------------------------------------------------------------------------- 1 | # Continuous Integration example 2 | 3 | This is a simple example application to demonstrate 4 | 1. how to build a Continuous Integration pipeline with GitHub Actions 5 | 2. how to set up a local pipeline using CaptainHook 6 | 7 | ## Installation 8 | To install it locally, simply run 9 | 10 | `composer install` 11 | 12 | ## Hot to test GitHub Actions 13 | 14 | To test the GitHub Actions pipeline, please create a separate GitHub repository from the project folder. This is necessary, because GitHub requires the `.github/worfklows` folder to be located in the project root. 15 | 16 | ## How to test CaptainHook 17 | 18 | After running `composer install`, the `pre-commit` hook is already installed. To test it, simply change a PHP file, add it using `git add`, and commit the changes using `git commit`. -------------------------------------------------------------------------------- /ch11/example-application/captainhook.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "fail-on-first-error": true 4 | }, 5 | "pre-commit": { 6 | "enabled": true, 7 | "actions": [ 8 | { 9 | "action": "vendor/bin/php-cs-fixer fix {$STAGED_FILES|of-type:php} --dry-run" 10 | }, 11 | { 12 | "action": "vendor/bin/phpstan analyse {$STAGED_FILES|of-type:php}" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch11/example-application/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clean-code-book/github-actions-pipeline", 3 | "description": "Example setup of a simple GitHub Actions pipeline", 4 | "type": "project", 5 | "require": { 6 | "php": ">= 8.1", 7 | "league/route": "^5.1", 8 | "laminas/laminas-diactoros": "^2.13", 9 | "laminas/laminas-httphandlerrunner": "^2.1" 10 | }, 11 | "require-dev": { 12 | "phpunit/phpunit": "^9.5", 13 | "phpstan/phpstan": "^1.8", 14 | "friendsofphp/php-cs-fixer": "^3.8", 15 | "guzzlehttp/guzzle": "^7.4", 16 | "captainhook/captainhook": "^5.10" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "GitHubActionsExample\\":"src/" 21 | } 22 | }, 23 | "scripts": { 24 | "post-autoload-dump": [ 25 | "if [ -e vendor/bin/captainhook ]; then vendor/bin/captainhook install -f -s; fi" 26 | ] 27 | }, 28 | "authors": [ 29 | { 30 | "name": "Carsten Windler", 31 | "email": "carsten@carstenwindler.de" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /ch11/example-application/phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 5 3 | paths: 4 | - src 5 | -------------------------------------------------------------------------------- /ch11/example-application/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | tests/Api 18 | 19 | 20 | tests/Unit 21 | 22 | 23 | 24 | 25 | 26 | src 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ch11/example-application/public/index.php: -------------------------------------------------------------------------------- 1 | 1, 14 | 'name' => 'Foo product', 15 | ] 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch11/example-application/src/Controller/UserController.php: -------------------------------------------------------------------------------- 1 | 1, 14 | 'name' => 'Foo bar', 15 | ] 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch11/example-application/src/bootstrap.php: -------------------------------------------------------------------------------- 1 | setStrategy($strategy); 19 | 20 | // Define routes 21 | $router->map( 22 | 'GET', 23 | '/products', 24 | [ 25 | ProductController::class, 26 | 'get' 27 | ] 28 | ); 29 | 30 | $router->map( 31 | 'GET', 32 | '/users', 33 | [ 34 | UserController::class, 35 | 'get' 36 | ] 37 | ); 38 | 39 | // Dispatch the request to receive a response object 40 | $response = $router->dispatch($request); 41 | 42 | // Send the response 43 | (new Laminas\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response); 44 | -------------------------------------------------------------------------------- /ch11/example-application/tests/Api/ProductControllerTest.php: -------------------------------------------------------------------------------- 1 | getBody()->getContents(), 22 | true, 23 | 512, 24 | JSON_THROW_ON_ERROR 25 | ); 26 | } 27 | 28 | public function setUp(): void 29 | { 30 | $this->client = new Client(); 31 | } 32 | 33 | public function testGetProducts() 34 | { 35 | $response = $this->client->request( 36 | 'GET', 37 | 'http://localhost:8000/products' 38 | ); 39 | 40 | $this->assertEquals( 41 | 200, 42 | $response->getStatusCode() 43 | ); 44 | 45 | $this->assertEquals( 46 | [ 47 | [ 48 | 'id' => 1, 49 | 'name' => 'Foo product', 50 | ] 51 | ], 52 | $this->getResponseAsArray($response) 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch11/example-application/tests/Unit/ProductControllerTest.php: -------------------------------------------------------------------------------- 1 | assertEquals( 20 | [ 21 | [ 22 | 'id' => 1, 23 | 'name' => 'Foo product', 24 | ] 25 | ], 26 | $productController->get() 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch12/design-patterns/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Clean-Code-in-PHP/4a0c2323a62450f6cc82ff8dc861e1a5d51b9ed9/ch12/design-patterns/.DS_Store -------------------------------------------------------------------------------- /ch12/design-patterns/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ -------------------------------------------------------------------------------- /ch12/design-patterns/README.md: -------------------------------------------------------------------------------- 1 | # Design Patterns 2 | 3 | This project contains no usable code, only the examples from chapter 12 of our book. 4 | 5 | ## Installation 6 | 7 | Run `composer install`. No more action needed. 8 | 9 | ## Running the examples 10 | 11 | Every 12 | 13 | TODO FORMAST PSR-12!!!!!!!!!!!!!!!!!!! -------------------------------------------------------------------------------- /ch12/design-patterns/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clean-code-book/design-patterns", 3 | "description": "Example code for the design patterns discussed in our book", 4 | "type": "project", 5 | "autoload": { 6 | "psr-4": { 7 | "DesignPatterns\\": "src/" 8 | } 9 | }, 10 | "authors": [ 11 | { 12 | "name": "Carsten Windler", 13 | "email": "carsten@carstenwindler.de" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /ch12/design-patterns/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": "f431e700213d937b59fdd6e5a31e54a7", 8 | "packages": [ 9 | { 10 | "name": "doctrine/instantiator", 11 | "version": "1.4.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/doctrine/instantiator.git", 15 | "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", 20 | "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^7.1 || ^8.0" 25 | }, 26 | "require-dev": { 27 | "doctrine/coding-standard": "^9", 28 | "ext-pdo": "*", 29 | "ext-phar": "*", 30 | "phpbench/phpbench": "^0.16 || ^1", 31 | "phpstan/phpstan": "^1.4", 32 | "phpstan/phpstan-phpunit": "^1", 33 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", 34 | "vimeo/psalm": "^4.22" 35 | }, 36 | "type": "library", 37 | "autoload": { 38 | "psr-4": { 39 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Marco Pivetta", 49 | "email": "ocramius@gmail.com", 50 | "homepage": "https://ocramius.github.io/" 51 | } 52 | ], 53 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 54 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 55 | "keywords": [ 56 | "constructor", 57 | "instantiate" 58 | ], 59 | "support": { 60 | "issues": "https://github.com/doctrine/instantiator/issues", 61 | "source": "https://github.com/doctrine/instantiator/tree/1.4.1" 62 | }, 63 | "funding": [ 64 | { 65 | "url": "https://www.doctrine-project.org/sponsorship.html", 66 | "type": "custom" 67 | }, 68 | { 69 | "url": "https://www.patreon.com/phpdoctrine", 70 | "type": "patreon" 71 | }, 72 | { 73 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 74 | "type": "tidelift" 75 | } 76 | ], 77 | "time": "2022-03-03T08:28:38+00:00" 78 | }, 79 | { 80 | "name": "myclabs/deep-copy", 81 | "version": "1.11.0", 82 | "source": { 83 | "type": "git", 84 | "url": "https://github.com/myclabs/DeepCopy.git", 85 | "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" 86 | }, 87 | "dist": { 88 | "type": "zip", 89 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", 90 | "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", 91 | "shasum": "" 92 | }, 93 | "require": { 94 | "php": "^7.1 || ^8.0" 95 | }, 96 | "conflict": { 97 | "doctrine/collections": "<1.6.8", 98 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 99 | }, 100 | "require-dev": { 101 | "doctrine/collections": "^1.6.8", 102 | "doctrine/common": "^2.13.3 || ^3.2.2", 103 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 104 | }, 105 | "type": "library", 106 | "autoload": { 107 | "files": [ 108 | "src/DeepCopy/deep_copy.php" 109 | ], 110 | "psr-4": { 111 | "DeepCopy\\": "src/DeepCopy/" 112 | } 113 | }, 114 | "notification-url": "https://packagist.org/downloads/", 115 | "license": [ 116 | "MIT" 117 | ], 118 | "description": "Create deep copies (clones) of your objects", 119 | "keywords": [ 120 | "clone", 121 | "copy", 122 | "duplicate", 123 | "object", 124 | "object graph" 125 | ], 126 | "support": { 127 | "issues": "https://github.com/myclabs/DeepCopy/issues", 128 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" 129 | }, 130 | "funding": [ 131 | { 132 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 133 | "type": "tidelift" 134 | } 135 | ], 136 | "time": "2022-03-03T13:19:32+00:00" 137 | }, 138 | { 139 | "name": "nikic/php-parser", 140 | "version": "v4.14.0", 141 | "source": { 142 | "type": "git", 143 | "url": "https://github.com/nikic/PHP-Parser.git", 144 | "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" 145 | }, 146 | "dist": { 147 | "type": "zip", 148 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", 149 | "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", 150 | "shasum": "" 151 | }, 152 | "require": { 153 | "ext-tokenizer": "*", 154 | "php": ">=7.0" 155 | }, 156 | "require-dev": { 157 | "ircmaxell/php-yacc": "^0.0.7", 158 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 159 | }, 160 | "bin": [ 161 | "bin/php-parse" 162 | ], 163 | "type": "library", 164 | "extra": { 165 | "branch-alias": { 166 | "dev-master": "4.9-dev" 167 | } 168 | }, 169 | "autoload": { 170 | "psr-4": { 171 | "PhpParser\\": "lib/PhpParser" 172 | } 173 | }, 174 | "notification-url": "https://packagist.org/downloads/", 175 | "license": [ 176 | "BSD-3-Clause" 177 | ], 178 | "authors": [ 179 | { 180 | "name": "Nikita Popov" 181 | } 182 | ], 183 | "description": "A PHP parser written in PHP", 184 | "keywords": [ 185 | "parser", 186 | "php" 187 | ], 188 | "support": { 189 | "issues": "https://github.com/nikic/PHP-Parser/issues", 190 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" 191 | }, 192 | "time": "2022-05-31T20:59:12+00:00" 193 | }, 194 | { 195 | "name": "phar-io/manifest", 196 | "version": "2.0.3", 197 | "source": { 198 | "type": "git", 199 | "url": "https://github.com/phar-io/manifest.git", 200 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53" 201 | }, 202 | "dist": { 203 | "type": "zip", 204 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", 205 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53", 206 | "shasum": "" 207 | }, 208 | "require": { 209 | "ext-dom": "*", 210 | "ext-phar": "*", 211 | "ext-xmlwriter": "*", 212 | "phar-io/version": "^3.0.1", 213 | "php": "^7.2 || ^8.0" 214 | }, 215 | "type": "library", 216 | "extra": { 217 | "branch-alias": { 218 | "dev-master": "2.0.x-dev" 219 | } 220 | }, 221 | "autoload": { 222 | "classmap": [ 223 | "src/" 224 | ] 225 | }, 226 | "notification-url": "https://packagist.org/downloads/", 227 | "license": [ 228 | "BSD-3-Clause" 229 | ], 230 | "authors": [ 231 | { 232 | "name": "Arne Blankerts", 233 | "email": "arne@blankerts.de", 234 | "role": "Developer" 235 | }, 236 | { 237 | "name": "Sebastian Heuer", 238 | "email": "sebastian@phpeople.de", 239 | "role": "Developer" 240 | }, 241 | { 242 | "name": "Sebastian Bergmann", 243 | "email": "sebastian@phpunit.de", 244 | "role": "Developer" 245 | } 246 | ], 247 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 248 | "support": { 249 | "issues": "https://github.com/phar-io/manifest/issues", 250 | "source": "https://github.com/phar-io/manifest/tree/2.0.3" 251 | }, 252 | "time": "2021-07-20T11:28:43+00:00" 253 | }, 254 | { 255 | "name": "phar-io/version", 256 | "version": "3.2.1", 257 | "source": { 258 | "type": "git", 259 | "url": "https://github.com/phar-io/version.git", 260 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 261 | }, 262 | "dist": { 263 | "type": "zip", 264 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 265 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 266 | "shasum": "" 267 | }, 268 | "require": { 269 | "php": "^7.2 || ^8.0" 270 | }, 271 | "type": "library", 272 | "autoload": { 273 | "classmap": [ 274 | "src/" 275 | ] 276 | }, 277 | "notification-url": "https://packagist.org/downloads/", 278 | "license": [ 279 | "BSD-3-Clause" 280 | ], 281 | "authors": [ 282 | { 283 | "name": "Arne Blankerts", 284 | "email": "arne@blankerts.de", 285 | "role": "Developer" 286 | }, 287 | { 288 | "name": "Sebastian Heuer", 289 | "email": "sebastian@phpeople.de", 290 | "role": "Developer" 291 | }, 292 | { 293 | "name": "Sebastian Bergmann", 294 | "email": "sebastian@phpunit.de", 295 | "role": "Developer" 296 | } 297 | ], 298 | "description": "Library for handling version information and constraints", 299 | "support": { 300 | "issues": "https://github.com/phar-io/version/issues", 301 | "source": "https://github.com/phar-io/version/tree/3.2.1" 302 | }, 303 | "time": "2022-02-21T01:04:05+00:00" 304 | }, 305 | { 306 | "name": "phpdocumentor/reflection-common", 307 | "version": "2.2.0", 308 | "source": { 309 | "type": "git", 310 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 311 | "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" 312 | }, 313 | "dist": { 314 | "type": "zip", 315 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", 316 | "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", 317 | "shasum": "" 318 | }, 319 | "require": { 320 | "php": "^7.2 || ^8.0" 321 | }, 322 | "type": "library", 323 | "extra": { 324 | "branch-alias": { 325 | "dev-2.x": "2.x-dev" 326 | } 327 | }, 328 | "autoload": { 329 | "psr-4": { 330 | "phpDocumentor\\Reflection\\": "src/" 331 | } 332 | }, 333 | "notification-url": "https://packagist.org/downloads/", 334 | "license": [ 335 | "MIT" 336 | ], 337 | "authors": [ 338 | { 339 | "name": "Jaap van Otterdijk", 340 | "email": "opensource@ijaap.nl" 341 | } 342 | ], 343 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 344 | "homepage": "http://www.phpdoc.org", 345 | "keywords": [ 346 | "FQSEN", 347 | "phpDocumentor", 348 | "phpdoc", 349 | "reflection", 350 | "static analysis" 351 | ], 352 | "support": { 353 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", 354 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" 355 | }, 356 | "time": "2020-06-27T09:03:43+00:00" 357 | }, 358 | { 359 | "name": "phpdocumentor/reflection-docblock", 360 | "version": "5.3.0", 361 | "source": { 362 | "type": "git", 363 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 364 | "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" 365 | }, 366 | "dist": { 367 | "type": "zip", 368 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", 369 | "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", 370 | "shasum": "" 371 | }, 372 | "require": { 373 | "ext-filter": "*", 374 | "php": "^7.2 || ^8.0", 375 | "phpdocumentor/reflection-common": "^2.2", 376 | "phpdocumentor/type-resolver": "^1.3", 377 | "webmozart/assert": "^1.9.1" 378 | }, 379 | "require-dev": { 380 | "mockery/mockery": "~1.3.2", 381 | "psalm/phar": "^4.8" 382 | }, 383 | "type": "library", 384 | "extra": { 385 | "branch-alias": { 386 | "dev-master": "5.x-dev" 387 | } 388 | }, 389 | "autoload": { 390 | "psr-4": { 391 | "phpDocumentor\\Reflection\\": "src" 392 | } 393 | }, 394 | "notification-url": "https://packagist.org/downloads/", 395 | "license": [ 396 | "MIT" 397 | ], 398 | "authors": [ 399 | { 400 | "name": "Mike van Riel", 401 | "email": "me@mikevanriel.com" 402 | }, 403 | { 404 | "name": "Jaap van Otterdijk", 405 | "email": "account@ijaap.nl" 406 | } 407 | ], 408 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 409 | "support": { 410 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", 411 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" 412 | }, 413 | "time": "2021-10-19T17:43:47+00:00" 414 | }, 415 | { 416 | "name": "phpdocumentor/type-resolver", 417 | "version": "1.6.1", 418 | "source": { 419 | "type": "git", 420 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 421 | "reference": "77a32518733312af16a44300404e945338981de3" 422 | }, 423 | "dist": { 424 | "type": "zip", 425 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", 426 | "reference": "77a32518733312af16a44300404e945338981de3", 427 | "shasum": "" 428 | }, 429 | "require": { 430 | "php": "^7.2 || ^8.0", 431 | "phpdocumentor/reflection-common": "^2.0" 432 | }, 433 | "require-dev": { 434 | "ext-tokenizer": "*", 435 | "psalm/phar": "^4.8" 436 | }, 437 | "type": "library", 438 | "extra": { 439 | "branch-alias": { 440 | "dev-1.x": "1.x-dev" 441 | } 442 | }, 443 | "autoload": { 444 | "psr-4": { 445 | "phpDocumentor\\Reflection\\": "src" 446 | } 447 | }, 448 | "notification-url": "https://packagist.org/downloads/", 449 | "license": [ 450 | "MIT" 451 | ], 452 | "authors": [ 453 | { 454 | "name": "Mike van Riel", 455 | "email": "me@mikevanriel.com" 456 | } 457 | ], 458 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 459 | "support": { 460 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues", 461 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" 462 | }, 463 | "time": "2022-03-15T21:29:03+00:00" 464 | }, 465 | { 466 | "name": "phpspec/prophecy", 467 | "version": "v1.15.0", 468 | "source": { 469 | "type": "git", 470 | "url": "https://github.com/phpspec/prophecy.git", 471 | "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" 472 | }, 473 | "dist": { 474 | "type": "zip", 475 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", 476 | "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", 477 | "shasum": "" 478 | }, 479 | "require": { 480 | "doctrine/instantiator": "^1.2", 481 | "php": "^7.2 || ~8.0, <8.2", 482 | "phpdocumentor/reflection-docblock": "^5.2", 483 | "sebastian/comparator": "^3.0 || ^4.0", 484 | "sebastian/recursion-context": "^3.0 || ^4.0" 485 | }, 486 | "require-dev": { 487 | "phpspec/phpspec": "^6.0 || ^7.0", 488 | "phpunit/phpunit": "^8.0 || ^9.0" 489 | }, 490 | "type": "library", 491 | "extra": { 492 | "branch-alias": { 493 | "dev-master": "1.x-dev" 494 | } 495 | }, 496 | "autoload": { 497 | "psr-4": { 498 | "Prophecy\\": "src/Prophecy" 499 | } 500 | }, 501 | "notification-url": "https://packagist.org/downloads/", 502 | "license": [ 503 | "MIT" 504 | ], 505 | "authors": [ 506 | { 507 | "name": "Konstantin Kudryashov", 508 | "email": "ever.zet@gmail.com", 509 | "homepage": "http://everzet.com" 510 | }, 511 | { 512 | "name": "Marcello Duarte", 513 | "email": "marcello.duarte@gmail.com" 514 | } 515 | ], 516 | "description": "Highly opinionated mocking framework for PHP 5.3+", 517 | "homepage": "https://github.com/phpspec/prophecy", 518 | "keywords": [ 519 | "Double", 520 | "Dummy", 521 | "fake", 522 | "mock", 523 | "spy", 524 | "stub" 525 | ], 526 | "support": { 527 | "issues": "https://github.com/phpspec/prophecy/issues", 528 | "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" 529 | }, 530 | "time": "2021-12-08T12:19:24+00:00" 531 | }, 532 | { 533 | "name": "phpunit/php-code-coverage", 534 | "version": "9.2.15", 535 | "source": { 536 | "type": "git", 537 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 538 | "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" 539 | }, 540 | "dist": { 541 | "type": "zip", 542 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", 543 | "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", 544 | "shasum": "" 545 | }, 546 | "require": { 547 | "ext-dom": "*", 548 | "ext-libxml": "*", 549 | "ext-xmlwriter": "*", 550 | "nikic/php-parser": "^4.13.0", 551 | "php": ">=7.3", 552 | "phpunit/php-file-iterator": "^3.0.3", 553 | "phpunit/php-text-template": "^2.0.2", 554 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 555 | "sebastian/complexity": "^2.0", 556 | "sebastian/environment": "^5.1.2", 557 | "sebastian/lines-of-code": "^1.0.3", 558 | "sebastian/version": "^3.0.1", 559 | "theseer/tokenizer": "^1.2.0" 560 | }, 561 | "require-dev": { 562 | "phpunit/phpunit": "^9.3" 563 | }, 564 | "suggest": { 565 | "ext-pcov": "*", 566 | "ext-xdebug": "*" 567 | }, 568 | "type": "library", 569 | "extra": { 570 | "branch-alias": { 571 | "dev-master": "9.2-dev" 572 | } 573 | }, 574 | "autoload": { 575 | "classmap": [ 576 | "src/" 577 | ] 578 | }, 579 | "notification-url": "https://packagist.org/downloads/", 580 | "license": [ 581 | "BSD-3-Clause" 582 | ], 583 | "authors": [ 584 | { 585 | "name": "Sebastian Bergmann", 586 | "email": "sebastian@phpunit.de", 587 | "role": "lead" 588 | } 589 | ], 590 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 591 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 592 | "keywords": [ 593 | "coverage", 594 | "testing", 595 | "xunit" 596 | ], 597 | "support": { 598 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 599 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" 600 | }, 601 | "funding": [ 602 | { 603 | "url": "https://github.com/sebastianbergmann", 604 | "type": "github" 605 | } 606 | ], 607 | "time": "2022-03-07T09:28:20+00:00" 608 | }, 609 | { 610 | "name": "phpunit/php-file-iterator", 611 | "version": "3.0.6", 612 | "source": { 613 | "type": "git", 614 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 615 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 616 | }, 617 | "dist": { 618 | "type": "zip", 619 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 620 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 621 | "shasum": "" 622 | }, 623 | "require": { 624 | "php": ">=7.3" 625 | }, 626 | "require-dev": { 627 | "phpunit/phpunit": "^9.3" 628 | }, 629 | "type": "library", 630 | "extra": { 631 | "branch-alias": { 632 | "dev-master": "3.0-dev" 633 | } 634 | }, 635 | "autoload": { 636 | "classmap": [ 637 | "src/" 638 | ] 639 | }, 640 | "notification-url": "https://packagist.org/downloads/", 641 | "license": [ 642 | "BSD-3-Clause" 643 | ], 644 | "authors": [ 645 | { 646 | "name": "Sebastian Bergmann", 647 | "email": "sebastian@phpunit.de", 648 | "role": "lead" 649 | } 650 | ], 651 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 652 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 653 | "keywords": [ 654 | "filesystem", 655 | "iterator" 656 | ], 657 | "support": { 658 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 659 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 660 | }, 661 | "funding": [ 662 | { 663 | "url": "https://github.com/sebastianbergmann", 664 | "type": "github" 665 | } 666 | ], 667 | "time": "2021-12-02T12:48:52+00:00" 668 | }, 669 | { 670 | "name": "phpunit/php-invoker", 671 | "version": "3.1.1", 672 | "source": { 673 | "type": "git", 674 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 675 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 676 | }, 677 | "dist": { 678 | "type": "zip", 679 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 680 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 681 | "shasum": "" 682 | }, 683 | "require": { 684 | "php": ">=7.3" 685 | }, 686 | "require-dev": { 687 | "ext-pcntl": "*", 688 | "phpunit/phpunit": "^9.3" 689 | }, 690 | "suggest": { 691 | "ext-pcntl": "*" 692 | }, 693 | "type": "library", 694 | "extra": { 695 | "branch-alias": { 696 | "dev-master": "3.1-dev" 697 | } 698 | }, 699 | "autoload": { 700 | "classmap": [ 701 | "src/" 702 | ] 703 | }, 704 | "notification-url": "https://packagist.org/downloads/", 705 | "license": [ 706 | "BSD-3-Clause" 707 | ], 708 | "authors": [ 709 | { 710 | "name": "Sebastian Bergmann", 711 | "email": "sebastian@phpunit.de", 712 | "role": "lead" 713 | } 714 | ], 715 | "description": "Invoke callables with a timeout", 716 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 717 | "keywords": [ 718 | "process" 719 | ], 720 | "support": { 721 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 722 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 723 | }, 724 | "funding": [ 725 | { 726 | "url": "https://github.com/sebastianbergmann", 727 | "type": "github" 728 | } 729 | ], 730 | "time": "2020-09-28T05:58:55+00:00" 731 | }, 732 | { 733 | "name": "phpunit/php-text-template", 734 | "version": "2.0.4", 735 | "source": { 736 | "type": "git", 737 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 738 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 739 | }, 740 | "dist": { 741 | "type": "zip", 742 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 743 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 744 | "shasum": "" 745 | }, 746 | "require": { 747 | "php": ">=7.3" 748 | }, 749 | "require-dev": { 750 | "phpunit/phpunit": "^9.3" 751 | }, 752 | "type": "library", 753 | "extra": { 754 | "branch-alias": { 755 | "dev-master": "2.0-dev" 756 | } 757 | }, 758 | "autoload": { 759 | "classmap": [ 760 | "src/" 761 | ] 762 | }, 763 | "notification-url": "https://packagist.org/downloads/", 764 | "license": [ 765 | "BSD-3-Clause" 766 | ], 767 | "authors": [ 768 | { 769 | "name": "Sebastian Bergmann", 770 | "email": "sebastian@phpunit.de", 771 | "role": "lead" 772 | } 773 | ], 774 | "description": "Simple template engine.", 775 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 776 | "keywords": [ 777 | "template" 778 | ], 779 | "support": { 780 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 781 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 782 | }, 783 | "funding": [ 784 | { 785 | "url": "https://github.com/sebastianbergmann", 786 | "type": "github" 787 | } 788 | ], 789 | "time": "2020-10-26T05:33:50+00:00" 790 | }, 791 | { 792 | "name": "phpunit/php-timer", 793 | "version": "5.0.3", 794 | "source": { 795 | "type": "git", 796 | "url": "https://github.com/sebastianbergmann/php-timer.git", 797 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 798 | }, 799 | "dist": { 800 | "type": "zip", 801 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 802 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 803 | "shasum": "" 804 | }, 805 | "require": { 806 | "php": ">=7.3" 807 | }, 808 | "require-dev": { 809 | "phpunit/phpunit": "^9.3" 810 | }, 811 | "type": "library", 812 | "extra": { 813 | "branch-alias": { 814 | "dev-master": "5.0-dev" 815 | } 816 | }, 817 | "autoload": { 818 | "classmap": [ 819 | "src/" 820 | ] 821 | }, 822 | "notification-url": "https://packagist.org/downloads/", 823 | "license": [ 824 | "BSD-3-Clause" 825 | ], 826 | "authors": [ 827 | { 828 | "name": "Sebastian Bergmann", 829 | "email": "sebastian@phpunit.de", 830 | "role": "lead" 831 | } 832 | ], 833 | "description": "Utility class for timing", 834 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 835 | "keywords": [ 836 | "timer" 837 | ], 838 | "support": { 839 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 840 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 841 | }, 842 | "funding": [ 843 | { 844 | "url": "https://github.com/sebastianbergmann", 845 | "type": "github" 846 | } 847 | ], 848 | "time": "2020-10-26T13:16:10+00:00" 849 | }, 850 | { 851 | "name": "phpunit/phpunit", 852 | "version": "9.5.21", 853 | "source": { 854 | "type": "git", 855 | "url": "https://github.com/sebastianbergmann/phpunit.git", 856 | "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" 857 | }, 858 | "dist": { 859 | "type": "zip", 860 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", 861 | "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", 862 | "shasum": "" 863 | }, 864 | "require": { 865 | "doctrine/instantiator": "^1.3.1", 866 | "ext-dom": "*", 867 | "ext-json": "*", 868 | "ext-libxml": "*", 869 | "ext-mbstring": "*", 870 | "ext-xml": "*", 871 | "ext-xmlwriter": "*", 872 | "myclabs/deep-copy": "^1.10.1", 873 | "phar-io/manifest": "^2.0.3", 874 | "phar-io/version": "^3.0.2", 875 | "php": ">=7.3", 876 | "phpspec/prophecy": "^1.12.1", 877 | "phpunit/php-code-coverage": "^9.2.13", 878 | "phpunit/php-file-iterator": "^3.0.5", 879 | "phpunit/php-invoker": "^3.1.1", 880 | "phpunit/php-text-template": "^2.0.3", 881 | "phpunit/php-timer": "^5.0.2", 882 | "sebastian/cli-parser": "^1.0.1", 883 | "sebastian/code-unit": "^1.0.6", 884 | "sebastian/comparator": "^4.0.5", 885 | "sebastian/diff": "^4.0.3", 886 | "sebastian/environment": "^5.1.3", 887 | "sebastian/exporter": "^4.0.3", 888 | "sebastian/global-state": "^5.0.1", 889 | "sebastian/object-enumerator": "^4.0.3", 890 | "sebastian/resource-operations": "^3.0.3", 891 | "sebastian/type": "^3.0", 892 | "sebastian/version": "^3.0.2" 893 | }, 894 | "require-dev": { 895 | "phpspec/prophecy-phpunit": "^2.0.1" 896 | }, 897 | "suggest": { 898 | "ext-soap": "*", 899 | "ext-xdebug": "*" 900 | }, 901 | "bin": [ 902 | "phpunit" 903 | ], 904 | "type": "library", 905 | "extra": { 906 | "branch-alias": { 907 | "dev-master": "9.5-dev" 908 | } 909 | }, 910 | "autoload": { 911 | "files": [ 912 | "src/Framework/Assert/Functions.php" 913 | ], 914 | "classmap": [ 915 | "src/" 916 | ] 917 | }, 918 | "notification-url": "https://packagist.org/downloads/", 919 | "license": [ 920 | "BSD-3-Clause" 921 | ], 922 | "authors": [ 923 | { 924 | "name": "Sebastian Bergmann", 925 | "email": "sebastian@phpunit.de", 926 | "role": "lead" 927 | } 928 | ], 929 | "description": "The PHP Unit Testing framework.", 930 | "homepage": "https://phpunit.de/", 931 | "keywords": [ 932 | "phpunit", 933 | "testing", 934 | "xunit" 935 | ], 936 | "support": { 937 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 938 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" 939 | }, 940 | "funding": [ 941 | { 942 | "url": "https://phpunit.de/sponsors.html", 943 | "type": "custom" 944 | }, 945 | { 946 | "url": "https://github.com/sebastianbergmann", 947 | "type": "github" 948 | } 949 | ], 950 | "time": "2022-06-19T12:14:25+00:00" 951 | }, 952 | { 953 | "name": "sebastian/cli-parser", 954 | "version": "1.0.1", 955 | "source": { 956 | "type": "git", 957 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 958 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" 959 | }, 960 | "dist": { 961 | "type": "zip", 962 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", 963 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", 964 | "shasum": "" 965 | }, 966 | "require": { 967 | "php": ">=7.3" 968 | }, 969 | "require-dev": { 970 | "phpunit/phpunit": "^9.3" 971 | }, 972 | "type": "library", 973 | "extra": { 974 | "branch-alias": { 975 | "dev-master": "1.0-dev" 976 | } 977 | }, 978 | "autoload": { 979 | "classmap": [ 980 | "src/" 981 | ] 982 | }, 983 | "notification-url": "https://packagist.org/downloads/", 984 | "license": [ 985 | "BSD-3-Clause" 986 | ], 987 | "authors": [ 988 | { 989 | "name": "Sebastian Bergmann", 990 | "email": "sebastian@phpunit.de", 991 | "role": "lead" 992 | } 993 | ], 994 | "description": "Library for parsing CLI options", 995 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 996 | "support": { 997 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 998 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" 999 | }, 1000 | "funding": [ 1001 | { 1002 | "url": "https://github.com/sebastianbergmann", 1003 | "type": "github" 1004 | } 1005 | ], 1006 | "time": "2020-09-28T06:08:49+00:00" 1007 | }, 1008 | { 1009 | "name": "sebastian/code-unit", 1010 | "version": "1.0.8", 1011 | "source": { 1012 | "type": "git", 1013 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1014 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1015 | }, 1016 | "dist": { 1017 | "type": "zip", 1018 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1019 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1020 | "shasum": "" 1021 | }, 1022 | "require": { 1023 | "php": ">=7.3" 1024 | }, 1025 | "require-dev": { 1026 | "phpunit/phpunit": "^9.3" 1027 | }, 1028 | "type": "library", 1029 | "extra": { 1030 | "branch-alias": { 1031 | "dev-master": "1.0-dev" 1032 | } 1033 | }, 1034 | "autoload": { 1035 | "classmap": [ 1036 | "src/" 1037 | ] 1038 | }, 1039 | "notification-url": "https://packagist.org/downloads/", 1040 | "license": [ 1041 | "BSD-3-Clause" 1042 | ], 1043 | "authors": [ 1044 | { 1045 | "name": "Sebastian Bergmann", 1046 | "email": "sebastian@phpunit.de", 1047 | "role": "lead" 1048 | } 1049 | ], 1050 | "description": "Collection of value objects that represent the PHP code units", 1051 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1052 | "support": { 1053 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1054 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1055 | }, 1056 | "funding": [ 1057 | { 1058 | "url": "https://github.com/sebastianbergmann", 1059 | "type": "github" 1060 | } 1061 | ], 1062 | "time": "2020-10-26T13:08:54+00:00" 1063 | }, 1064 | { 1065 | "name": "sebastian/code-unit-reverse-lookup", 1066 | "version": "2.0.3", 1067 | "source": { 1068 | "type": "git", 1069 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1070 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1071 | }, 1072 | "dist": { 1073 | "type": "zip", 1074 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1075 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1076 | "shasum": "" 1077 | }, 1078 | "require": { 1079 | "php": ">=7.3" 1080 | }, 1081 | "require-dev": { 1082 | "phpunit/phpunit": "^9.3" 1083 | }, 1084 | "type": "library", 1085 | "extra": { 1086 | "branch-alias": { 1087 | "dev-master": "2.0-dev" 1088 | } 1089 | }, 1090 | "autoload": { 1091 | "classmap": [ 1092 | "src/" 1093 | ] 1094 | }, 1095 | "notification-url": "https://packagist.org/downloads/", 1096 | "license": [ 1097 | "BSD-3-Clause" 1098 | ], 1099 | "authors": [ 1100 | { 1101 | "name": "Sebastian Bergmann", 1102 | "email": "sebastian@phpunit.de" 1103 | } 1104 | ], 1105 | "description": "Looks up which function or method a line of code belongs to", 1106 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1107 | "support": { 1108 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1109 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1110 | }, 1111 | "funding": [ 1112 | { 1113 | "url": "https://github.com/sebastianbergmann", 1114 | "type": "github" 1115 | } 1116 | ], 1117 | "time": "2020-09-28T05:30:19+00:00" 1118 | }, 1119 | { 1120 | "name": "sebastian/comparator", 1121 | "version": "4.0.6", 1122 | "source": { 1123 | "type": "git", 1124 | "url": "https://github.com/sebastianbergmann/comparator.git", 1125 | "reference": "55f4261989e546dc112258c7a75935a81a7ce382" 1126 | }, 1127 | "dist": { 1128 | "type": "zip", 1129 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", 1130 | "reference": "55f4261989e546dc112258c7a75935a81a7ce382", 1131 | "shasum": "" 1132 | }, 1133 | "require": { 1134 | "php": ">=7.3", 1135 | "sebastian/diff": "^4.0", 1136 | "sebastian/exporter": "^4.0" 1137 | }, 1138 | "require-dev": { 1139 | "phpunit/phpunit": "^9.3" 1140 | }, 1141 | "type": "library", 1142 | "extra": { 1143 | "branch-alias": { 1144 | "dev-master": "4.0-dev" 1145 | } 1146 | }, 1147 | "autoload": { 1148 | "classmap": [ 1149 | "src/" 1150 | ] 1151 | }, 1152 | "notification-url": "https://packagist.org/downloads/", 1153 | "license": [ 1154 | "BSD-3-Clause" 1155 | ], 1156 | "authors": [ 1157 | { 1158 | "name": "Sebastian Bergmann", 1159 | "email": "sebastian@phpunit.de" 1160 | }, 1161 | { 1162 | "name": "Jeff Welch", 1163 | "email": "whatthejeff@gmail.com" 1164 | }, 1165 | { 1166 | "name": "Volker Dusch", 1167 | "email": "github@wallbash.com" 1168 | }, 1169 | { 1170 | "name": "Bernhard Schussek", 1171 | "email": "bschussek@2bepublished.at" 1172 | } 1173 | ], 1174 | "description": "Provides the functionality to compare PHP values for equality", 1175 | "homepage": "https://github.com/sebastianbergmann/comparator", 1176 | "keywords": [ 1177 | "comparator", 1178 | "compare", 1179 | "equality" 1180 | ], 1181 | "support": { 1182 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1183 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" 1184 | }, 1185 | "funding": [ 1186 | { 1187 | "url": "https://github.com/sebastianbergmann", 1188 | "type": "github" 1189 | } 1190 | ], 1191 | "time": "2020-10-26T15:49:45+00:00" 1192 | }, 1193 | { 1194 | "name": "sebastian/complexity", 1195 | "version": "2.0.2", 1196 | "source": { 1197 | "type": "git", 1198 | "url": "https://github.com/sebastianbergmann/complexity.git", 1199 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" 1200 | }, 1201 | "dist": { 1202 | "type": "zip", 1203 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", 1204 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", 1205 | "shasum": "" 1206 | }, 1207 | "require": { 1208 | "nikic/php-parser": "^4.7", 1209 | "php": ">=7.3" 1210 | }, 1211 | "require-dev": { 1212 | "phpunit/phpunit": "^9.3" 1213 | }, 1214 | "type": "library", 1215 | "extra": { 1216 | "branch-alias": { 1217 | "dev-master": "2.0-dev" 1218 | } 1219 | }, 1220 | "autoload": { 1221 | "classmap": [ 1222 | "src/" 1223 | ] 1224 | }, 1225 | "notification-url": "https://packagist.org/downloads/", 1226 | "license": [ 1227 | "BSD-3-Clause" 1228 | ], 1229 | "authors": [ 1230 | { 1231 | "name": "Sebastian Bergmann", 1232 | "email": "sebastian@phpunit.de", 1233 | "role": "lead" 1234 | } 1235 | ], 1236 | "description": "Library for calculating the complexity of PHP code units", 1237 | "homepage": "https://github.com/sebastianbergmann/complexity", 1238 | "support": { 1239 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1240 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" 1241 | }, 1242 | "funding": [ 1243 | { 1244 | "url": "https://github.com/sebastianbergmann", 1245 | "type": "github" 1246 | } 1247 | ], 1248 | "time": "2020-10-26T15:52:27+00:00" 1249 | }, 1250 | { 1251 | "name": "sebastian/diff", 1252 | "version": "4.0.4", 1253 | "source": { 1254 | "type": "git", 1255 | "url": "https://github.com/sebastianbergmann/diff.git", 1256 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" 1257 | }, 1258 | "dist": { 1259 | "type": "zip", 1260 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", 1261 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", 1262 | "shasum": "" 1263 | }, 1264 | "require": { 1265 | "php": ">=7.3" 1266 | }, 1267 | "require-dev": { 1268 | "phpunit/phpunit": "^9.3", 1269 | "symfony/process": "^4.2 || ^5" 1270 | }, 1271 | "type": "library", 1272 | "extra": { 1273 | "branch-alias": { 1274 | "dev-master": "4.0-dev" 1275 | } 1276 | }, 1277 | "autoload": { 1278 | "classmap": [ 1279 | "src/" 1280 | ] 1281 | }, 1282 | "notification-url": "https://packagist.org/downloads/", 1283 | "license": [ 1284 | "BSD-3-Clause" 1285 | ], 1286 | "authors": [ 1287 | { 1288 | "name": "Sebastian Bergmann", 1289 | "email": "sebastian@phpunit.de" 1290 | }, 1291 | { 1292 | "name": "Kore Nordmann", 1293 | "email": "mail@kore-nordmann.de" 1294 | } 1295 | ], 1296 | "description": "Diff implementation", 1297 | "homepage": "https://github.com/sebastianbergmann/diff", 1298 | "keywords": [ 1299 | "diff", 1300 | "udiff", 1301 | "unidiff", 1302 | "unified diff" 1303 | ], 1304 | "support": { 1305 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1306 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" 1307 | }, 1308 | "funding": [ 1309 | { 1310 | "url": "https://github.com/sebastianbergmann", 1311 | "type": "github" 1312 | } 1313 | ], 1314 | "time": "2020-10-26T13:10:38+00:00" 1315 | }, 1316 | { 1317 | "name": "sebastian/environment", 1318 | "version": "5.1.4", 1319 | "source": { 1320 | "type": "git", 1321 | "url": "https://github.com/sebastianbergmann/environment.git", 1322 | "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" 1323 | }, 1324 | "dist": { 1325 | "type": "zip", 1326 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", 1327 | "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", 1328 | "shasum": "" 1329 | }, 1330 | "require": { 1331 | "php": ">=7.3" 1332 | }, 1333 | "require-dev": { 1334 | "phpunit/phpunit": "^9.3" 1335 | }, 1336 | "suggest": { 1337 | "ext-posix": "*" 1338 | }, 1339 | "type": "library", 1340 | "extra": { 1341 | "branch-alias": { 1342 | "dev-master": "5.1-dev" 1343 | } 1344 | }, 1345 | "autoload": { 1346 | "classmap": [ 1347 | "src/" 1348 | ] 1349 | }, 1350 | "notification-url": "https://packagist.org/downloads/", 1351 | "license": [ 1352 | "BSD-3-Clause" 1353 | ], 1354 | "authors": [ 1355 | { 1356 | "name": "Sebastian Bergmann", 1357 | "email": "sebastian@phpunit.de" 1358 | } 1359 | ], 1360 | "description": "Provides functionality to handle HHVM/PHP environments", 1361 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1362 | "keywords": [ 1363 | "Xdebug", 1364 | "environment", 1365 | "hhvm" 1366 | ], 1367 | "support": { 1368 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1369 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" 1370 | }, 1371 | "funding": [ 1372 | { 1373 | "url": "https://github.com/sebastianbergmann", 1374 | "type": "github" 1375 | } 1376 | ], 1377 | "time": "2022-04-03T09:37:03+00:00" 1378 | }, 1379 | { 1380 | "name": "sebastian/exporter", 1381 | "version": "4.0.4", 1382 | "source": { 1383 | "type": "git", 1384 | "url": "https://github.com/sebastianbergmann/exporter.git", 1385 | "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" 1386 | }, 1387 | "dist": { 1388 | "type": "zip", 1389 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", 1390 | "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", 1391 | "shasum": "" 1392 | }, 1393 | "require": { 1394 | "php": ">=7.3", 1395 | "sebastian/recursion-context": "^4.0" 1396 | }, 1397 | "require-dev": { 1398 | "ext-mbstring": "*", 1399 | "phpunit/phpunit": "^9.3" 1400 | }, 1401 | "type": "library", 1402 | "extra": { 1403 | "branch-alias": { 1404 | "dev-master": "4.0-dev" 1405 | } 1406 | }, 1407 | "autoload": { 1408 | "classmap": [ 1409 | "src/" 1410 | ] 1411 | }, 1412 | "notification-url": "https://packagist.org/downloads/", 1413 | "license": [ 1414 | "BSD-3-Clause" 1415 | ], 1416 | "authors": [ 1417 | { 1418 | "name": "Sebastian Bergmann", 1419 | "email": "sebastian@phpunit.de" 1420 | }, 1421 | { 1422 | "name": "Jeff Welch", 1423 | "email": "whatthejeff@gmail.com" 1424 | }, 1425 | { 1426 | "name": "Volker Dusch", 1427 | "email": "github@wallbash.com" 1428 | }, 1429 | { 1430 | "name": "Adam Harvey", 1431 | "email": "aharvey@php.net" 1432 | }, 1433 | { 1434 | "name": "Bernhard Schussek", 1435 | "email": "bschussek@gmail.com" 1436 | } 1437 | ], 1438 | "description": "Provides the functionality to export PHP variables for visualization", 1439 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1440 | "keywords": [ 1441 | "export", 1442 | "exporter" 1443 | ], 1444 | "support": { 1445 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1446 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" 1447 | }, 1448 | "funding": [ 1449 | { 1450 | "url": "https://github.com/sebastianbergmann", 1451 | "type": "github" 1452 | } 1453 | ], 1454 | "time": "2021-11-11T14:18:36+00:00" 1455 | }, 1456 | { 1457 | "name": "sebastian/global-state", 1458 | "version": "5.0.5", 1459 | "source": { 1460 | "type": "git", 1461 | "url": "https://github.com/sebastianbergmann/global-state.git", 1462 | "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" 1463 | }, 1464 | "dist": { 1465 | "type": "zip", 1466 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", 1467 | "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", 1468 | "shasum": "" 1469 | }, 1470 | "require": { 1471 | "php": ">=7.3", 1472 | "sebastian/object-reflector": "^2.0", 1473 | "sebastian/recursion-context": "^4.0" 1474 | }, 1475 | "require-dev": { 1476 | "ext-dom": "*", 1477 | "phpunit/phpunit": "^9.3" 1478 | }, 1479 | "suggest": { 1480 | "ext-uopz": "*" 1481 | }, 1482 | "type": "library", 1483 | "extra": { 1484 | "branch-alias": { 1485 | "dev-master": "5.0-dev" 1486 | } 1487 | }, 1488 | "autoload": { 1489 | "classmap": [ 1490 | "src/" 1491 | ] 1492 | }, 1493 | "notification-url": "https://packagist.org/downloads/", 1494 | "license": [ 1495 | "BSD-3-Clause" 1496 | ], 1497 | "authors": [ 1498 | { 1499 | "name": "Sebastian Bergmann", 1500 | "email": "sebastian@phpunit.de" 1501 | } 1502 | ], 1503 | "description": "Snapshotting of global state", 1504 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1505 | "keywords": [ 1506 | "global state" 1507 | ], 1508 | "support": { 1509 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1510 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" 1511 | }, 1512 | "funding": [ 1513 | { 1514 | "url": "https://github.com/sebastianbergmann", 1515 | "type": "github" 1516 | } 1517 | ], 1518 | "time": "2022-02-14T08:28:10+00:00" 1519 | }, 1520 | { 1521 | "name": "sebastian/lines-of-code", 1522 | "version": "1.0.3", 1523 | "source": { 1524 | "type": "git", 1525 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1526 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" 1527 | }, 1528 | "dist": { 1529 | "type": "zip", 1530 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1531 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1532 | "shasum": "" 1533 | }, 1534 | "require": { 1535 | "nikic/php-parser": "^4.6", 1536 | "php": ">=7.3" 1537 | }, 1538 | "require-dev": { 1539 | "phpunit/phpunit": "^9.3" 1540 | }, 1541 | "type": "library", 1542 | "extra": { 1543 | "branch-alias": { 1544 | "dev-master": "1.0-dev" 1545 | } 1546 | }, 1547 | "autoload": { 1548 | "classmap": [ 1549 | "src/" 1550 | ] 1551 | }, 1552 | "notification-url": "https://packagist.org/downloads/", 1553 | "license": [ 1554 | "BSD-3-Clause" 1555 | ], 1556 | "authors": [ 1557 | { 1558 | "name": "Sebastian Bergmann", 1559 | "email": "sebastian@phpunit.de", 1560 | "role": "lead" 1561 | } 1562 | ], 1563 | "description": "Library for counting the lines of code in PHP source code", 1564 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1565 | "support": { 1566 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1567 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" 1568 | }, 1569 | "funding": [ 1570 | { 1571 | "url": "https://github.com/sebastianbergmann", 1572 | "type": "github" 1573 | } 1574 | ], 1575 | "time": "2020-11-28T06:42:11+00:00" 1576 | }, 1577 | { 1578 | "name": "sebastian/object-enumerator", 1579 | "version": "4.0.4", 1580 | "source": { 1581 | "type": "git", 1582 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1583 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1584 | }, 1585 | "dist": { 1586 | "type": "zip", 1587 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1588 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1589 | "shasum": "" 1590 | }, 1591 | "require": { 1592 | "php": ">=7.3", 1593 | "sebastian/object-reflector": "^2.0", 1594 | "sebastian/recursion-context": "^4.0" 1595 | }, 1596 | "require-dev": { 1597 | "phpunit/phpunit": "^9.3" 1598 | }, 1599 | "type": "library", 1600 | "extra": { 1601 | "branch-alias": { 1602 | "dev-master": "4.0-dev" 1603 | } 1604 | }, 1605 | "autoload": { 1606 | "classmap": [ 1607 | "src/" 1608 | ] 1609 | }, 1610 | "notification-url": "https://packagist.org/downloads/", 1611 | "license": [ 1612 | "BSD-3-Clause" 1613 | ], 1614 | "authors": [ 1615 | { 1616 | "name": "Sebastian Bergmann", 1617 | "email": "sebastian@phpunit.de" 1618 | } 1619 | ], 1620 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1621 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1622 | "support": { 1623 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1624 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1625 | }, 1626 | "funding": [ 1627 | { 1628 | "url": "https://github.com/sebastianbergmann", 1629 | "type": "github" 1630 | } 1631 | ], 1632 | "time": "2020-10-26T13:12:34+00:00" 1633 | }, 1634 | { 1635 | "name": "sebastian/object-reflector", 1636 | "version": "2.0.4", 1637 | "source": { 1638 | "type": "git", 1639 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1640 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 1641 | }, 1642 | "dist": { 1643 | "type": "zip", 1644 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1645 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1646 | "shasum": "" 1647 | }, 1648 | "require": { 1649 | "php": ">=7.3" 1650 | }, 1651 | "require-dev": { 1652 | "phpunit/phpunit": "^9.3" 1653 | }, 1654 | "type": "library", 1655 | "extra": { 1656 | "branch-alias": { 1657 | "dev-master": "2.0-dev" 1658 | } 1659 | }, 1660 | "autoload": { 1661 | "classmap": [ 1662 | "src/" 1663 | ] 1664 | }, 1665 | "notification-url": "https://packagist.org/downloads/", 1666 | "license": [ 1667 | "BSD-3-Clause" 1668 | ], 1669 | "authors": [ 1670 | { 1671 | "name": "Sebastian Bergmann", 1672 | "email": "sebastian@phpunit.de" 1673 | } 1674 | ], 1675 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1676 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1677 | "support": { 1678 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1679 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 1680 | }, 1681 | "funding": [ 1682 | { 1683 | "url": "https://github.com/sebastianbergmann", 1684 | "type": "github" 1685 | } 1686 | ], 1687 | "time": "2020-10-26T13:14:26+00:00" 1688 | }, 1689 | { 1690 | "name": "sebastian/recursion-context", 1691 | "version": "4.0.4", 1692 | "source": { 1693 | "type": "git", 1694 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1695 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" 1696 | }, 1697 | "dist": { 1698 | "type": "zip", 1699 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", 1700 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", 1701 | "shasum": "" 1702 | }, 1703 | "require": { 1704 | "php": ">=7.3" 1705 | }, 1706 | "require-dev": { 1707 | "phpunit/phpunit": "^9.3" 1708 | }, 1709 | "type": "library", 1710 | "extra": { 1711 | "branch-alias": { 1712 | "dev-master": "4.0-dev" 1713 | } 1714 | }, 1715 | "autoload": { 1716 | "classmap": [ 1717 | "src/" 1718 | ] 1719 | }, 1720 | "notification-url": "https://packagist.org/downloads/", 1721 | "license": [ 1722 | "BSD-3-Clause" 1723 | ], 1724 | "authors": [ 1725 | { 1726 | "name": "Sebastian Bergmann", 1727 | "email": "sebastian@phpunit.de" 1728 | }, 1729 | { 1730 | "name": "Jeff Welch", 1731 | "email": "whatthejeff@gmail.com" 1732 | }, 1733 | { 1734 | "name": "Adam Harvey", 1735 | "email": "aharvey@php.net" 1736 | } 1737 | ], 1738 | "description": "Provides functionality to recursively process PHP variables", 1739 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1740 | "support": { 1741 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1742 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" 1743 | }, 1744 | "funding": [ 1745 | { 1746 | "url": "https://github.com/sebastianbergmann", 1747 | "type": "github" 1748 | } 1749 | ], 1750 | "time": "2020-10-26T13:17:30+00:00" 1751 | }, 1752 | { 1753 | "name": "sebastian/resource-operations", 1754 | "version": "3.0.3", 1755 | "source": { 1756 | "type": "git", 1757 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1758 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 1759 | }, 1760 | "dist": { 1761 | "type": "zip", 1762 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1763 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1764 | "shasum": "" 1765 | }, 1766 | "require": { 1767 | "php": ">=7.3" 1768 | }, 1769 | "require-dev": { 1770 | "phpunit/phpunit": "^9.0" 1771 | }, 1772 | "type": "library", 1773 | "extra": { 1774 | "branch-alias": { 1775 | "dev-master": "3.0-dev" 1776 | } 1777 | }, 1778 | "autoload": { 1779 | "classmap": [ 1780 | "src/" 1781 | ] 1782 | }, 1783 | "notification-url": "https://packagist.org/downloads/", 1784 | "license": [ 1785 | "BSD-3-Clause" 1786 | ], 1787 | "authors": [ 1788 | { 1789 | "name": "Sebastian Bergmann", 1790 | "email": "sebastian@phpunit.de" 1791 | } 1792 | ], 1793 | "description": "Provides a list of PHP built-in functions that operate on resources", 1794 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1795 | "support": { 1796 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 1797 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" 1798 | }, 1799 | "funding": [ 1800 | { 1801 | "url": "https://github.com/sebastianbergmann", 1802 | "type": "github" 1803 | } 1804 | ], 1805 | "time": "2020-09-28T06:45:17+00:00" 1806 | }, 1807 | { 1808 | "name": "sebastian/type", 1809 | "version": "3.0.0", 1810 | "source": { 1811 | "type": "git", 1812 | "url": "https://github.com/sebastianbergmann/type.git", 1813 | "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" 1814 | }, 1815 | "dist": { 1816 | "type": "zip", 1817 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", 1818 | "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", 1819 | "shasum": "" 1820 | }, 1821 | "require": { 1822 | "php": ">=7.3" 1823 | }, 1824 | "require-dev": { 1825 | "phpunit/phpunit": "^9.5" 1826 | }, 1827 | "type": "library", 1828 | "extra": { 1829 | "branch-alias": { 1830 | "dev-master": "3.0-dev" 1831 | } 1832 | }, 1833 | "autoload": { 1834 | "classmap": [ 1835 | "src/" 1836 | ] 1837 | }, 1838 | "notification-url": "https://packagist.org/downloads/", 1839 | "license": [ 1840 | "BSD-3-Clause" 1841 | ], 1842 | "authors": [ 1843 | { 1844 | "name": "Sebastian Bergmann", 1845 | "email": "sebastian@phpunit.de", 1846 | "role": "lead" 1847 | } 1848 | ], 1849 | "description": "Collection of value objects that represent the types of the PHP type system", 1850 | "homepage": "https://github.com/sebastianbergmann/type", 1851 | "support": { 1852 | "issues": "https://github.com/sebastianbergmann/type/issues", 1853 | "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" 1854 | }, 1855 | "funding": [ 1856 | { 1857 | "url": "https://github.com/sebastianbergmann", 1858 | "type": "github" 1859 | } 1860 | ], 1861 | "time": "2022-03-15T09:54:48+00:00" 1862 | }, 1863 | { 1864 | "name": "sebastian/version", 1865 | "version": "3.0.2", 1866 | "source": { 1867 | "type": "git", 1868 | "url": "https://github.com/sebastianbergmann/version.git", 1869 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 1870 | }, 1871 | "dist": { 1872 | "type": "zip", 1873 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 1874 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 1875 | "shasum": "" 1876 | }, 1877 | "require": { 1878 | "php": ">=7.3" 1879 | }, 1880 | "type": "library", 1881 | "extra": { 1882 | "branch-alias": { 1883 | "dev-master": "3.0-dev" 1884 | } 1885 | }, 1886 | "autoload": { 1887 | "classmap": [ 1888 | "src/" 1889 | ] 1890 | }, 1891 | "notification-url": "https://packagist.org/downloads/", 1892 | "license": [ 1893 | "BSD-3-Clause" 1894 | ], 1895 | "authors": [ 1896 | { 1897 | "name": "Sebastian Bergmann", 1898 | "email": "sebastian@phpunit.de", 1899 | "role": "lead" 1900 | } 1901 | ], 1902 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1903 | "homepage": "https://github.com/sebastianbergmann/version", 1904 | "support": { 1905 | "issues": "https://github.com/sebastianbergmann/version/issues", 1906 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 1907 | }, 1908 | "funding": [ 1909 | { 1910 | "url": "https://github.com/sebastianbergmann", 1911 | "type": "github" 1912 | } 1913 | ], 1914 | "time": "2020-09-28T06:39:44+00:00" 1915 | }, 1916 | { 1917 | "name": "theseer/tokenizer", 1918 | "version": "1.2.1", 1919 | "source": { 1920 | "type": "git", 1921 | "url": "https://github.com/theseer/tokenizer.git", 1922 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" 1923 | }, 1924 | "dist": { 1925 | "type": "zip", 1926 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", 1927 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", 1928 | "shasum": "" 1929 | }, 1930 | "require": { 1931 | "ext-dom": "*", 1932 | "ext-tokenizer": "*", 1933 | "ext-xmlwriter": "*", 1934 | "php": "^7.2 || ^8.0" 1935 | }, 1936 | "type": "library", 1937 | "autoload": { 1938 | "classmap": [ 1939 | "src/" 1940 | ] 1941 | }, 1942 | "notification-url": "https://packagist.org/downloads/", 1943 | "license": [ 1944 | "BSD-3-Clause" 1945 | ], 1946 | "authors": [ 1947 | { 1948 | "name": "Arne Blankerts", 1949 | "email": "arne@blankerts.de", 1950 | "role": "Developer" 1951 | } 1952 | ], 1953 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1954 | "support": { 1955 | "issues": "https://github.com/theseer/tokenizer/issues", 1956 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1" 1957 | }, 1958 | "funding": [ 1959 | { 1960 | "url": "https://github.com/theseer", 1961 | "type": "github" 1962 | } 1963 | ], 1964 | "time": "2021-07-28T10:34:58+00:00" 1965 | }, 1966 | { 1967 | "name": "webmozart/assert", 1968 | "version": "1.11.0", 1969 | "source": { 1970 | "type": "git", 1971 | "url": "https://github.com/webmozarts/assert.git", 1972 | "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" 1973 | }, 1974 | "dist": { 1975 | "type": "zip", 1976 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", 1977 | "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", 1978 | "shasum": "" 1979 | }, 1980 | "require": { 1981 | "ext-ctype": "*", 1982 | "php": "^7.2 || ^8.0" 1983 | }, 1984 | "conflict": { 1985 | "phpstan/phpstan": "<0.12.20", 1986 | "vimeo/psalm": "<4.6.1 || 4.6.2" 1987 | }, 1988 | "require-dev": { 1989 | "phpunit/phpunit": "^8.5.13" 1990 | }, 1991 | "type": "library", 1992 | "extra": { 1993 | "branch-alias": { 1994 | "dev-master": "1.10-dev" 1995 | } 1996 | }, 1997 | "autoload": { 1998 | "psr-4": { 1999 | "Webmozart\\Assert\\": "src/" 2000 | } 2001 | }, 2002 | "notification-url": "https://packagist.org/downloads/", 2003 | "license": [ 2004 | "MIT" 2005 | ], 2006 | "authors": [ 2007 | { 2008 | "name": "Bernhard Schussek", 2009 | "email": "bschussek@gmail.com" 2010 | } 2011 | ], 2012 | "description": "Assertions to validate method input/output with nice error messages.", 2013 | "keywords": [ 2014 | "assert", 2015 | "check", 2016 | "validate" 2017 | ], 2018 | "support": { 2019 | "issues": "https://github.com/webmozarts/assert/issues", 2020 | "source": "https://github.com/webmozarts/assert/tree/1.11.0" 2021 | }, 2022 | "time": "2022-06-03T18:03:27+00:00" 2023 | } 2024 | ], 2025 | "packages-dev": [], 2026 | "aliases": [], 2027 | "minimum-stability": "stable", 2028 | "stability-flags": [], 2029 | "prefer-stable": false, 2030 | "prefer-lowest": false, 2031 | "platform": [], 2032 | "platform-dev": [], 2033 | "plugin-api-version": "2.3.0" 2034 | } 2035 | -------------------------------------------------------------------------------- /ch12/design-patterns/src/DependencyInjection/ConstructorInjection.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 14 | } 15 | 16 | public function doSomething(): void 17 | { 18 | // Some action happens here 19 | 20 | // Let us log something 21 | $this->logger->log('Some action has been done'); 22 | } 23 | } 24 | 25 | $constructorInjection = new ConstructorInjection( 26 | new FileLogger() 27 | ); -------------------------------------------------------------------------------- /ch12/design-patterns/src/DependencyInjection/FileLogger.php: -------------------------------------------------------------------------------- 1 | logger = new FileLogger(); 14 | } 15 | 16 | public function doSomething(): void 17 | { 18 | // Some action happens here 19 | 20 | // Let us log something 21 | $this->logger->log('Some action has been done'); 22 | } 23 | } -------------------------------------------------------------------------------- /ch12/design-patterns/src/DependencyInjection/Logger.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 18 | } 19 | 20 | public function doSomething(): void 21 | { 22 | // Some action happens here 23 | 24 | // Let us log something 25 | $this->logger->log('Some action has been done'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch12/design-patterns/src/DependencyInjection/SetterInjectionFactory.php: -------------------------------------------------------------------------------- 1 | setLogger(new FileLogger()); 13 | 14 | return $setterInjection; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch12/design-patterns/src/FactoryMethod/AbstractWriter.php: -------------------------------------------------------------------------------- 1 | createEncoder(); 12 | 13 | // Apply some filtering which should always happen, 14 | // regardless of the output format. 15 | array_walk( 16 | $data, 17 | function (&$value) { 18 | $value = str_replace('data', '', $value); 19 | } 20 | ); 21 | 22 | // For demonstration purposes, we echo the result 23 | // here, instead of writing it into a file 24 | echo $encoder->encode($data); 25 | } 26 | 27 | abstract protected function createEncoder(): Encoder; 28 | } -------------------------------------------------------------------------------- /ch12/design-patterns/src/FactoryMethod/CsvEncoder.php: -------------------------------------------------------------------------------- 1 | write($exampleData); 17 | 18 | echo PHP_EOL; 19 | } 20 | 21 | echo "Output using the CsvWriter:" . PHP_EOL; 22 | 23 | factoryMethodExample(new CsvWriter()); 24 | 25 | echo "Output using the JsonWriter:" . PHP_EOL; 26 | 27 | factoryMethodExample(new JsonWriter()); -------------------------------------------------------------------------------- /ch12/design-patterns/src/FactoryMethod/JsonEncoder.php: -------------------------------------------------------------------------------- 1 | observers = new SplObjectStorage(); 20 | } 21 | 22 | public function attach(SplObserver $observer): void 23 | { 24 | $this->observers->attach($observer); 25 | } 26 | 27 | public function detach(SplObserver $observer): void 28 | { 29 | $this->observers->detach($observer); 30 | } 31 | 32 | public function notify(): void 33 | { 34 | foreach ($this->observers as $observer) { 35 | $observer->update($this); 36 | } 37 | } 38 | 39 | public function cancelSubscription(): void 40 | { 41 | // Required code for the actual cancellation 42 | // ... 43 | 44 | $this->notify(); 45 | } 46 | } -------------------------------------------------------------------------------- /ch12/design-patterns/src/Obvserver/CustomerAccountObserver.php: -------------------------------------------------------------------------------- 1 | mailService->sendEmail( 19 | 'sales@example.com', 20 | 'Account ' . $splSubject->id . ' has cancelled the subscription' 21 | ); 22 | } 23 | } -------------------------------------------------------------------------------- /ch12/design-patterns/src/Obvserver/MailService.php: -------------------------------------------------------------------------------- 1 | mailService->sendEmail( 21 | 'sales@example.com', 22 | 'Account ' . $this->id . ' has cancelled the subscription' 23 | ); 24 | } 25 | } -------------------------------------------------------------------------------- /ch12/design-patterns/src/Obvserver/bootstrap.php: -------------------------------------------------------------------------------- 1 | attach($customerAccountObserver); -------------------------------------------------------------------------------- /ch12/design-patterns/src/ServiceLocator/ServiceLocator.php: -------------------------------------------------------------------------------- 1 | serviceLocator->get(SomeService::class); 16 | $someService->doSomething(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch12/design-patterns/src/ServiceLocator/SomeService.php: -------------------------------------------------------------------------------- 1 | to write great PHP code?} --> B[No] 9 | A --> C[Yes] 10 | C --> E(Awesome!) 11 | B --> D{Did you read
Clean Code in PHP?} --> F[No] 12 | D --> G[Yes] 13 | G --> H(Please read it again) 14 | F --> I(Please read it) 15 | ``` -------------------------------------------------------------------------------- /ch13/openapi/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock -------------------------------------------------------------------------------- /ch13/openapi/README.md: -------------------------------------------------------------------------------- 1 | # OpenAPI example 2 | 3 | ## Installation 4 | 5 | Run `composer install` 6 | 7 | ## Create the API documentation 8 | 9 | 1. `vendor/bin/openapi src/Annotations -o openapi-annotations.yaml` to create the documentation using the Annotations example 10 | 2. `vendor/bin/openapi src/Attributes -o openapi-attributes.yaml` to create the documentation using the Attributes example 11 | 12 | ## Compare both YAML files 13 | 14 | To check for differences between both YAML files, you can use `git diff --no-index to compare files which are not tracked by git: 15 | 16 | `git diff --no-index openapi-annotations.yaml openapi-attributes.yaml` 17 | 18 | If all went fine, you should not get any difference reported. 19 | 20 | ## Swagger UI 21 | 22 | As quick example, pull the Swagger-UI from Docker Hub: 23 | 24 | `docker pull swaggerapi/swagger-ui` 25 | 26 | Since Swagger-UI required a JSON instead a YAML, create one first: 27 | 28 | `vendor/bin/openapi src/Attributes -o openapi-attributes.json` 29 | 30 | Then, run the container locally: 31 | 32 | ``` 33 | docker run -p 80:8080 -e SWAGGER_JSON=/foo/openapi-attributes.json -v `pwd`:/foo swaggerapi/swagger-ui 34 | ``` 35 | 36 | Now you can open http://localhost in your browser. -------------------------------------------------------------------------------- /ch13/openapi/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "autoload": { 3 | "psr-4": { 4 | "OpenApiExample\\":"src/" 5 | } 6 | }, 7 | "require": { 8 | "zircote/swagger-php": "^4.4" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch13/openapi/openapi-annotations.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: 'Product API' 4 | version: '0.1' 5 | paths: 6 | /product: 7 | get: 8 | operationId: getProducts 9 | parameters: 10 | - 11 | name: limit 12 | in: query 13 | description: 'How many products to return at one time' 14 | required: false 15 | schema: 16 | type: integer 17 | responses: 18 | '200': 19 | description: 'Returns the product data' 20 | -------------------------------------------------------------------------------- /ch13/openapi/openapi-attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "Product API", 5 | "version": "0.1" 6 | }, 7 | "paths": { 8 | "/product": { 9 | "get": { 10 | "operationId": "getProducts", 11 | "parameters": [ 12 | { 13 | "name": "limit", 14 | "in": "query", 15 | "description": "How many products to return at one time", 16 | "required": false, 17 | "schema": { 18 | "type": "integer" 19 | } 20 | } 21 | ], 22 | "responses": { 23 | "200": { 24 | "description": "Returns the product data" 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ch13/openapi/openapi-attributes.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: 'Product API' 4 | version: '0.1' 5 | paths: 6 | /product: 7 | get: 8 | operationId: getProducts 9 | parameters: 10 | - 11 | name: limit 12 | in: query 13 | description: 'How many products to return at one time' 14 | required: false 15 | schema: 16 | type: integer 17 | responses: 18 | '200': 19 | description: 'Returns the product data' 20 | -------------------------------------------------------------------------------- /ch13/openapi/src/Annotations/Controller/ProductController.php: -------------------------------------------------------------------------------- 1 |