├── .env.example ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── crook ├── composer.json ├── composer.lock ├── phpunit.xml ├── src └── crook │ ├── Application.php │ ├── Command │ ├── AddHook.php │ ├── InitHook.php │ └── RemoveHook.php │ ├── Config.php │ └── Hook.php ├── tests ├── crook │ ├── ApplicationTest.php │ ├── ConfigTest.php │ └── HookTest.php └── dumbCode │ ├── NonPsrCompliant.php │ └── PsrCompliant.php └── theHook /.env.example: -------------------------------------------------------------------------------- 1 | COMPOSER_BIN='composer' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | .idea 3 | .env 4 | /coverage/ 5 | clover 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '7.1' 4 | 5 | before_script: 6 | - composer install 7 | 8 | env: 9 | - COMPOSER_BIN=composer 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Felipe 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 | [![Build Status](https://travis-ci.org/felipebool/crook.svg?branch=master)](https://travis-ci.org/felipebool/crook) 2 | [![Maintainability](https://api.codeclimate.com/v1/badges/dda7bbc045a955530da4/maintainability)](https://codeclimate.com/github/felipebool/crook/maintainability) 3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2849859fd1ad4d299bf7403a85171319)](https://www.codacy.com/app/felipebool/crook?utm_source=github.com&utm_medium=referral&utm_content=felipebool/crook&utm_campaign=Badge_Grade) 4 | [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/2849859fd1ad4d299bf7403a85171319)](https://www.codacy.com/app/felipebool/crook?utm_source=github.com&utm_medium=referral&utm_content=felipebool/crook&utm_campaign=Badge_Coverage) 5 | 6 | # Crook 7 | First of all, Crook is a work in progress. 8 | 9 | If you are not familiar with git hooks, you may want to read [Git Hooks documentation](https://git-scm.com/docs/githooks) first. 10 | 11 | Crook is the simplest way to define and manage your Git Hooks. Its aim is to allow scripts from your composer.json run when git hook actions are triggered. 12 | 13 | ## Usage 14 | The aim of this project is to be as simple as possible, thus, you won't have to write any PHP code, you just need to install any packages from packagist and then make them run for partucular git hooks. The process is explained in the following sections. 15 | 16 | ### Installation 17 | Just run 18 | 19 | ```$ composer require felipebool/crook --dev``` 20 | 21 | ### Init Crook 22 | ```$ vendor/bin/crook init``` will create crook.json configuration file and theHook in the root of your project. 23 | 24 | ### Add a new hook 25 | ```$ vendor/bin/crook add hook-name action-name``` will create a symbolic link from .git/hooks/hook-name to theHook, enabling that hook. 26 | 27 | ### Remove a hook 28 | ```$ vendor/bin/crook remove hook-name``` will remove the symbolic link .git/hooks/hook-name, disabling that hook. 29 | 30 | ### Add a action to composer.json 31 | When you add a new action using ```add``` you need to add what is expected to run when that action is triggered inside you composer.json. To do that, you must create a new entry inside the section ```scripts``` and then define what must run there. 32 | 33 | ## Crook configuration file 34 | Crook uses a json configuration file just like composer, it is called crook.json. The configuration is made, basically, by writting as a key the git hook name and as value the respective script entry in composer.json. See the following example 35 | ```json 36 | { 37 | "pre-commit": "code-check", 38 | "composer": "/home/felipe/bin/composer" 39 | } 40 | ``` 41 | Although you are able to edit crook.json by yourself, you should do it using ```$ vendor/bin/crook``` in order to create the symbolic links. Only the composer path **must** be set manually. The mechanism is explained in the next section. 42 | 43 | ## The mechanism 44 | Every time you run a 45 | ```vendor/bin/crook add hook-name action-name``` 46 | Crook creates a symbolic link from .git/hooks/hook-name to /your/project/hook/theHook, simple as that. 47 | 48 | Now, when git trigger the action hook-name, it will follow the link to /your/project/hook/theHook and Crook will then look for a script named action-name inside your project's composer.json and will execute the commands defined there. 49 | 50 | ### Adding code validation using phpcs before any commit 51 | In order to check your code against PSR2, you must do this 52 | 53 | #### Add the script action inside composer.json 54 | ``` 55 | "scripts": { 56 | "code-check": "phpcs --standard=PSR2 src/", 57 | } 58 | ``` 59 | 60 | #### Initialize crook 61 | ```$ vendor/bin/crook init``` 62 | 63 | #### Bind code-check to pre-commit hook 64 | ```$ vendor/bin/crook add pre-commit code-check``` 65 | 66 | Next time you run ```$ git commit -m 'some message'``` crook will run the code defined inside code-check and will prevent code from being commited if the check fail. 67 | 68 | -------------------------------------------------------------------------------- /bin/crook: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 3 | add(new AddHook); 60 | $application->add(new RemoveHook); 61 | $application->add(new InitHook); 62 | 63 | try { 64 | $application->run(); 65 | } catch (\Exception $e) { 66 | echo $e->getMessage(); 67 | } 68 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "felipebool/crook", 3 | "description": "Crook is a simple tool to ease your life when dealing with git hooks", 4 | "type": "library", 5 | "keywords": [ 6 | "crook", 7 | "git", 8 | "hooks", 9 | "githook" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Felipe Lopes", 15 | "email": "bolzin@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "symfony/console": "^4.0|^5.0", 20 | "php": "^7.1" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "Crook\\": "src/crook" 25 | } 26 | }, 27 | "require-dev": { 28 | "squizlabs/php_codesniffer": "^3.2", 29 | "phpunit/phpunit": "^7.0", 30 | "vlucas/phpdotenv": "^2.4", 31 | "codacy/coverage": "^1.4" 32 | }, 33 | "scripts": { 34 | "code-check-non-psr2": "phpcs --standard=PSR2 tests/dumbCode/NonPsrCompliant.php", 35 | "code-check-psr2": "phpcs --standard=PSR2 tests/dumbCode/PsrCompliant.php", 36 | "phpunit": "phpunit --bootstrap vendor/autoload", 37 | "post-root-package-install": [ 38 | "@php -r \"copy('theHook', 'theHook');\"" 39 | ] 40 | }, 41 | "bin": [ 42 | "bin/crook" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "300e359a52ef9cc670f85431aa6ceb79", 8 | "packages": [ 9 | { 10 | "name": "psr/container", 11 | "version": "1.0.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/php-fig/container.git", 15 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 20 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "type": "library", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-master": "1.0.x-dev" 30 | } 31 | }, 32 | "autoload": { 33 | "psr-4": { 34 | "Psr\\Container\\": "src/" 35 | } 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "MIT" 40 | ], 41 | "authors": [ 42 | { 43 | "name": "PHP-FIG", 44 | "homepage": "http://www.php-fig.org/" 45 | } 46 | ], 47 | "description": "Common Container Interface (PHP FIG PSR-11)", 48 | "homepage": "https://github.com/php-fig/container", 49 | "keywords": [ 50 | "PSR-11", 51 | "container", 52 | "container-interface", 53 | "container-interop", 54 | "psr" 55 | ], 56 | "time": "2017-02-14T16:28:37+00:00" 57 | }, 58 | { 59 | "name": "symfony/console", 60 | "version": "v5.0.8", 61 | "source": { 62 | "type": "git", 63 | "url": "https://github.com/symfony/console.git", 64 | "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935" 65 | }, 66 | "dist": { 67 | "type": "zip", 68 | "url": "https://api.github.com/repos/symfony/console/zipball/5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", 69 | "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", 70 | "shasum": "" 71 | }, 72 | "require": { 73 | "php": "^7.2.5", 74 | "symfony/polyfill-mbstring": "~1.0", 75 | "symfony/polyfill-php73": "^1.8", 76 | "symfony/service-contracts": "^1.1|^2" 77 | }, 78 | "conflict": { 79 | "symfony/dependency-injection": "<4.4", 80 | "symfony/event-dispatcher": "<4.4", 81 | "symfony/lock": "<4.4", 82 | "symfony/process": "<4.4" 83 | }, 84 | "provide": { 85 | "psr/log-implementation": "1.0" 86 | }, 87 | "require-dev": { 88 | "psr/log": "~1.0", 89 | "symfony/config": "^4.4|^5.0", 90 | "symfony/dependency-injection": "^4.4|^5.0", 91 | "symfony/event-dispatcher": "^4.4|^5.0", 92 | "symfony/lock": "^4.4|^5.0", 93 | "symfony/process": "^4.4|^5.0", 94 | "symfony/var-dumper": "^4.4|^5.0" 95 | }, 96 | "suggest": { 97 | "psr/log": "For using the console logger", 98 | "symfony/event-dispatcher": "", 99 | "symfony/lock": "", 100 | "symfony/process": "" 101 | }, 102 | "type": "library", 103 | "extra": { 104 | "branch-alias": { 105 | "dev-master": "5.0-dev" 106 | } 107 | }, 108 | "autoload": { 109 | "psr-4": { 110 | "Symfony\\Component\\Console\\": "" 111 | }, 112 | "exclude-from-classmap": [ 113 | "/Tests/" 114 | ] 115 | }, 116 | "notification-url": "https://packagist.org/downloads/", 117 | "license": [ 118 | "MIT" 119 | ], 120 | "authors": [ 121 | { 122 | "name": "Fabien Potencier", 123 | "email": "fabien@symfony.com" 124 | }, 125 | { 126 | "name": "Symfony Community", 127 | "homepage": "https://symfony.com/contributors" 128 | } 129 | ], 130 | "description": "Symfony Console Component", 131 | "homepage": "https://symfony.com", 132 | "time": "2020-03-30T11:42:42+00:00" 133 | }, 134 | { 135 | "name": "symfony/polyfill-mbstring", 136 | "version": "v1.15.0", 137 | "source": { 138 | "type": "git", 139 | "url": "https://github.com/symfony/polyfill-mbstring.git", 140 | "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" 141 | }, 142 | "dist": { 143 | "type": "zip", 144 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", 145 | "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", 146 | "shasum": "" 147 | }, 148 | "require": { 149 | "php": ">=5.3.3" 150 | }, 151 | "suggest": { 152 | "ext-mbstring": "For best performance" 153 | }, 154 | "type": "library", 155 | "extra": { 156 | "branch-alias": { 157 | "dev-master": "1.15-dev" 158 | } 159 | }, 160 | "autoload": { 161 | "psr-4": { 162 | "Symfony\\Polyfill\\Mbstring\\": "" 163 | }, 164 | "files": [ 165 | "bootstrap.php" 166 | ] 167 | }, 168 | "notification-url": "https://packagist.org/downloads/", 169 | "license": [ 170 | "MIT" 171 | ], 172 | "authors": [ 173 | { 174 | "name": "Nicolas Grekas", 175 | "email": "p@tchwork.com" 176 | }, 177 | { 178 | "name": "Symfony Community", 179 | "homepage": "https://symfony.com/contributors" 180 | } 181 | ], 182 | "description": "Symfony polyfill for the Mbstring extension", 183 | "homepage": "https://symfony.com", 184 | "keywords": [ 185 | "compatibility", 186 | "mbstring", 187 | "polyfill", 188 | "portable", 189 | "shim" 190 | ], 191 | "time": "2020-03-09T19:04:49+00:00" 192 | }, 193 | { 194 | "name": "symfony/polyfill-php73", 195 | "version": "v1.15.0", 196 | "source": { 197 | "type": "git", 198 | "url": "https://github.com/symfony/polyfill-php73.git", 199 | "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" 200 | }, 201 | "dist": { 202 | "type": "zip", 203 | "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", 204 | "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", 205 | "shasum": "" 206 | }, 207 | "require": { 208 | "php": ">=5.3.3" 209 | }, 210 | "type": "library", 211 | "extra": { 212 | "branch-alias": { 213 | "dev-master": "1.15-dev" 214 | } 215 | }, 216 | "autoload": { 217 | "psr-4": { 218 | "Symfony\\Polyfill\\Php73\\": "" 219 | }, 220 | "files": [ 221 | "bootstrap.php" 222 | ], 223 | "classmap": [ 224 | "Resources/stubs" 225 | ] 226 | }, 227 | "notification-url": "https://packagist.org/downloads/", 228 | "license": [ 229 | "MIT" 230 | ], 231 | "authors": [ 232 | { 233 | "name": "Nicolas Grekas", 234 | "email": "p@tchwork.com" 235 | }, 236 | { 237 | "name": "Symfony Community", 238 | "homepage": "https://symfony.com/contributors" 239 | } 240 | ], 241 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", 242 | "homepage": "https://symfony.com", 243 | "keywords": [ 244 | "compatibility", 245 | "polyfill", 246 | "portable", 247 | "shim" 248 | ], 249 | "time": "2020-02-27T09:26:54+00:00" 250 | }, 251 | { 252 | "name": "symfony/service-contracts", 253 | "version": "v2.0.1", 254 | "source": { 255 | "type": "git", 256 | "url": "https://github.com/symfony/service-contracts.git", 257 | "reference": "144c5e51266b281231e947b51223ba14acf1a749" 258 | }, 259 | "dist": { 260 | "type": "zip", 261 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", 262 | "reference": "144c5e51266b281231e947b51223ba14acf1a749", 263 | "shasum": "" 264 | }, 265 | "require": { 266 | "php": "^7.2.5", 267 | "psr/container": "^1.0" 268 | }, 269 | "suggest": { 270 | "symfony/service-implementation": "" 271 | }, 272 | "type": "library", 273 | "extra": { 274 | "branch-alias": { 275 | "dev-master": "2.0-dev" 276 | } 277 | }, 278 | "autoload": { 279 | "psr-4": { 280 | "Symfony\\Contracts\\Service\\": "" 281 | } 282 | }, 283 | "notification-url": "https://packagist.org/downloads/", 284 | "license": [ 285 | "MIT" 286 | ], 287 | "authors": [ 288 | { 289 | "name": "Nicolas Grekas", 290 | "email": "p@tchwork.com" 291 | }, 292 | { 293 | "name": "Symfony Community", 294 | "homepage": "https://symfony.com/contributors" 295 | } 296 | ], 297 | "description": "Generic abstractions related to writing services", 298 | "homepage": "https://symfony.com", 299 | "keywords": [ 300 | "abstractions", 301 | "contracts", 302 | "decoupling", 303 | "interfaces", 304 | "interoperability", 305 | "standards" 306 | ], 307 | "time": "2019-11-18T17:27:11+00:00" 308 | } 309 | ], 310 | "packages-dev": [ 311 | { 312 | "name": "codacy/coverage", 313 | "version": "1.4.3", 314 | "source": { 315 | "type": "git", 316 | "url": "https://github.com/codacy/php-codacy-coverage.git", 317 | "reference": "1852ca987c91ef466ebcfdbdd4e1788b653eaf1d" 318 | }, 319 | "dist": { 320 | "type": "zip", 321 | "url": "https://api.github.com/repos/codacy/php-codacy-coverage/zipball/1852ca987c91ef466ebcfdbdd4e1788b653eaf1d", 322 | "reference": "1852ca987c91ef466ebcfdbdd4e1788b653eaf1d", 323 | "shasum": "" 324 | }, 325 | "require": { 326 | "gitonomy/gitlib": ">=1.0", 327 | "php": ">=5.3.3", 328 | "symfony/console": "~2.5|~3.0|~4.0|~5.0" 329 | }, 330 | "require-dev": { 331 | "clue/phar-composer": "^1.1", 332 | "phpunit/phpunit": "~6.5" 333 | }, 334 | "bin": [ 335 | "bin/codacycoverage" 336 | ], 337 | "type": "library", 338 | "autoload": { 339 | "classmap": [ 340 | "src/" 341 | ] 342 | }, 343 | "notification-url": "https://packagist.org/downloads/", 344 | "license": [ 345 | "MIT" 346 | ], 347 | "authors": [ 348 | { 349 | "name": "Jakob Pupke", 350 | "email": "jakob.pupke@gmail.com" 351 | } 352 | ], 353 | "description": "Sends PHP test coverage information to Codacy.", 354 | "homepage": "https://github.com/codacy/php-codacy-coverage", 355 | "abandoned": true, 356 | "time": "2020-01-10T10:52:12+00:00" 357 | }, 358 | { 359 | "name": "doctrine/instantiator", 360 | "version": "1.3.0", 361 | "source": { 362 | "type": "git", 363 | "url": "https://github.com/doctrine/instantiator.git", 364 | "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" 365 | }, 366 | "dist": { 367 | "type": "zip", 368 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", 369 | "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", 370 | "shasum": "" 371 | }, 372 | "require": { 373 | "php": "^7.1" 374 | }, 375 | "require-dev": { 376 | "doctrine/coding-standard": "^6.0", 377 | "ext-pdo": "*", 378 | "ext-phar": "*", 379 | "phpbench/phpbench": "^0.13", 380 | "phpstan/phpstan-phpunit": "^0.11", 381 | "phpstan/phpstan-shim": "^0.11", 382 | "phpunit/phpunit": "^7.0" 383 | }, 384 | "type": "library", 385 | "extra": { 386 | "branch-alias": { 387 | "dev-master": "1.2.x-dev" 388 | } 389 | }, 390 | "autoload": { 391 | "psr-4": { 392 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 393 | } 394 | }, 395 | "notification-url": "https://packagist.org/downloads/", 396 | "license": [ 397 | "MIT" 398 | ], 399 | "authors": [ 400 | { 401 | "name": "Marco Pivetta", 402 | "email": "ocramius@gmail.com", 403 | "homepage": "http://ocramius.github.com/" 404 | } 405 | ], 406 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 407 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 408 | "keywords": [ 409 | "constructor", 410 | "instantiate" 411 | ], 412 | "time": "2019-10-21T16:45:58+00:00" 413 | }, 414 | { 415 | "name": "gitonomy/gitlib", 416 | "version": "v1.2.1", 417 | "source": { 418 | "type": "git", 419 | "url": "https://github.com/gitonomy/gitlib.git", 420 | "reference": "718ca021c67f3ea8f6a5fa5d231ec49675068868" 421 | }, 422 | "dist": { 423 | "type": "zip", 424 | "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/718ca021c67f3ea8f6a5fa5d231ec49675068868", 425 | "reference": "718ca021c67f3ea8f6a5fa5d231ec49675068868", 426 | "shasum": "" 427 | }, 428 | "require": { 429 | "ext-pcre": "*", 430 | "php": "^5.6 || ^7.0", 431 | "symfony/polyfill-mbstring": "^1.7", 432 | "symfony/process": "^3.4|^4.0|^5.0" 433 | }, 434 | "require-dev": { 435 | "phpunit/phpunit": "^5.7|^6.5|^7.0", 436 | "psr/log": "^1.0" 437 | }, 438 | "suggest": { 439 | "ext-fileinfo": "Required to determine the mimetype of a blob", 440 | "psr/log": "Required to use loggers for reporting of execution" 441 | }, 442 | "type": "library", 443 | "extra": { 444 | "branch-alias": { 445 | "dev-master": "1.2-dev" 446 | } 447 | }, 448 | "autoload": { 449 | "psr-4": { 450 | "Gitonomy\\Git\\": "src/Gitonomy/Git/" 451 | } 452 | }, 453 | "notification-url": "https://packagist.org/downloads/", 454 | "license": [ 455 | "MIT" 456 | ], 457 | "authors": [ 458 | { 459 | "name": "Graham Campbell", 460 | "email": "graham@alt-three.com" 461 | }, 462 | { 463 | "name": "Julien Didier", 464 | "email": "genzo.wm@gmail.com" 465 | }, 466 | { 467 | "name": "Grégoire Pineau", 468 | "email": "lyrixx@lyrixx.info" 469 | }, 470 | { 471 | "name": "Alexandre Salomé", 472 | "email": "alexandre.salome@gmail.com" 473 | } 474 | ], 475 | "description": "Library for accessing git", 476 | "time": "2020-03-23T12:43:44+00:00" 477 | }, 478 | { 479 | "name": "myclabs/deep-copy", 480 | "version": "1.9.5", 481 | "source": { 482 | "type": "git", 483 | "url": "https://github.com/myclabs/DeepCopy.git", 484 | "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" 485 | }, 486 | "dist": { 487 | "type": "zip", 488 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", 489 | "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", 490 | "shasum": "" 491 | }, 492 | "require": { 493 | "php": "^7.1" 494 | }, 495 | "replace": { 496 | "myclabs/deep-copy": "self.version" 497 | }, 498 | "require-dev": { 499 | "doctrine/collections": "^1.0", 500 | "doctrine/common": "^2.6", 501 | "phpunit/phpunit": "^7.1" 502 | }, 503 | "type": "library", 504 | "autoload": { 505 | "psr-4": { 506 | "DeepCopy\\": "src/DeepCopy/" 507 | }, 508 | "files": [ 509 | "src/DeepCopy/deep_copy.php" 510 | ] 511 | }, 512 | "notification-url": "https://packagist.org/downloads/", 513 | "license": [ 514 | "MIT" 515 | ], 516 | "description": "Create deep copies (clones) of your objects", 517 | "keywords": [ 518 | "clone", 519 | "copy", 520 | "duplicate", 521 | "object", 522 | "object graph" 523 | ], 524 | "time": "2020-01-17T21:11:47+00:00" 525 | }, 526 | { 527 | "name": "phar-io/manifest", 528 | "version": "1.0.3", 529 | "source": { 530 | "type": "git", 531 | "url": "https://github.com/phar-io/manifest.git", 532 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" 533 | }, 534 | "dist": { 535 | "type": "zip", 536 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 537 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 538 | "shasum": "" 539 | }, 540 | "require": { 541 | "ext-dom": "*", 542 | "ext-phar": "*", 543 | "phar-io/version": "^2.0", 544 | "php": "^5.6 || ^7.0" 545 | }, 546 | "type": "library", 547 | "extra": { 548 | "branch-alias": { 549 | "dev-master": "1.0.x-dev" 550 | } 551 | }, 552 | "autoload": { 553 | "classmap": [ 554 | "src/" 555 | ] 556 | }, 557 | "notification-url": "https://packagist.org/downloads/", 558 | "license": [ 559 | "BSD-3-Clause" 560 | ], 561 | "authors": [ 562 | { 563 | "name": "Arne Blankerts", 564 | "email": "arne@blankerts.de", 565 | "role": "Developer" 566 | }, 567 | { 568 | "name": "Sebastian Heuer", 569 | "email": "sebastian@phpeople.de", 570 | "role": "Developer" 571 | }, 572 | { 573 | "name": "Sebastian Bergmann", 574 | "email": "sebastian@phpunit.de", 575 | "role": "Developer" 576 | } 577 | ], 578 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 579 | "time": "2018-07-08T19:23:20+00:00" 580 | }, 581 | { 582 | "name": "phar-io/version", 583 | "version": "2.0.1", 584 | "source": { 585 | "type": "git", 586 | "url": "https://github.com/phar-io/version.git", 587 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" 588 | }, 589 | "dist": { 590 | "type": "zip", 591 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", 592 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", 593 | "shasum": "" 594 | }, 595 | "require": { 596 | "php": "^5.6 || ^7.0" 597 | }, 598 | "type": "library", 599 | "autoload": { 600 | "classmap": [ 601 | "src/" 602 | ] 603 | }, 604 | "notification-url": "https://packagist.org/downloads/", 605 | "license": [ 606 | "BSD-3-Clause" 607 | ], 608 | "authors": [ 609 | { 610 | "name": "Arne Blankerts", 611 | "email": "arne@blankerts.de", 612 | "role": "Developer" 613 | }, 614 | { 615 | "name": "Sebastian Heuer", 616 | "email": "sebastian@phpeople.de", 617 | "role": "Developer" 618 | }, 619 | { 620 | "name": "Sebastian Bergmann", 621 | "email": "sebastian@phpunit.de", 622 | "role": "Developer" 623 | } 624 | ], 625 | "description": "Library for handling version information and constraints", 626 | "time": "2018-07-08T19:19:57+00:00" 627 | }, 628 | { 629 | "name": "phpdocumentor/reflection-common", 630 | "version": "2.1.0", 631 | "source": { 632 | "type": "git", 633 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 634 | "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" 635 | }, 636 | "dist": { 637 | "type": "zip", 638 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", 639 | "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", 640 | "shasum": "" 641 | }, 642 | "require": { 643 | "php": ">=7.1" 644 | }, 645 | "type": "library", 646 | "extra": { 647 | "branch-alias": { 648 | "dev-master": "2.x-dev" 649 | } 650 | }, 651 | "autoload": { 652 | "psr-4": { 653 | "phpDocumentor\\Reflection\\": "src/" 654 | } 655 | }, 656 | "notification-url": "https://packagist.org/downloads/", 657 | "license": [ 658 | "MIT" 659 | ], 660 | "authors": [ 661 | { 662 | "name": "Jaap van Otterdijk", 663 | "email": "opensource@ijaap.nl" 664 | } 665 | ], 666 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 667 | "homepage": "http://www.phpdoc.org", 668 | "keywords": [ 669 | "FQSEN", 670 | "phpDocumentor", 671 | "phpdoc", 672 | "reflection", 673 | "static analysis" 674 | ], 675 | "time": "2020-04-27T09:25:28+00:00" 676 | }, 677 | { 678 | "name": "phpdocumentor/reflection-docblock", 679 | "version": "5.1.0", 680 | "source": { 681 | "type": "git", 682 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 683 | "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" 684 | }, 685 | "dist": { 686 | "type": "zip", 687 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", 688 | "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", 689 | "shasum": "" 690 | }, 691 | "require": { 692 | "ext-filter": "^7.1", 693 | "php": "^7.2", 694 | "phpdocumentor/reflection-common": "^2.0", 695 | "phpdocumentor/type-resolver": "^1.0", 696 | "webmozart/assert": "^1" 697 | }, 698 | "require-dev": { 699 | "doctrine/instantiator": "^1", 700 | "mockery/mockery": "^1" 701 | }, 702 | "type": "library", 703 | "extra": { 704 | "branch-alias": { 705 | "dev-master": "5.x-dev" 706 | } 707 | }, 708 | "autoload": { 709 | "psr-4": { 710 | "phpDocumentor\\Reflection\\": "src" 711 | } 712 | }, 713 | "notification-url": "https://packagist.org/downloads/", 714 | "license": [ 715 | "MIT" 716 | ], 717 | "authors": [ 718 | { 719 | "name": "Mike van Riel", 720 | "email": "me@mikevanriel.com" 721 | }, 722 | { 723 | "name": "Jaap van Otterdijk", 724 | "email": "account@ijaap.nl" 725 | } 726 | ], 727 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 728 | "time": "2020-02-22T12:28:44+00:00" 729 | }, 730 | { 731 | "name": "phpdocumentor/type-resolver", 732 | "version": "1.1.0", 733 | "source": { 734 | "type": "git", 735 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 736 | "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" 737 | }, 738 | "dist": { 739 | "type": "zip", 740 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", 741 | "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", 742 | "shasum": "" 743 | }, 744 | "require": { 745 | "php": "^7.2", 746 | "phpdocumentor/reflection-common": "^2.0" 747 | }, 748 | "require-dev": { 749 | "ext-tokenizer": "^7.2", 750 | "mockery/mockery": "~1" 751 | }, 752 | "type": "library", 753 | "extra": { 754 | "branch-alias": { 755 | "dev-master": "1.x-dev" 756 | } 757 | }, 758 | "autoload": { 759 | "psr-4": { 760 | "phpDocumentor\\Reflection\\": "src" 761 | } 762 | }, 763 | "notification-url": "https://packagist.org/downloads/", 764 | "license": [ 765 | "MIT" 766 | ], 767 | "authors": [ 768 | { 769 | "name": "Mike van Riel", 770 | "email": "me@mikevanriel.com" 771 | } 772 | ], 773 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 774 | "time": "2020-02-18T18:59:58+00:00" 775 | }, 776 | { 777 | "name": "phpspec/prophecy", 778 | "version": "v1.10.3", 779 | "source": { 780 | "type": "git", 781 | "url": "https://github.com/phpspec/prophecy.git", 782 | "reference": "451c3cd1418cf640de218914901e51b064abb093" 783 | }, 784 | "dist": { 785 | "type": "zip", 786 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", 787 | "reference": "451c3cd1418cf640de218914901e51b064abb093", 788 | "shasum": "" 789 | }, 790 | "require": { 791 | "doctrine/instantiator": "^1.0.2", 792 | "php": "^5.3|^7.0", 793 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 794 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", 795 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" 796 | }, 797 | "require-dev": { 798 | "phpspec/phpspec": "^2.5 || ^3.2", 799 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 800 | }, 801 | "type": "library", 802 | "extra": { 803 | "branch-alias": { 804 | "dev-master": "1.10.x-dev" 805 | } 806 | }, 807 | "autoload": { 808 | "psr-4": { 809 | "Prophecy\\": "src/Prophecy" 810 | } 811 | }, 812 | "notification-url": "https://packagist.org/downloads/", 813 | "license": [ 814 | "MIT" 815 | ], 816 | "authors": [ 817 | { 818 | "name": "Konstantin Kudryashov", 819 | "email": "ever.zet@gmail.com", 820 | "homepage": "http://everzet.com" 821 | }, 822 | { 823 | "name": "Marcello Duarte", 824 | "email": "marcello.duarte@gmail.com" 825 | } 826 | ], 827 | "description": "Highly opinionated mocking framework for PHP 5.3+", 828 | "homepage": "https://github.com/phpspec/prophecy", 829 | "keywords": [ 830 | "Double", 831 | "Dummy", 832 | "fake", 833 | "mock", 834 | "spy", 835 | "stub" 836 | ], 837 | "time": "2020-03-05T15:02:03+00:00" 838 | }, 839 | { 840 | "name": "phpunit/php-code-coverage", 841 | "version": "6.1.4", 842 | "source": { 843 | "type": "git", 844 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 845 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" 846 | }, 847 | "dist": { 848 | "type": "zip", 849 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 850 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 851 | "shasum": "" 852 | }, 853 | "require": { 854 | "ext-dom": "*", 855 | "ext-xmlwriter": "*", 856 | "php": "^7.1", 857 | "phpunit/php-file-iterator": "^2.0", 858 | "phpunit/php-text-template": "^1.2.1", 859 | "phpunit/php-token-stream": "^3.0", 860 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 861 | "sebastian/environment": "^3.1 || ^4.0", 862 | "sebastian/version": "^2.0.1", 863 | "theseer/tokenizer": "^1.1" 864 | }, 865 | "require-dev": { 866 | "phpunit/phpunit": "^7.0" 867 | }, 868 | "suggest": { 869 | "ext-xdebug": "^2.6.0" 870 | }, 871 | "type": "library", 872 | "extra": { 873 | "branch-alias": { 874 | "dev-master": "6.1-dev" 875 | } 876 | }, 877 | "autoload": { 878 | "classmap": [ 879 | "src/" 880 | ] 881 | }, 882 | "notification-url": "https://packagist.org/downloads/", 883 | "license": [ 884 | "BSD-3-Clause" 885 | ], 886 | "authors": [ 887 | { 888 | "name": "Sebastian Bergmann", 889 | "email": "sebastian@phpunit.de", 890 | "role": "lead" 891 | } 892 | ], 893 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 894 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 895 | "keywords": [ 896 | "coverage", 897 | "testing", 898 | "xunit" 899 | ], 900 | "time": "2018-10-31T16:06:48+00:00" 901 | }, 902 | { 903 | "name": "phpunit/php-file-iterator", 904 | "version": "2.0.2", 905 | "source": { 906 | "type": "git", 907 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 908 | "reference": "050bedf145a257b1ff02746c31894800e5122946" 909 | }, 910 | "dist": { 911 | "type": "zip", 912 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", 913 | "reference": "050bedf145a257b1ff02746c31894800e5122946", 914 | "shasum": "" 915 | }, 916 | "require": { 917 | "php": "^7.1" 918 | }, 919 | "require-dev": { 920 | "phpunit/phpunit": "^7.1" 921 | }, 922 | "type": "library", 923 | "extra": { 924 | "branch-alias": { 925 | "dev-master": "2.0.x-dev" 926 | } 927 | }, 928 | "autoload": { 929 | "classmap": [ 930 | "src/" 931 | ] 932 | }, 933 | "notification-url": "https://packagist.org/downloads/", 934 | "license": [ 935 | "BSD-3-Clause" 936 | ], 937 | "authors": [ 938 | { 939 | "name": "Sebastian Bergmann", 940 | "email": "sebastian@phpunit.de", 941 | "role": "lead" 942 | } 943 | ], 944 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 945 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 946 | "keywords": [ 947 | "filesystem", 948 | "iterator" 949 | ], 950 | "time": "2018-09-13T20:33:42+00:00" 951 | }, 952 | { 953 | "name": "phpunit/php-text-template", 954 | "version": "1.2.1", 955 | "source": { 956 | "type": "git", 957 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 958 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 959 | }, 960 | "dist": { 961 | "type": "zip", 962 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 963 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 964 | "shasum": "" 965 | }, 966 | "require": { 967 | "php": ">=5.3.3" 968 | }, 969 | "type": "library", 970 | "autoload": { 971 | "classmap": [ 972 | "src/" 973 | ] 974 | }, 975 | "notification-url": "https://packagist.org/downloads/", 976 | "license": [ 977 | "BSD-3-Clause" 978 | ], 979 | "authors": [ 980 | { 981 | "name": "Sebastian Bergmann", 982 | "email": "sebastian@phpunit.de", 983 | "role": "lead" 984 | } 985 | ], 986 | "description": "Simple template engine.", 987 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 988 | "keywords": [ 989 | "template" 990 | ], 991 | "time": "2015-06-21T13:50:34+00:00" 992 | }, 993 | { 994 | "name": "phpunit/php-timer", 995 | "version": "2.1.2", 996 | "source": { 997 | "type": "git", 998 | "url": "https://github.com/sebastianbergmann/php-timer.git", 999 | "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" 1000 | }, 1001 | "dist": { 1002 | "type": "zip", 1003 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", 1004 | "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", 1005 | "shasum": "" 1006 | }, 1007 | "require": { 1008 | "php": "^7.1" 1009 | }, 1010 | "require-dev": { 1011 | "phpunit/phpunit": "^7.0" 1012 | }, 1013 | "type": "library", 1014 | "extra": { 1015 | "branch-alias": { 1016 | "dev-master": "2.1-dev" 1017 | } 1018 | }, 1019 | "autoload": { 1020 | "classmap": [ 1021 | "src/" 1022 | ] 1023 | }, 1024 | "notification-url": "https://packagist.org/downloads/", 1025 | "license": [ 1026 | "BSD-3-Clause" 1027 | ], 1028 | "authors": [ 1029 | { 1030 | "name": "Sebastian Bergmann", 1031 | "email": "sebastian@phpunit.de", 1032 | "role": "lead" 1033 | } 1034 | ], 1035 | "description": "Utility class for timing", 1036 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1037 | "keywords": [ 1038 | "timer" 1039 | ], 1040 | "time": "2019-06-07T04:22:29+00:00" 1041 | }, 1042 | { 1043 | "name": "phpunit/php-token-stream", 1044 | "version": "3.1.1", 1045 | "source": { 1046 | "type": "git", 1047 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1048 | "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" 1049 | }, 1050 | "dist": { 1051 | "type": "zip", 1052 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", 1053 | "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", 1054 | "shasum": "" 1055 | }, 1056 | "require": { 1057 | "ext-tokenizer": "*", 1058 | "php": "^7.1" 1059 | }, 1060 | "require-dev": { 1061 | "phpunit/phpunit": "^7.0" 1062 | }, 1063 | "type": "library", 1064 | "extra": { 1065 | "branch-alias": { 1066 | "dev-master": "3.1-dev" 1067 | } 1068 | }, 1069 | "autoload": { 1070 | "classmap": [ 1071 | "src/" 1072 | ] 1073 | }, 1074 | "notification-url": "https://packagist.org/downloads/", 1075 | "license": [ 1076 | "BSD-3-Clause" 1077 | ], 1078 | "authors": [ 1079 | { 1080 | "name": "Sebastian Bergmann", 1081 | "email": "sebastian@phpunit.de" 1082 | } 1083 | ], 1084 | "description": "Wrapper around PHP's tokenizer extension.", 1085 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1086 | "keywords": [ 1087 | "tokenizer" 1088 | ], 1089 | "time": "2019-09-17T06:23:10+00:00" 1090 | }, 1091 | { 1092 | "name": "phpunit/phpunit", 1093 | "version": "7.5.20", 1094 | "source": { 1095 | "type": "git", 1096 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1097 | "reference": "9467db479d1b0487c99733bb1e7944d32deded2c" 1098 | }, 1099 | "dist": { 1100 | "type": "zip", 1101 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c", 1102 | "reference": "9467db479d1b0487c99733bb1e7944d32deded2c", 1103 | "shasum": "" 1104 | }, 1105 | "require": { 1106 | "doctrine/instantiator": "^1.1", 1107 | "ext-dom": "*", 1108 | "ext-json": "*", 1109 | "ext-libxml": "*", 1110 | "ext-mbstring": "*", 1111 | "ext-xml": "*", 1112 | "myclabs/deep-copy": "^1.7", 1113 | "phar-io/manifest": "^1.0.2", 1114 | "phar-io/version": "^2.0", 1115 | "php": "^7.1", 1116 | "phpspec/prophecy": "^1.7", 1117 | "phpunit/php-code-coverage": "^6.0.7", 1118 | "phpunit/php-file-iterator": "^2.0.1", 1119 | "phpunit/php-text-template": "^1.2.1", 1120 | "phpunit/php-timer": "^2.1", 1121 | "sebastian/comparator": "^3.0", 1122 | "sebastian/diff": "^3.0", 1123 | "sebastian/environment": "^4.0", 1124 | "sebastian/exporter": "^3.1", 1125 | "sebastian/global-state": "^2.0", 1126 | "sebastian/object-enumerator": "^3.0.3", 1127 | "sebastian/resource-operations": "^2.0", 1128 | "sebastian/version": "^2.0.1" 1129 | }, 1130 | "conflict": { 1131 | "phpunit/phpunit-mock-objects": "*" 1132 | }, 1133 | "require-dev": { 1134 | "ext-pdo": "*" 1135 | }, 1136 | "suggest": { 1137 | "ext-soap": "*", 1138 | "ext-xdebug": "*", 1139 | "phpunit/php-invoker": "^2.0" 1140 | }, 1141 | "bin": [ 1142 | "phpunit" 1143 | ], 1144 | "type": "library", 1145 | "extra": { 1146 | "branch-alias": { 1147 | "dev-master": "7.5-dev" 1148 | } 1149 | }, 1150 | "autoload": { 1151 | "classmap": [ 1152 | "src/" 1153 | ] 1154 | }, 1155 | "notification-url": "https://packagist.org/downloads/", 1156 | "license": [ 1157 | "BSD-3-Clause" 1158 | ], 1159 | "authors": [ 1160 | { 1161 | "name": "Sebastian Bergmann", 1162 | "email": "sebastian@phpunit.de", 1163 | "role": "lead" 1164 | } 1165 | ], 1166 | "description": "The PHP Unit Testing framework.", 1167 | "homepage": "https://phpunit.de/", 1168 | "keywords": [ 1169 | "phpunit", 1170 | "testing", 1171 | "xunit" 1172 | ], 1173 | "time": "2020-01-08T08:45:45+00:00" 1174 | }, 1175 | { 1176 | "name": "sebastian/code-unit-reverse-lookup", 1177 | "version": "1.0.1", 1178 | "source": { 1179 | "type": "git", 1180 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1181 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1182 | }, 1183 | "dist": { 1184 | "type": "zip", 1185 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1186 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1187 | "shasum": "" 1188 | }, 1189 | "require": { 1190 | "php": "^5.6 || ^7.0" 1191 | }, 1192 | "require-dev": { 1193 | "phpunit/phpunit": "^5.7 || ^6.0" 1194 | }, 1195 | "type": "library", 1196 | "extra": { 1197 | "branch-alias": { 1198 | "dev-master": "1.0.x-dev" 1199 | } 1200 | }, 1201 | "autoload": { 1202 | "classmap": [ 1203 | "src/" 1204 | ] 1205 | }, 1206 | "notification-url": "https://packagist.org/downloads/", 1207 | "license": [ 1208 | "BSD-3-Clause" 1209 | ], 1210 | "authors": [ 1211 | { 1212 | "name": "Sebastian Bergmann", 1213 | "email": "sebastian@phpunit.de" 1214 | } 1215 | ], 1216 | "description": "Looks up which function or method a line of code belongs to", 1217 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1218 | "time": "2017-03-04T06:30:41+00:00" 1219 | }, 1220 | { 1221 | "name": "sebastian/comparator", 1222 | "version": "3.0.2", 1223 | "source": { 1224 | "type": "git", 1225 | "url": "https://github.com/sebastianbergmann/comparator.git", 1226 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" 1227 | }, 1228 | "dist": { 1229 | "type": "zip", 1230 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1231 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1232 | "shasum": "" 1233 | }, 1234 | "require": { 1235 | "php": "^7.1", 1236 | "sebastian/diff": "^3.0", 1237 | "sebastian/exporter": "^3.1" 1238 | }, 1239 | "require-dev": { 1240 | "phpunit/phpunit": "^7.1" 1241 | }, 1242 | "type": "library", 1243 | "extra": { 1244 | "branch-alias": { 1245 | "dev-master": "3.0-dev" 1246 | } 1247 | }, 1248 | "autoload": { 1249 | "classmap": [ 1250 | "src/" 1251 | ] 1252 | }, 1253 | "notification-url": "https://packagist.org/downloads/", 1254 | "license": [ 1255 | "BSD-3-Clause" 1256 | ], 1257 | "authors": [ 1258 | { 1259 | "name": "Jeff Welch", 1260 | "email": "whatthejeff@gmail.com" 1261 | }, 1262 | { 1263 | "name": "Volker Dusch", 1264 | "email": "github@wallbash.com" 1265 | }, 1266 | { 1267 | "name": "Bernhard Schussek", 1268 | "email": "bschussek@2bepublished.at" 1269 | }, 1270 | { 1271 | "name": "Sebastian Bergmann", 1272 | "email": "sebastian@phpunit.de" 1273 | } 1274 | ], 1275 | "description": "Provides the functionality to compare PHP values for equality", 1276 | "homepage": "https://github.com/sebastianbergmann/comparator", 1277 | "keywords": [ 1278 | "comparator", 1279 | "compare", 1280 | "equality" 1281 | ], 1282 | "time": "2018-07-12T15:12:46+00:00" 1283 | }, 1284 | { 1285 | "name": "sebastian/diff", 1286 | "version": "3.0.2", 1287 | "source": { 1288 | "type": "git", 1289 | "url": "https://github.com/sebastianbergmann/diff.git", 1290 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" 1291 | }, 1292 | "dist": { 1293 | "type": "zip", 1294 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1295 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1296 | "shasum": "" 1297 | }, 1298 | "require": { 1299 | "php": "^7.1" 1300 | }, 1301 | "require-dev": { 1302 | "phpunit/phpunit": "^7.5 || ^8.0", 1303 | "symfony/process": "^2 || ^3.3 || ^4" 1304 | }, 1305 | "type": "library", 1306 | "extra": { 1307 | "branch-alias": { 1308 | "dev-master": "3.0-dev" 1309 | } 1310 | }, 1311 | "autoload": { 1312 | "classmap": [ 1313 | "src/" 1314 | ] 1315 | }, 1316 | "notification-url": "https://packagist.org/downloads/", 1317 | "license": [ 1318 | "BSD-3-Clause" 1319 | ], 1320 | "authors": [ 1321 | { 1322 | "name": "Kore Nordmann", 1323 | "email": "mail@kore-nordmann.de" 1324 | }, 1325 | { 1326 | "name": "Sebastian Bergmann", 1327 | "email": "sebastian@phpunit.de" 1328 | } 1329 | ], 1330 | "description": "Diff implementation", 1331 | "homepage": "https://github.com/sebastianbergmann/diff", 1332 | "keywords": [ 1333 | "diff", 1334 | "udiff", 1335 | "unidiff", 1336 | "unified diff" 1337 | ], 1338 | "time": "2019-02-04T06:01:07+00:00" 1339 | }, 1340 | { 1341 | "name": "sebastian/environment", 1342 | "version": "4.2.3", 1343 | "source": { 1344 | "type": "git", 1345 | "url": "https://github.com/sebastianbergmann/environment.git", 1346 | "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" 1347 | }, 1348 | "dist": { 1349 | "type": "zip", 1350 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", 1351 | "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", 1352 | "shasum": "" 1353 | }, 1354 | "require": { 1355 | "php": "^7.1" 1356 | }, 1357 | "require-dev": { 1358 | "phpunit/phpunit": "^7.5" 1359 | }, 1360 | "suggest": { 1361 | "ext-posix": "*" 1362 | }, 1363 | "type": "library", 1364 | "extra": { 1365 | "branch-alias": { 1366 | "dev-master": "4.2-dev" 1367 | } 1368 | }, 1369 | "autoload": { 1370 | "classmap": [ 1371 | "src/" 1372 | ] 1373 | }, 1374 | "notification-url": "https://packagist.org/downloads/", 1375 | "license": [ 1376 | "BSD-3-Clause" 1377 | ], 1378 | "authors": [ 1379 | { 1380 | "name": "Sebastian Bergmann", 1381 | "email": "sebastian@phpunit.de" 1382 | } 1383 | ], 1384 | "description": "Provides functionality to handle HHVM/PHP environments", 1385 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1386 | "keywords": [ 1387 | "Xdebug", 1388 | "environment", 1389 | "hhvm" 1390 | ], 1391 | "time": "2019-11-20T08:46:58+00:00" 1392 | }, 1393 | { 1394 | "name": "sebastian/exporter", 1395 | "version": "3.1.2", 1396 | "source": { 1397 | "type": "git", 1398 | "url": "https://github.com/sebastianbergmann/exporter.git", 1399 | "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" 1400 | }, 1401 | "dist": { 1402 | "type": "zip", 1403 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", 1404 | "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", 1405 | "shasum": "" 1406 | }, 1407 | "require": { 1408 | "php": "^7.0", 1409 | "sebastian/recursion-context": "^3.0" 1410 | }, 1411 | "require-dev": { 1412 | "ext-mbstring": "*", 1413 | "phpunit/phpunit": "^6.0" 1414 | }, 1415 | "type": "library", 1416 | "extra": { 1417 | "branch-alias": { 1418 | "dev-master": "3.1.x-dev" 1419 | } 1420 | }, 1421 | "autoload": { 1422 | "classmap": [ 1423 | "src/" 1424 | ] 1425 | }, 1426 | "notification-url": "https://packagist.org/downloads/", 1427 | "license": [ 1428 | "BSD-3-Clause" 1429 | ], 1430 | "authors": [ 1431 | { 1432 | "name": "Sebastian Bergmann", 1433 | "email": "sebastian@phpunit.de" 1434 | }, 1435 | { 1436 | "name": "Jeff Welch", 1437 | "email": "whatthejeff@gmail.com" 1438 | }, 1439 | { 1440 | "name": "Volker Dusch", 1441 | "email": "github@wallbash.com" 1442 | }, 1443 | { 1444 | "name": "Adam Harvey", 1445 | "email": "aharvey@php.net" 1446 | }, 1447 | { 1448 | "name": "Bernhard Schussek", 1449 | "email": "bschussek@gmail.com" 1450 | } 1451 | ], 1452 | "description": "Provides the functionality to export PHP variables for visualization", 1453 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1454 | "keywords": [ 1455 | "export", 1456 | "exporter" 1457 | ], 1458 | "time": "2019-09-14T09:02:43+00:00" 1459 | }, 1460 | { 1461 | "name": "sebastian/global-state", 1462 | "version": "2.0.0", 1463 | "source": { 1464 | "type": "git", 1465 | "url": "https://github.com/sebastianbergmann/global-state.git", 1466 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1467 | }, 1468 | "dist": { 1469 | "type": "zip", 1470 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1471 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1472 | "shasum": "" 1473 | }, 1474 | "require": { 1475 | "php": "^7.0" 1476 | }, 1477 | "require-dev": { 1478 | "phpunit/phpunit": "^6.0" 1479 | }, 1480 | "suggest": { 1481 | "ext-uopz": "*" 1482 | }, 1483 | "type": "library", 1484 | "extra": { 1485 | "branch-alias": { 1486 | "dev-master": "2.0-dev" 1487 | } 1488 | }, 1489 | "autoload": { 1490 | "classmap": [ 1491 | "src/" 1492 | ] 1493 | }, 1494 | "notification-url": "https://packagist.org/downloads/", 1495 | "license": [ 1496 | "BSD-3-Clause" 1497 | ], 1498 | "authors": [ 1499 | { 1500 | "name": "Sebastian Bergmann", 1501 | "email": "sebastian@phpunit.de" 1502 | } 1503 | ], 1504 | "description": "Snapshotting of global state", 1505 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1506 | "keywords": [ 1507 | "global state" 1508 | ], 1509 | "time": "2017-04-27T15:39:26+00:00" 1510 | }, 1511 | { 1512 | "name": "sebastian/object-enumerator", 1513 | "version": "3.0.3", 1514 | "source": { 1515 | "type": "git", 1516 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1517 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" 1518 | }, 1519 | "dist": { 1520 | "type": "zip", 1521 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1522 | "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", 1523 | "shasum": "" 1524 | }, 1525 | "require": { 1526 | "php": "^7.0", 1527 | "sebastian/object-reflector": "^1.1.1", 1528 | "sebastian/recursion-context": "^3.0" 1529 | }, 1530 | "require-dev": { 1531 | "phpunit/phpunit": "^6.0" 1532 | }, 1533 | "type": "library", 1534 | "extra": { 1535 | "branch-alias": { 1536 | "dev-master": "3.0.x-dev" 1537 | } 1538 | }, 1539 | "autoload": { 1540 | "classmap": [ 1541 | "src/" 1542 | ] 1543 | }, 1544 | "notification-url": "https://packagist.org/downloads/", 1545 | "license": [ 1546 | "BSD-3-Clause" 1547 | ], 1548 | "authors": [ 1549 | { 1550 | "name": "Sebastian Bergmann", 1551 | "email": "sebastian@phpunit.de" 1552 | } 1553 | ], 1554 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1555 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1556 | "time": "2017-08-03T12:35:26+00:00" 1557 | }, 1558 | { 1559 | "name": "sebastian/object-reflector", 1560 | "version": "1.1.1", 1561 | "source": { 1562 | "type": "git", 1563 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1564 | "reference": "773f97c67f28de00d397be301821b06708fca0be" 1565 | }, 1566 | "dist": { 1567 | "type": "zip", 1568 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", 1569 | "reference": "773f97c67f28de00d397be301821b06708fca0be", 1570 | "shasum": "" 1571 | }, 1572 | "require": { 1573 | "php": "^7.0" 1574 | }, 1575 | "require-dev": { 1576 | "phpunit/phpunit": "^6.0" 1577 | }, 1578 | "type": "library", 1579 | "extra": { 1580 | "branch-alias": { 1581 | "dev-master": "1.1-dev" 1582 | } 1583 | }, 1584 | "autoload": { 1585 | "classmap": [ 1586 | "src/" 1587 | ] 1588 | }, 1589 | "notification-url": "https://packagist.org/downloads/", 1590 | "license": [ 1591 | "BSD-3-Clause" 1592 | ], 1593 | "authors": [ 1594 | { 1595 | "name": "Sebastian Bergmann", 1596 | "email": "sebastian@phpunit.de" 1597 | } 1598 | ], 1599 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1600 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1601 | "time": "2017-03-29T09:07:27+00:00" 1602 | }, 1603 | { 1604 | "name": "sebastian/recursion-context", 1605 | "version": "3.0.0", 1606 | "source": { 1607 | "type": "git", 1608 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1609 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" 1610 | }, 1611 | "dist": { 1612 | "type": "zip", 1613 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1614 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1615 | "shasum": "" 1616 | }, 1617 | "require": { 1618 | "php": "^7.0" 1619 | }, 1620 | "require-dev": { 1621 | "phpunit/phpunit": "^6.0" 1622 | }, 1623 | "type": "library", 1624 | "extra": { 1625 | "branch-alias": { 1626 | "dev-master": "3.0.x-dev" 1627 | } 1628 | }, 1629 | "autoload": { 1630 | "classmap": [ 1631 | "src/" 1632 | ] 1633 | }, 1634 | "notification-url": "https://packagist.org/downloads/", 1635 | "license": [ 1636 | "BSD-3-Clause" 1637 | ], 1638 | "authors": [ 1639 | { 1640 | "name": "Jeff Welch", 1641 | "email": "whatthejeff@gmail.com" 1642 | }, 1643 | { 1644 | "name": "Sebastian Bergmann", 1645 | "email": "sebastian@phpunit.de" 1646 | }, 1647 | { 1648 | "name": "Adam Harvey", 1649 | "email": "aharvey@php.net" 1650 | } 1651 | ], 1652 | "description": "Provides functionality to recursively process PHP variables", 1653 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1654 | "time": "2017-03-03T06:23:57+00:00" 1655 | }, 1656 | { 1657 | "name": "sebastian/resource-operations", 1658 | "version": "2.0.1", 1659 | "source": { 1660 | "type": "git", 1661 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1662 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" 1663 | }, 1664 | "dist": { 1665 | "type": "zip", 1666 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 1667 | "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", 1668 | "shasum": "" 1669 | }, 1670 | "require": { 1671 | "php": "^7.1" 1672 | }, 1673 | "type": "library", 1674 | "extra": { 1675 | "branch-alias": { 1676 | "dev-master": "2.0-dev" 1677 | } 1678 | }, 1679 | "autoload": { 1680 | "classmap": [ 1681 | "src/" 1682 | ] 1683 | }, 1684 | "notification-url": "https://packagist.org/downloads/", 1685 | "license": [ 1686 | "BSD-3-Clause" 1687 | ], 1688 | "authors": [ 1689 | { 1690 | "name": "Sebastian Bergmann", 1691 | "email": "sebastian@phpunit.de" 1692 | } 1693 | ], 1694 | "description": "Provides a list of PHP built-in functions that operate on resources", 1695 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1696 | "time": "2018-10-04T04:07:39+00:00" 1697 | }, 1698 | { 1699 | "name": "sebastian/version", 1700 | "version": "2.0.1", 1701 | "source": { 1702 | "type": "git", 1703 | "url": "https://github.com/sebastianbergmann/version.git", 1704 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1705 | }, 1706 | "dist": { 1707 | "type": "zip", 1708 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1709 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1710 | "shasum": "" 1711 | }, 1712 | "require": { 1713 | "php": ">=5.6" 1714 | }, 1715 | "type": "library", 1716 | "extra": { 1717 | "branch-alias": { 1718 | "dev-master": "2.0.x-dev" 1719 | } 1720 | }, 1721 | "autoload": { 1722 | "classmap": [ 1723 | "src/" 1724 | ] 1725 | }, 1726 | "notification-url": "https://packagist.org/downloads/", 1727 | "license": [ 1728 | "BSD-3-Clause" 1729 | ], 1730 | "authors": [ 1731 | { 1732 | "name": "Sebastian Bergmann", 1733 | "email": "sebastian@phpunit.de", 1734 | "role": "lead" 1735 | } 1736 | ], 1737 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1738 | "homepage": "https://github.com/sebastianbergmann/version", 1739 | "time": "2016-10-03T07:35:21+00:00" 1740 | }, 1741 | { 1742 | "name": "squizlabs/php_codesniffer", 1743 | "version": "3.5.5", 1744 | "source": { 1745 | "type": "git", 1746 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1747 | "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6" 1748 | }, 1749 | "dist": { 1750 | "type": "zip", 1751 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6", 1752 | "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6", 1753 | "shasum": "" 1754 | }, 1755 | "require": { 1756 | "ext-simplexml": "*", 1757 | "ext-tokenizer": "*", 1758 | "ext-xmlwriter": "*", 1759 | "php": ">=5.4.0" 1760 | }, 1761 | "require-dev": { 1762 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 1763 | }, 1764 | "bin": [ 1765 | "bin/phpcs", 1766 | "bin/phpcbf" 1767 | ], 1768 | "type": "library", 1769 | "extra": { 1770 | "branch-alias": { 1771 | "dev-master": "3.x-dev" 1772 | } 1773 | }, 1774 | "notification-url": "https://packagist.org/downloads/", 1775 | "license": [ 1776 | "BSD-3-Clause" 1777 | ], 1778 | "authors": [ 1779 | { 1780 | "name": "Greg Sherwood", 1781 | "role": "lead" 1782 | } 1783 | ], 1784 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 1785 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 1786 | "keywords": [ 1787 | "phpcs", 1788 | "standards" 1789 | ], 1790 | "time": "2020-04-17T01:09:41+00:00" 1791 | }, 1792 | { 1793 | "name": "symfony/polyfill-ctype", 1794 | "version": "v1.15.0", 1795 | "source": { 1796 | "type": "git", 1797 | "url": "https://github.com/symfony/polyfill-ctype.git", 1798 | "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" 1799 | }, 1800 | "dist": { 1801 | "type": "zip", 1802 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", 1803 | "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", 1804 | "shasum": "" 1805 | }, 1806 | "require": { 1807 | "php": ">=5.3.3" 1808 | }, 1809 | "suggest": { 1810 | "ext-ctype": "For best performance" 1811 | }, 1812 | "type": "library", 1813 | "extra": { 1814 | "branch-alias": { 1815 | "dev-master": "1.15-dev" 1816 | } 1817 | }, 1818 | "autoload": { 1819 | "psr-4": { 1820 | "Symfony\\Polyfill\\Ctype\\": "" 1821 | }, 1822 | "files": [ 1823 | "bootstrap.php" 1824 | ] 1825 | }, 1826 | "notification-url": "https://packagist.org/downloads/", 1827 | "license": [ 1828 | "MIT" 1829 | ], 1830 | "authors": [ 1831 | { 1832 | "name": "Gert de Pagter", 1833 | "email": "BackEndTea@gmail.com" 1834 | }, 1835 | { 1836 | "name": "Symfony Community", 1837 | "homepage": "https://symfony.com/contributors" 1838 | } 1839 | ], 1840 | "description": "Symfony polyfill for ctype functions", 1841 | "homepage": "https://symfony.com", 1842 | "keywords": [ 1843 | "compatibility", 1844 | "ctype", 1845 | "polyfill", 1846 | "portable" 1847 | ], 1848 | "time": "2020-02-27T09:26:54+00:00" 1849 | }, 1850 | { 1851 | "name": "symfony/process", 1852 | "version": "v5.0.8", 1853 | "source": { 1854 | "type": "git", 1855 | "url": "https://github.com/symfony/process.git", 1856 | "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7" 1857 | }, 1858 | "dist": { 1859 | "type": "zip", 1860 | "url": "https://api.github.com/repos/symfony/process/zipball/3179f68dff5bad14d38c4114a1dab98030801fd7", 1861 | "reference": "3179f68dff5bad14d38c4114a1dab98030801fd7", 1862 | "shasum": "" 1863 | }, 1864 | "require": { 1865 | "php": "^7.2.5" 1866 | }, 1867 | "type": "library", 1868 | "extra": { 1869 | "branch-alias": { 1870 | "dev-master": "5.0-dev" 1871 | } 1872 | }, 1873 | "autoload": { 1874 | "psr-4": { 1875 | "Symfony\\Component\\Process\\": "" 1876 | }, 1877 | "exclude-from-classmap": [ 1878 | "/Tests/" 1879 | ] 1880 | }, 1881 | "notification-url": "https://packagist.org/downloads/", 1882 | "license": [ 1883 | "MIT" 1884 | ], 1885 | "authors": [ 1886 | { 1887 | "name": "Fabien Potencier", 1888 | "email": "fabien@symfony.com" 1889 | }, 1890 | { 1891 | "name": "Symfony Community", 1892 | "homepage": "https://symfony.com/contributors" 1893 | } 1894 | ], 1895 | "description": "Symfony Process Component", 1896 | "homepage": "https://symfony.com", 1897 | "time": "2020-04-15T15:59:10+00:00" 1898 | }, 1899 | { 1900 | "name": "theseer/tokenizer", 1901 | "version": "1.1.3", 1902 | "source": { 1903 | "type": "git", 1904 | "url": "https://github.com/theseer/tokenizer.git", 1905 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" 1906 | }, 1907 | "dist": { 1908 | "type": "zip", 1909 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1910 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1911 | "shasum": "" 1912 | }, 1913 | "require": { 1914 | "ext-dom": "*", 1915 | "ext-tokenizer": "*", 1916 | "ext-xmlwriter": "*", 1917 | "php": "^7.0" 1918 | }, 1919 | "type": "library", 1920 | "autoload": { 1921 | "classmap": [ 1922 | "src/" 1923 | ] 1924 | }, 1925 | "notification-url": "https://packagist.org/downloads/", 1926 | "license": [ 1927 | "BSD-3-Clause" 1928 | ], 1929 | "authors": [ 1930 | { 1931 | "name": "Arne Blankerts", 1932 | "email": "arne@blankerts.de", 1933 | "role": "Developer" 1934 | } 1935 | ], 1936 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1937 | "time": "2019-06-13T22:48:21+00:00" 1938 | }, 1939 | { 1940 | "name": "vlucas/phpdotenv", 1941 | "version": "v2.6.3", 1942 | "source": { 1943 | "type": "git", 1944 | "url": "https://github.com/vlucas/phpdotenv.git", 1945 | "reference": "df4c4d08a639be4ef5d6d1322868f9e477553679" 1946 | }, 1947 | "dist": { 1948 | "type": "zip", 1949 | "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/df4c4d08a639be4ef5d6d1322868f9e477553679", 1950 | "reference": "df4c4d08a639be4ef5d6d1322868f9e477553679", 1951 | "shasum": "" 1952 | }, 1953 | "require": { 1954 | "php": ">=5.3.9", 1955 | "symfony/polyfill-ctype": "^1.9" 1956 | }, 1957 | "require-dev": { 1958 | "ext-filter": "*", 1959 | "ext-pcre": "*", 1960 | "phpunit/phpunit": "^4.8.35 || ^5.0" 1961 | }, 1962 | "suggest": { 1963 | "ext-filter": "Required to use the boolean validator.", 1964 | "ext-pcre": "Required to use most of the library." 1965 | }, 1966 | "type": "library", 1967 | "extra": { 1968 | "branch-alias": { 1969 | "dev-master": "2.6-dev" 1970 | } 1971 | }, 1972 | "autoload": { 1973 | "psr-4": { 1974 | "Dotenv\\": "src/" 1975 | } 1976 | }, 1977 | "notification-url": "https://packagist.org/downloads/", 1978 | "license": [ 1979 | "BSD-3-Clause" 1980 | ], 1981 | "authors": [ 1982 | { 1983 | "name": "Vance Lucas", 1984 | "email": "vance@vancelucas.com", 1985 | "homepage": "http://www.vancelucas.com" 1986 | } 1987 | ], 1988 | "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", 1989 | "keywords": [ 1990 | "dotenv", 1991 | "env", 1992 | "environment" 1993 | ], 1994 | "time": "2020-04-12T15:11:38+00:00" 1995 | }, 1996 | { 1997 | "name": "webmozart/assert", 1998 | "version": "1.8.0", 1999 | "source": { 2000 | "type": "git", 2001 | "url": "https://github.com/webmozart/assert.git", 2002 | "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" 2003 | }, 2004 | "dist": { 2005 | "type": "zip", 2006 | "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", 2007 | "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", 2008 | "shasum": "" 2009 | }, 2010 | "require": { 2011 | "php": "^5.3.3 || ^7.0", 2012 | "symfony/polyfill-ctype": "^1.8" 2013 | }, 2014 | "conflict": { 2015 | "vimeo/psalm": "<3.9.1" 2016 | }, 2017 | "require-dev": { 2018 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 2019 | }, 2020 | "type": "library", 2021 | "autoload": { 2022 | "psr-4": { 2023 | "Webmozart\\Assert\\": "src/" 2024 | } 2025 | }, 2026 | "notification-url": "https://packagist.org/downloads/", 2027 | "license": [ 2028 | "MIT" 2029 | ], 2030 | "authors": [ 2031 | { 2032 | "name": "Bernhard Schussek", 2033 | "email": "bschussek@gmail.com" 2034 | } 2035 | ], 2036 | "description": "Assertions to validate method input/output with nice error messages.", 2037 | "keywords": [ 2038 | "assert", 2039 | "check", 2040 | "validate" 2041 | ], 2042 | "time": "2020-04-18T12:12:48+00:00" 2043 | } 2044 | ], 2045 | "aliases": [], 2046 | "minimum-stability": "stable", 2047 | "stability-flags": [], 2048 | "prefer-stable": false, 2049 | "prefer-lowest": false, 2050 | "platform": { 2051 | "php": "^7.1" 2052 | }, 2053 | "platform-dev": [] 2054 | } 2055 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/crook/ 6 | ./tests/dumbCode/ 7 | 8 | 9 | 10 | 11 | 12 | src 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/crook/Application.php: -------------------------------------------------------------------------------- 1 | config = $config; 24 | $this->hookType = $hookType; 25 | } 26 | 27 | /** 28 | * Gets the action to $hookType and execute it, returning the error 29 | * message and code if something goes wrong 30 | * 31 | * @return array 32 | */ 33 | public function run() 34 | { 35 | $hook = new Hook($this->config); 36 | 37 | try { 38 | $action = $hook->getAction($this->hookType); 39 | $bin = $this->config->getComposerPath(); 40 | } catch (\Exception $e) { 41 | return [ 42 | 'code' => 23, 43 | 'message' => $e->getMessage() . "\n" 44 | ]; 45 | } 46 | 47 | $command = $bin . ' run-script ' . $action; 48 | exec($command, $output, $returnCode); 49 | 50 | return [ 51 | 'code' => $returnCode, 52 | 'message' => implode("\n", $output) 53 | ]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/crook/Command/AddHook.php: -------------------------------------------------------------------------------- 1 | setName('add'); 21 | $this->setDescription('Add a new hook to project'); 22 | 23 | $this->addArgument( 24 | 'hook-name', 25 | InputArgument::REQUIRED, 26 | 'Git hook name' 27 | ); 28 | 29 | $this->addArgument( 30 | 'hook-action', 31 | InputArgument::REQUIRED, 32 | 'Composer action' 33 | ); 34 | } 35 | 36 | /** 37 | * Creates symlink and add hook-name and hook-action to crook.json 38 | * configuration file 39 | * 40 | * @param InputInterface $input 41 | * @param OutputInterface $output 42 | * @return int|null|void 43 | * @throws \Exception 44 | */ 45 | protected function execute(InputInterface $input, OutputInterface $output) 46 | { 47 | $hookName = $input->getArgument('hook-name'); 48 | $hookAction = $input->getArgument('hook-action'); 49 | 50 | $hook = new Hook(new Config); 51 | 52 | try { 53 | $hook->add($hookName, $hookAction); 54 | $hook->createLink($hookName); 55 | } catch (\Exception $e) { 56 | throw new \Exception($e->getMessage() . "\n"); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/crook/Command/InitHook.php: -------------------------------------------------------------------------------- 1 | setName('init'); 20 | $this->setDescription('Init crook files'); 21 | } 22 | 23 | /** 24 | * Creates crook.json configuration file, copy theHook file to project 25 | * root directory and make it executable 26 | * 27 | * @param InputInterface $input 28 | * @param OutputInterface $output 29 | * @return int|null|void 30 | */ 31 | protected function execute(InputInterface $input, OutputInterface $output) 32 | { 33 | $config = new Config; 34 | $hook = new Hook($config); 35 | 36 | $config->createCrookConfigFile(); 37 | 38 | $hook->copyTheHook(); 39 | $hook->makeTheHookExecutable(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/crook/Command/RemoveHook.php: -------------------------------------------------------------------------------- 1 | setName('remove'); 21 | $this->setDescription('Remove a hook from project'); 22 | $this->addArgument( 23 | 'hook-name', 24 | InputArgument::REQUIRED, 25 | 'Git hook name' 26 | ); 27 | } 28 | 29 | /** 30 | * Removes link from hook-name to theHook and remove hook-name from 31 | * crook.json configuration file 32 | * 33 | * @param InputInterface $input 34 | * @param OutputInterface $output 35 | * @return int|null|void 36 | */ 37 | protected function execute(InputInterface $input, OutputInterface $output) 38 | { 39 | $hookName = $input->getArgument('hook-name'); 40 | 41 | $hook = new Hook(new Config); 42 | 43 | $hook->removeLink($hookName); 44 | $hook->remove($hookName); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/crook/Config.php: -------------------------------------------------------------------------------- 1 | getProjectRoot() . '.git/hooks/'; 29 | } 30 | 31 | /** 32 | * Returns vendor directory 33 | * 34 | * @return string 35 | */ 36 | public function getVendorDir() 37 | { 38 | return $this->getProjectRoot() . 'vendor/'; 39 | } 40 | 41 | /** 42 | * Returns composer.json content 43 | * 44 | * @return array 45 | */ 46 | public function getComposerContent(): array 47 | { 48 | $path = $this->getProjectRoot() . 'composer.json'; 49 | 50 | return json_decode(file_get_contents($path), true); 51 | } 52 | 53 | /** 54 | * Returns composer path, throws exceptions if it is not defined 55 | * 56 | * @return string 57 | * @throws \Exception 58 | */ 59 | public function getComposerPath(): string 60 | { 61 | $crookConfig = $this->getCrookContent(); 62 | 63 | if (isset($crookConfig['composer'])) { 64 | return $crookConfig['composer']; 65 | } 66 | 67 | throw new \Exception('Undefined composer path'); 68 | } 69 | 70 | /** 71 | * Returns crooks.json configuration file path 72 | * 73 | * @return string 74 | */ 75 | public function getCrookPath(): string 76 | { 77 | return $this->getProjectRoot() . 'crook.json'; 78 | } 79 | 80 | /** 81 | * Returns crook.json content 82 | * 83 | * @return array 84 | */ 85 | public function getCrookContent(): array 86 | { 87 | $path = $this->getCrookPath(); 88 | 89 | if (!file_exists($path)) { 90 | $this->createCrookConfigFile(); 91 | } 92 | 93 | $content = file_get_contents($path); 94 | $content = !empty($content) ? $content : '{}'; 95 | 96 | return json_decode($content, true); 97 | } 98 | 99 | /** 100 | * Creates crooks.json and returns the amount of bytes 101 | * written or false, in case of error. 102 | * 103 | * @return int 104 | */ 105 | public function createCrookConfigFile(): int 106 | { 107 | $crookFile = $this->getCrookPath(); 108 | 109 | return file_put_contents($crookFile, ''); 110 | } 111 | 112 | /** 113 | * Updates crook.json configuration file 114 | * 115 | * @param array $newConf 116 | * @return bool|int 117 | */ 118 | public function update(array $newConf) 119 | { 120 | $fp = fopen($this->getCrookPath(), 'w'); 121 | 122 | return fwrite( 123 | $fp, 124 | json_encode( 125 | $newConf, 126 | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES 127 | ) 128 | ); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/crook/Hook.php: -------------------------------------------------------------------------------- 1 | config = $config; 23 | } 24 | 25 | /** 26 | * Add new hook $name with action $action 27 | * 28 | * @param $name 29 | * @param $action 30 | * @return bool 31 | * @throws \Exception 32 | */ 33 | public function add($name, $action): bool 34 | { 35 | if (!in_array($name, $this->getAvailableHooks())) { 36 | throw new \Exception('Invalid hook name: ' . $name); 37 | } 38 | 39 | $crookConf = $this->config->getCrookContent(); 40 | $crookConf[$name] = $action; 41 | 42 | return $this->config->update($crookConf); 43 | } 44 | 45 | /** 46 | * Remove $name hook from crook.json 47 | * 48 | * @param $name 49 | * @return bool|int 50 | */ 51 | public function remove($name) 52 | { 53 | $crookConf = $this->config->getCrookContent(); 54 | unset($crookConf[$name]); 55 | 56 | return $this->config->update($crookConf); 57 | } 58 | 59 | /** 60 | * Get action for $name hook 61 | * 62 | * @param $name 63 | * @return string 64 | */ 65 | public function getAction($name): string 66 | { 67 | $crookConf = $this->config->getCrookContent(); 68 | 69 | return $crookConf[$name] ?? ''; 70 | } 71 | 72 | /** 73 | * Create link from .git/hooks/$name to theHook 74 | * 75 | * @param $name 76 | * @return bool 77 | */ 78 | public function createLink($name): bool 79 | { 80 | $gitHookPath = $this->config->getGitHookDir() . $name; 81 | $theHookPath = $this->config->getProjectRoot() . 'theHook'; 82 | 83 | if (!in_array($name, $this->getAvailableHooks())) { 84 | throw new \Exception('Invalid hook name: ' . $name); 85 | } 86 | 87 | return symlink($theHookPath, $gitHookPath); 88 | } 89 | 90 | /** 91 | * Remove link from .git/hooks/$name to theHook 92 | * 93 | * @param $name 94 | * @return bool 95 | */ 96 | public function removeLink($name): bool 97 | { 98 | $gitHookPath = $this->config->getGitHookDir() . $name; 99 | 100 | return unlink($gitHookPath); 101 | } 102 | 103 | /** 104 | * Copy theHook file from package vendot to project root directory 105 | */ 106 | public function copyTheHook() 107 | { 108 | $source = $this->config->getVendorDir() . 'felipebool/crook/theHook'; 109 | $destination = $this->config->getProjectRoot() . 'theHook'; 110 | 111 | copy($source, $destination); 112 | } 113 | 114 | /** 115 | * Make theHook executable 116 | */ 117 | public function makeTheHookExecutable() 118 | { 119 | $theHookPath = $this->config->getProjectRoot() . 'theHook'; 120 | 121 | chmod($theHookPath, 0755); 122 | } 123 | 124 | private function getAvailableHooks() 125 | { 126 | return [ 127 | 'applypatch-msg', 128 | 'pre-applypatch', 129 | 'post-applypatch', 130 | 'pre-commit', 131 | 'prepare-commit-msg', 132 | 'commit-msg', 133 | 'post-commit', 134 | 'pre-rebase', 135 | 'post-checkout', 136 | 'post-merge', 137 | 'pre-push', 138 | 'pre-receive', 139 | 'update', 140 | 'post-receive', 141 | 'post-update', 142 | 'pre-auto-gc', 143 | 'post-rewrite' 144 | ]; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /tests/crook/ApplicationTest.php: -------------------------------------------------------------------------------- 1 | config = $this 15 | ->getMockBuilder('Crook\Config') 16 | ->setMethods(['getProjectRoot', 'getComposerPath']) 17 | ->getMock(); 18 | 19 | $this 20 | ->config 21 | ->method('getProjectRoot') 22 | ->willReturn(__DIR__ . '/../../'); 23 | 24 | if (file_exists(__DIR__ . '/../../.env')) { 25 | $dotenv = new Dotenv(__DIR__ . '/../../'); 26 | $dotenv->load(); 27 | } 28 | 29 | $this 30 | ->config 31 | ->method('getComposerPath') 32 | ->willReturn(getenv('COMPOSER_BIN')); 33 | } 34 | 35 | public function testPreCommitHookTypeWithNonPsrCodeRun() 36 | { 37 | $app = new Application($this->config, 'pre-commit'); 38 | $hook = new Hook($this->config); 39 | 40 | $hook->add('pre-commit', 'code-check-non-psr2'); 41 | $result = $app->run(); 42 | 43 | $this->assertContains('FOUND 3 ERRORS AFFECTING 2 LINES', $result['message']); 44 | $this->assertGreaterThan(0, $result['code']); 45 | } 46 | 47 | public function testPreCommitHookTypeWithPsrCodeRun() 48 | { 49 | $app = new Application($this->config, 'pre-commit'); 50 | $hook = new Hook($this->config); 51 | 52 | $hook->add('pre-commit', 'code-check-psr2'); 53 | $result = $app->run(); 54 | 55 | $this->assertEquals('', $result['message']); 56 | $this->assertEquals(0, $result['code']); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/crook/ConfigTest.php: -------------------------------------------------------------------------------- 1 | config = $this 14 | ->getMockBuilder('Crook\Config') 15 | ->setMethods(['getProjectRoot']) 16 | ->getMock(); 17 | 18 | $this 19 | ->config 20 | ->method('getProjectRoot') 21 | ->willReturn(__DIR__ . '/../../'); 22 | } 23 | 24 | public function testCreateCrookConfigFile() 25 | { 26 | $result = $this->config->createCrookConfigFile(); 27 | 28 | $this->assertFileExists($this->config->getCrookPath()); 29 | $this->assertGreaterThanOrEqual(0, $result); 30 | } 31 | 32 | /** 33 | * @depends testCreateCrookConfigFile 34 | */ 35 | public function testUpdate() 36 | { 37 | $newConf = [ 38 | 'pre-commit' => 'any-action' 39 | ]; 40 | 41 | $result = $this->config->update($newConf); 42 | $expected = strlen(json_encode( 43 | $newConf, 44 | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES 45 | )); 46 | 47 | $this->assertEquals($expected, $result); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/crook/HookTest.php: -------------------------------------------------------------------------------- 1 | config = $this 15 | ->getMockBuilder('Crook\Config') 16 | ->setMethods(['getProjectRoot']) 17 | ->getMock(); 18 | 19 | $this 20 | ->config 21 | ->method('getProjectRoot') 22 | ->willReturn(__DIR__ . '/../../'); 23 | } 24 | 25 | /** 26 | * @expectedException \Exception 27 | */ 28 | public function testAddInvalidHook() 29 | { 30 | $hook = new Hook($this->config); 31 | $hook->add('invalid-hook', 'any-action'); 32 | } 33 | 34 | public function testAddValidHook() 35 | { 36 | $hook = new Hook($this->config); 37 | 38 | try { 39 | $result = $hook->add('pre-commit', 'any-action'); 40 | } catch (\Exception $e) { 41 | $result = 0; 42 | } 43 | 44 | $this->assertGreaterThan(0, $result); 45 | } 46 | 47 | public function testRemovePreviouslyAddedHook() 48 | { 49 | $hook = new Hook($this->config); 50 | $hook->add('pre-commit', 'any-action'); 51 | 52 | $result = $hook->remove('pre-commit'); 53 | $this->assertGreaterThanOrEqual(0, $result); 54 | } 55 | 56 | public function testRemoveInexistentHook() 57 | { 58 | $hook = new Hook($this->config); 59 | $result = $hook->remove('inexistent-hook'); 60 | 61 | $this->assertGreaterThanOrEqual(0, $result); 62 | } 63 | 64 | public function tearDown() 65 | { 66 | $crookPath = $this->config->getCrookPath(); 67 | 68 | if (file_exists($crookPath)) { 69 | unlink($crookPath); 70 | } 71 | } 72 | 73 | public function testGetKnownAction() 74 | { 75 | $hook = new Hook($this->config); 76 | $hook->add('pre-commit', 'any-action'); 77 | 78 | $result = $hook->getAction('pre-commit'); 79 | 80 | $this->assertEquals('any-action', $result); 81 | } 82 | 83 | public function testGetUnknownAction() 84 | { 85 | $hook = new Hook($this->config); 86 | $result = $hook->getAction('pre-commit'); 87 | 88 | $this->assertEquals('', $result); 89 | } 90 | 91 | /** 92 | * @expectedException \Exception 93 | * 94 | * @throws \Exception@ 95 | */ 96 | public function testCreateInvalidLink() 97 | { 98 | $hook = new Hook($this->config); 99 | $result = $hook->createLink('invalid-hook'); 100 | } 101 | 102 | public function testCreateValidLink() 103 | { 104 | $hook = new Hook($this->config); 105 | $result = $hook->createLink('pre-commit'); 106 | 107 | $this->assertTrue($result); 108 | } 109 | 110 | /** 111 | * @depends testCreateValidLink 112 | */ 113 | public function testRemoveLink() 114 | { 115 | $hook = new Hook($this->config); 116 | $result = $hook->removeLink('pre-commit'); 117 | 118 | $this->assertTrue($result); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/dumbCode/NonPsrCompliant.php: -------------------------------------------------------------------------------- 1 | run(); 18 | } catch (\Exception $e) { 19 | exit(23); 20 | } 21 | 22 | echo $result['message']; 23 | exit($result['code']); 24 | --------------------------------------------------------------------------------