PK XAV3VK K phpunit.xml.distnu W+A
tests
src
PK XAV:
composer.locknu W+A {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "3022aec17694795060ac3d71280fbc23",
"content-hash": "3053742fe70568ac2d3264b50fad5a41",
"packages": [
{
"name": "consolidation/output-formatters",
"version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/consolidation/output-formatters.git",
"reference": "1e6c6ab49904a31c310940ec4efccf5f36e386e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/output-formatters/zipball/1e6c6ab49904a31c310940ec4efccf5f36e386e4",
"reference": "1e6c6ab49904a31c310940ec4efccf5f36e386e4",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"symfony/console": "~2.5|~3.0",
"symfony/finder": "~2.5|~3.0",
"victorjonsson/markdowndocs": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "^1.0",
"squizlabs/php_codesniffer": "2.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"Consolidation\\OutputFormatters\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Greg Anderson",
"email": "greg.1.anderson@greenknowe.org"
}
],
"description": "Format text by applying transformations provided by plug-in formatters.",
"time": "2016-11-18 23:04:31"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"time": "2015-12-27 11:43:31"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.2.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^4.4"
},
"type": "library",
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2016-09-30 07:12:33"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443",
"reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^5.2||^4.8.24"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"time": "2016-06-10 07:14:17"
},
{
"name": "psr/log",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2016-10-10 12:19:37"
},
{
"name": "symfony/console",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "c99da1119ae61e15de0e4829196b9fba6f73d065"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/c99da1119ae61e15de0e4829196b9fba6f73d065",
"reference": "c99da1119ae61e15de0e4829196b9fba6f73d065",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"symfony/debug": "~2.8|~3.0",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2016-10-06 01:44:51"
},
{
"name": "symfony/debug",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
"reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/class-loader": "~2.8|~3.0",
"symfony/http-kernel": "~2.8|~3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2016-09-06 11:02:40"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~2.8|~3.0",
"symfony/dependency-injection": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"symfony/stopwatch": "~2.8|~3.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2016-10-13 06:28:43"
},
{
"name": "symfony/finder",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
"reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2016-09-28 00:11:12"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4",
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2016-11-14 01:06:16"
},
{
"name": "victorjonsson/markdowndocs",
"version": "1.3.7",
"source": {
"type": "git",
"url": "https://github.com/victorjonsson/PHP-Markdown-Documentation-Generator.git",
"reference": "a8244617cdce4804cd94ea508c82e8d7e29a273a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/victorjonsson/PHP-Markdown-Documentation-Generator/zipball/a8244617cdce4804cd94ea508c82e8d7e29a273a",
"reference": "a8244617cdce4804cd94ea508c82e8d7e29a273a",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"symfony/console": ">=2.6"
},
"require-dev": {
"phpunit/phpunit": "3.7.23"
},
"bin": [
"bin/phpdoc-md"
],
"type": "library",
"autoload": {
"psr-0": {
"PHPDocsMD": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Jonsson",
"email": "kontakt@victorjonsson.se"
}
],
"description": "Command line tool for generating markdown-formatted class documentation",
"homepage": "https://github.com/victorjonsson/PHP-Markdown-Documentation-Generator",
"time": "2016-10-11 21:10:19"
},
{
"name": "webmozart/assert",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "bb2d123231c095735130cc8f6d31385a44c7b308"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308",
"reference": "bb2d123231c095735130cc8f6d31385a44c7b308",
"shasum": ""
},
"require": {
"php": "^5.3.3|^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"time": "2016-08-09 15:02:57"
}
],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14 21:17:01"
},
{
"name": "guzzle/guzzle",
"version": "v3.8.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.3",
"symfony/event-dispatcher": ">=2.1"
},
"replace": {
"guzzle/batch": "self.version",
"guzzle/cache": "self.version",
"guzzle/common": "self.version",
"guzzle/http": "self.version",
"guzzle/inflection": "self.version",
"guzzle/iterator": "self.version",
"guzzle/log": "self.version",
"guzzle/parser": "self.version",
"guzzle/plugin": "self.version",
"guzzle/plugin-async": "self.version",
"guzzle/plugin-backoff": "self.version",
"guzzle/plugin-cache": "self.version",
"guzzle/plugin-cookie": "self.version",
"guzzle/plugin-curlauth": "self.version",
"guzzle/plugin-error-response": "self.version",
"guzzle/plugin-history": "self.version",
"guzzle/plugin-log": "self.version",
"guzzle/plugin-md5": "self.version",
"guzzle/plugin-mock": "self.version",
"guzzle/plugin-oauth": "self.version",
"guzzle/service": "self.version",
"guzzle/stream": "self.version"
},
"require-dev": {
"doctrine/cache": "*",
"monolog/monolog": "1.*",
"phpunit/phpunit": "3.7.*",
"psr/log": "1.0.*",
"symfony/class-loader": "*",
"zendframework/zend-cache": "<2.3",
"zendframework/zend-log": "<2.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.8-dev"
}
},
"autoload": {
"psr-0": {
"Guzzle": "src/",
"Guzzle\\Tests": "tests/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Guzzle Community",
"homepage": "https://github.com/guzzle/guzzle/contributors"
}
],
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"abandoned": "guzzlehttp/guzzle",
"time": "2014-01-28 22:29:15"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"sebastian/recursion-context": "^1.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-06-07 08:13:47"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "~1.3",
"sebastian/environment": "^1.3.2",
"sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2015-06-21 13:08:43"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12 18:03:57"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2016-11-15 14:06:22"
},
{
"name": "phpunit/phpunit",
"version": "4.8.28",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/558a3a0d28b4cb7e4a593a4fbd2220e787076225",
"reference": "558a3a0d28b4cb7e4a593a4fbd2220e787076225",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "~2.1",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2016-11-14 06:25:28"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2015-10-02 06:51:40"
},
{
"name": "satooshi/php-coveralls",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/satooshi/php-coveralls.git",
"reference": "da51d304fe8622bf9a6da39a8446e7afd432115c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c",
"reference": "da51d304fe8622bf9a6da39a8446e7afd432115c",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-simplexml": "*",
"guzzle/guzzle": "^2.8|^3.0",
"php": ">=5.3.3",
"psr/log": "^1.0",
"symfony/config": "^2.1|^3.0",
"symfony/console": "^2.1|^3.0",
"symfony/stopwatch": "^2.0|^3.0",
"symfony/yaml": "^2.0|^3.0"
},
"suggest": {
"symfony/http-kernel": "Allows Symfony integration"
},
"bin": [
"bin/coveralls"
],
"type": "library",
"autoload": {
"psr-4": {
"Satooshi\\": "src/Satooshi/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kitamura Satoshi",
"email": "with.no.parachute@gmail.com",
"homepage": "https://www.facebook.com/satooshi.jp"
}
],
"description": "PHP client library for Coveralls API",
"homepage": "https://github.com/satooshi/php-coveralls",
"keywords": [
"ci",
"coverage",
"github",
"test"
],
"time": "2016-01-20 17:35:46"
},
{
"name": "sebastian/comparator",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "ce2bda23a56456f19e35d98241446b581f648c14"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ce2bda23a56456f19e35d98241446b581f648c14",
"reference": "ce2bda23a56456f19e35d98241446b581f648c14",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2016-11-17 14:39:37"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08 07:14:41"
},
{
"name": "sebastian/environment",
"version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-08-18 05:49:44"
},
{
"name": "sebastian/exporter",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2016-06-17 09:04:28"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/recursion-context",
"version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "938df7a6478e72795e5f8266cff24d06e3136f2e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/938df7a6478e72795e5f8266cff24d06e3136f2e",
"reference": "938df7a6478e72795e5f8266cff24d06e3136f2e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-15 06:55:36"
},
{
"name": "sebastian/version",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2015-06-21 13:59:46"
},
{
"name": "squizlabs/php_codesniffer",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
"reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"bin": [
"scripts/phpcs",
"scripts/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"classmap": [
"CodeSniffer.php",
"CodeSniffer/CLI.php",
"CodeSniffer/Exception.php",
"CodeSniffer/File.php",
"CodeSniffer/Fixer.php",
"CodeSniffer/Report.php",
"CodeSniffer/Reporting.php",
"CodeSniffer/Sniff.php",
"CodeSniffer/Tokens.php",
"CodeSniffer/Reports/",
"CodeSniffer/Tokenizers/",
"CodeSniffer/DocGenerators/",
"CodeSniffer/Standards/AbstractPatternSniff.php",
"CodeSniffer/Standards/AbstractScopeSniff.php",
"CodeSniffer/Standards/AbstractVariableSniff.php",
"CodeSniffer/Standards/IncorrectPatternException.php",
"CodeSniffer/Standards/Generic/Sniffs/",
"CodeSniffer/Standards/MySource/Sniffs/",
"CodeSniffer/Standards/PEAR/Sniffs/",
"CodeSniffer/Standards/PSR1/Sniffs/",
"CodeSniffer/Standards/PSR2/Sniffs/",
"CodeSniffer/Standards/Squiz/Sniffs/",
"CodeSniffer/Standards/Zend/Sniffs/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2016-09-01 23:53:02"
},
{
"name": "symfony/config",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "949e7e846743a7f9e46dc50eb639d5fde1f53341"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/949e7e846743a7f9e46dc50eb639d5fde1f53341",
"reference": "949e7e846743a7f9e46dc50eb639d5fde1f53341",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"symfony/filesystem": "~2.8|~3.0"
},
"suggest": {
"symfony/yaml": "To use the yaml reference dumper"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2016-09-25 08:27:07"
},
{
"name": "symfony/filesystem",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "0565b61bf098cb4dc09f4f103f033138ae4f42c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/0565b61bf098cb4dc09f4f103f033138ae4f42c6",
"reference": "0565b61bf098cb4dc09f4f103f033138ae4f42c6",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2016-10-18 04:30:12"
},
{
"name": "symfony/stopwatch",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/bb42806b12c5f89db4ebf64af6741afe6d8457e1",
"reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Stopwatch\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2016-06-29 05:41:56"
},
{
"name": "symfony/yaml",
"version": "v3.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27",
"reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-10-24 18:41:13"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.4.0"
},
"platform-dev": []
}
PK XAVƻ
.editorconfignu W+A # This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.php]
indent_style = space
indent_size = 4
PK XAV1 1 LICENSEnu W+A Copyright (c) 2016 Consolidation Org Developers
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
PK XAVѩS S CONTRIBUTING.mdnu W+A # Contributing to Consolidation
Thank you for your interest in contributing to the Consolidation effort! Consolidation aims to provide reusable, loosely-coupled components useful for building command-line tools. Consolidation is built on top of Symfony Console, but aims to separate the tool from the implementation details of Symfony.
Here are some of the guidelines you should follow to make the most of your efforts:
## Code Style Guidelines
Consolidation adheres to the [PSR-2 Coding Style Guide](http://www.php-fig.org/psr/psr-2/) for PHP code.
## Pull Request Guidelines
Every pull request is run through:
- phpcs -n --standard=PSR2 src
- phpunit
- [Scrutinizer](https://scrutinizer-ci.com/g/consolidation/annotated-command/)
It is easy to run the unit tests and code sniffer locally; just run:
- composer cs
To run the code beautifier, which will fix many of the problems reported by phpcs:
- composer cbf
These two commands (`composer cs` and `composer cbf`) are defined in the `scripts` section of [composer.json](composer.json).
After submitting a pull request, please examine the Scrutinizer report. It is not required to fix all Scrutinizer issues; you may ignore recommendations that you disagree with. The spacing patches produced by Scrutinizer do not conform to PSR2 standards, and therefore should never be applied. DocBlock patches may be applied at your discression. Things that Scrutinizer identifies as a bug nearly always need to be addressed.
Pull requests must pass phpcs and phpunit in order to be merged; ideally, new functionality will also include new unit tests.
PK XAV0~F .travis.ymlnu W+A language: php
branches:
# Only test the master branch and SemVer tags.
only:
- master
- /^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+.*$/
matrix:
include:
- php: 7.0
env: dependencies=highest
- php: 5.6
- php: 5.5
- php: 5.4
env: dependencies=lowest
sudo: false
cache:
directories:
- $HOME/.composer/cache
before_script:
- if [ -z "$dependencies" ]; then composer install --prefer-dist; fi;
- if [ "$dependencies" = "lowest" ]; then composer update --prefer-dist --prefer-lowest -n; fi;
- if [ "$dependencies" = "highest" ]; then composer update --prefer-dist -n; fi;
script:
- vendor/bin/phpunit
- vendor/bin/phpcs --standard=PSR2 -n src
after_success:
- travis_retry php vendor/bin/coveralls -v
PK XAV#` .github/pull_request_template.mdnu W+A ### Disposition
This pull request:
- [ ] Fixes a bug
- [ ] Adds a feature
- [ ] Breaks backwards compatibility
- [ ] Has tests that cover changes
### Summary
Short overview of what changed.
### Description
Any additional information.
PK XAV .github/issue_template.mdnu W+A ### Steps to reproduce
What did you do?
### Expected behavior
Tell us what should happen
### Actual behavior
Tell us what happens instead
### System Configuration
Which O.S. and PHP version are you using?
PK XAVB^&, ,
composer.jsonnu W+A {
"name": "consolidation/annotated-command",
"description": "Initialize Symfony Console commands from annotated command class methods.",
"license": "MIT",
"authors": [
{
"name": "Greg Anderson",
"email": "greg.1.anderson@greenknowe.org"
}
],
"autoload":{
"psr-4":{
"Consolidation\\AnnotatedCommand\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Consolidation\\TestUtils\\": "tests/src"
}
},
"require": {
"php": ">=5.4.0",
"consolidation/output-formatters": "^3.1.3",
"psr/log": "~1",
"symfony/console": "^2.8|~3",
"symfony/event-dispatcher": "^2.5|~3",
"symfony/finder": "^2.5|~3",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "^1.0",
"squizlabs/php_codesniffer": "^2.7"
},
"scripts": {
"cs": "phpcs --standard=PSR2 -n src",
"cbf": "phpcbf --standard=PSR2 -n src",
"unit": "SHELL_INTERACTIVE=true phpunit --colors=always",
"test": [
"@unit",
"@cs"
]
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
}
}
PK XAVD)
)
CHANGELOG.mdnu W+A # Change Log
### 2.0.1 ~ 2.0.3 - 14 November 2016
- Fix version requirement for output-formatters in composer.json
- Use output-formatters ~3
- Move php_codesniffer back to require-dev (moved to require by mistake)
### 2.0.0 - 30 September 2016
- **Breaking** Hooks with no command name now apply to all commands defined in the same class. This is a change of behavior from the 1.x branch, where hooks with no command name applied to a command with the same method name in a *different* class.
- **Breaking** The interfaces ValidatorInterface, ProcessResultInterface and AlterResultInterface have been updated to be passed a CommandData object, which contains an Input and Output object, plus the AnnotationData.
- **Breaking** The Symfony Command Event hook has been renamed to COMMAND_EVENT. There is a new COMMAND hook that behaves like the existing Drush command hook (i.e. the post-command event is called after the primary command method runs).
- Add an accessor function AnnotatedCommandFactory::setIncludeAllPublicMethods() to control whether all public methods of a command class, or only those with a @command annotation will be treated as commands. Default remains to treat all public methods as commands. The parameters to AnnotatedCommandFactory::createCommandsFromClass() and AnnotatedCommandFactory::createCommandsFromClassInfo() still behave the same way, but are deprecated. If omitted, the value set by the accessor will be used.
- @option and @usage annotations provided with @hook methods will be added to the help text of the command they hook. This should be done if a hook needs to add a new option, e.g. to control the behavior of the hook.
- @option annotations can now be either `@option type $name description`, or just `@option name description`.
- `@hook option` can be used to programatically add options to a command.
- A CommandInfoAltererInterface can be added via AnnotatedCommandFactory::addCommandInfoAlterer(); it will be given the opportunity to adjust every CommandInfo object parsed from a command file prior to the creation of commands.
- AnnotatedCommandFactory::setIncludeAllPublicMethods(false) may be used to require methods to be annotated with @commnad in order to be considered commands. This is in preference to the existing parameters of various command-creation methods of AnnotatedCommandFactory, which are now all deprecated in favor of this setter function.
- If a --field option is given, it will also force the output format to 'string'.
- Setter methods more consistently return $this.
- Removed PassThroughArgsInput. This class was unnecessary.
### 1.4.0 - 13 September 2016
- Add basic annotation hook capability, to allow hook functions to be attached to commands with arbitrary annotations.
### 1.3.0 - 8 September 2016
- Add ComandFileDiscovery::setSearchDepth(). The search depth applies to each search location, unless there are no search locations, in which case it applies to the base directory.
### 1.2.0 - 2 August 2016
- Support both the 2.x and 3.x versions of phpdocumentor/reflection-docblock.
- Support php 5.4.
- **Bug** Do not allow an @param docblock comment for the options to override the meaning of the options.
### 1.1.0 - 6 July 2016
- Introduce AnnotatedCommandFactory::createSelectedCommandsFromClassInfo() method.
### 1.0.0 - 20 May 2016
- First stable release.
PK XAVWV WV tests/testFullStack.phpnu W+A application = new ApplicationWithTerminalWidth('TestApplication', '0.0.0');
$this->commandFactory = new AnnotatedCommandFactory();
$alterOptionsEventManager = new AlterOptionsCommandEvent($this->application);
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
$eventDispatcher->addSubscriber($alterOptionsEventManager);
$this->application->setDispatcher($eventDispatcher);
$this->application->setAutoExit(false);
}
function testValidFormats()
{
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$commandInfo = new CommandInfo('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$this->assertEquals('example:table', $commandInfo->getName());
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
}
function testAutomaticOptions()
{
$commandFileInstance = new \Consolidation\TestUtils\alpha\AlphaCommandFile;
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$this->commandFactory->commandProcessor()->setFormatterManager($formatter);
$commandInfo = $this->commandFactory->createCommandInfo($commandFileInstance, 'exampleTable');
$command = $this->commandFactory->createCommand($commandInfo, $commandFileInstance);
$this->application->add($command);
$containsList =
[
'--format[=FORMAT] Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml [default: "table"]',
'--fields[=FIELDS] Available fields: I (first), II (second), III (third) [default: ""]',
];
$this->assertRunCommandViaApplicationContains('help example:table', $containsList);
}
function testCommandsAndHooks()
{
// First, search for commandfiles in the 'alpha'
// directory. Note that this same functionality
// is tested more thoroughly in isolation in
// testCommandFileDiscovery.php
$discovery = new CommandFileDiscovery();
$discovery
->setSearchPattern('*CommandFile.php')
->setIncludeFilesAtBase(false)
->setSearchLocations(['alpha']);
chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$hookManager = new HookManager();
$terminalWidthOption = new PrepareTerminalWidthOption();
$terminalWidthOption->setApplication($this->application);
$commandProcessor = new CommandProcessor($hookManager);
$commandProcessor->setFormatterManager($formatter);
$commandProcessor->addPrepareFormatter($terminalWidthOption);
// Create a new factory, and load all of the files
// discovered above. The command factory class is
// tested in isolation in testAnnotatedCommandFactory.php,
// but this is the only place where
$factory = new AnnotatedCommandFactory();
$factory->setCommandProcessor($commandProcessor);
// $factory->addListener(...);
$factory->setIncludeAllPublicMethods(false);
$this->addDiscoveredCommands($factory, $commandFiles);
$this->assertRunCommandViaApplicationContains('list', ['example:table'], ['additional:option', 'without:annotations']);
$this->assertTrue($this->application->has('example:table'));
$this->assertFalse($this->application->has('without:annotations'));
// Fetch a reference to the 'example:table' command and test its valid format types
$exampleTableCommand = $this->application->find('example:table');
$returnType = $exampleTableCommand->getReturnType();
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $returnType);
$validFormats = $formatter->validFormats($returnType);
$this->assertEquals('csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml', implode(',', $validFormats));
// Control: run commands without hooks.
$this->assertRunCommandViaApplicationEquals('always:fail', 'This command always fails.', 13);
$this->assertRunCommandViaApplicationEquals('simulated:status', '42');
$this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World.');
$this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphabet');
$this->assertRunCommandViaApplicationEquals('example:echo a b c', "a\tb\tc");
$this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.');
$this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument', 'Hello, world');
$this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument Joe', 'Hello, Joe');
// Add some hooks.
$factory->hookManager()->addValidator(new ExampleValidator());
$factory->hookManager()->addResultProcessor(new ExampleResultProcessor());
$factory->hookManager()->addAlterResult(new ExampleResultAlterer());
$factory->hookManager()->addStatusDeterminer(new ExampleStatusDeterminer());
$factory->hookManager()->addOutputExtractor(new ExampleOutputExtractor());
// Run the same commands as before, and confirm that results
// are different now that the hooks are in place.
$this->assertRunCommandViaApplicationEquals('simulated:status', '', 42);
$this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World!');
$this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphareplaced');
$this->assertRunCommandViaApplicationEquals('example:echo a b c', 'a,b,c');
$this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.');
$expected = <<assertRunCommandViaApplicationEquals('example:table', $expected);
$expected = <<assertRunCommandViaApplicationEquals('example:table --fields=III,II', $expected);
$expectedSingleField = <<assertRunCommandViaApplicationEquals('example:table --field=II', $expectedSingleField);
// Check the help for the example table command and see if the options
// from the alter hook were added. We expect that we should not see
// any of the information from the alter hook in the 'beta' folder yet.
$this->assertRunCommandViaApplicationContains('help example:table',
[
'Option added by @hook option example:table',
'example:table --french',
'Add a row with French numbers.'
],
[
'chinese',
'kanji',
]
);
$expectedOutputWithFrench = <<assertRunCommandViaApplicationEquals('example:table --french', $expectedOutputWithFrench);
$expectedAssociativeListTable = <<assertRunCommandViaApplicationEquals('example:list', $expectedAssociativeListTable);
$this->assertRunCommandViaApplicationEquals('example:list --field=sftp_command', 'sftp -o Port=2222 dev@appserver.dev.drush.in');
$this->assertRunCommandViaApplicationEquals('get:serious', 'very serious');
$this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1);
$this->assertRunCommandViaApplicationContains('help example:wrap',
[
'Test word wrapping',
'[default: "table"]',
]
);
$expectedUnwrappedOutput = <<application->setWidthAndHeight(0, 0);
$this->assertRunCommandViaApplicationEquals('example:wrap', $expectedUnwrappedOutput);
$expectedWrappedOutput = <<application->setWidthAndHeight(42, 24);
$this->assertRunCommandViaApplicationEquals('example:wrap', $expectedWrappedOutput);
}
function testCommandsAndHooksIncludeAllPublicMethods()
{
// First, search for commandfiles in the 'alpha'
// directory. Note that this same functionality
// is tested more thoroughly in isolation in
// testCommandFileDiscovery.php
$discovery = new CommandFileDiscovery();
$discovery
->setSearchPattern('*CommandFile.php')
->setIncludeFilesAtBase(false)
->setSearchLocations(['alpha']);
chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$hookManager = new HookManager();
$commandProcessor = new CommandProcessor($hookManager);
$commandProcessor->setFormatterManager($formatter);
// Create a new factory, and load all of the files
// discovered above. The command factory class is
// tested in isolation in testAnnotatedCommandFactory.php,
// but this is the only place where
$factory = new AnnotatedCommandFactory();
$factory->setCommandProcessor($commandProcessor);
// $factory->addListener(...);
// Now we will once again add all commands, this time including all
// public methods. The command 'withoutAnnotations' should now be found.
$factory->setIncludeAllPublicMethods(true);
$this->addDiscoveredCommands($factory, $commandFiles);
$this->assertTrue($this->application->has('without:annotations'));
$this->assertRunCommandViaApplicationContains('list', ['example:table', 'without:annotations'], ['alter:formatters']);
$this->assertRunCommandViaApplicationEquals('get:serious', 'very serious');
$this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1);
}
function testCommandsAndHooksWithBetaFolder()
{
// First, search for commandfiles in the 'alpha'
// directory. Note that this same functionality
// is tested more thoroughly in isolation in
// testCommandFileDiscovery.php
$discovery = new CommandFileDiscovery();
$discovery
->setSearchPattern('*CommandFile.php')
->setIncludeFilesAtBase(false)
->setSearchLocations(['alpha', 'beta']);
chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$hookManager = new HookManager();
$commandProcessor = new CommandProcessor($hookManager);
$commandProcessor->setFormatterManager($formatter);
// Create a new factory, and load all of the files
// discovered above. The command factory class is
// tested in isolation in testAnnotatedCommandFactory.php,
// but this is the only place where
$factory = new AnnotatedCommandFactory();
$factory->setCommandProcessor($commandProcessor);
// $factory->addListener(...);
$factory->setIncludeAllPublicMethods(true);
$this->addDiscoveredCommands($factory, $commandFiles);
// A few asserts, to make sure that our hooks all get registered.
$allRegisteredHooks = $hookManager->getAllHooks();
$registeredHookNames = array_keys($allRegisteredHooks);
sort($registeredHookNames);
$this->assertEquals('*,example:table', implode(',', $registeredHookNames));
$allHooksForExampleTable = $allRegisteredHooks['example:table'];
$allHookPhasesForExampleTable = array_keys($allHooksForExampleTable);
sort($allHookPhasesForExampleTable);
$this->assertEquals('alter,option', implode(',', $allHookPhasesForExampleTable));
$this->assertContains('alterFormattersChinese', var_export($allHooksForExampleTable, true));
$alterHooksForExampleTable = $this->callProtected($hookManager, 'getHooks', [['example:table'], 'alter']);
$this->assertContains('alterFormattersKanji', var_export($alterHooksForExampleTable, true));
$allHooksForAnyCommand = $allRegisteredHooks['*'];
$allHookPhasesForAnyCommand = array_keys($allHooksForAnyCommand);
sort($allHookPhasesForAnyCommand);
$this->assertEquals('alter', implode(',', $allHookPhasesForAnyCommand));
$this->assertContains('alterFormattersKanji', var_export($allHooksForAnyCommand, true));
// Help should have the information from the hooks in the 'beta' folder
$this->assertRunCommandViaApplicationContains('help example:table',
[
'Option added by @hook option example:table',
'example:table --french',
'Add a row with French numbers.',
'chinese',
'kanji',
]
);
// Confirm that the "unavailable" command is now available
$this->assertTrue($this->application->has('unavailable:command'));
$expectedOutputWithChinese = <<assertRunCommandViaApplicationEquals('example:table --chinese', $expectedOutputWithChinese);
$expectedOutputWithKanji = <<assertRunCommandViaApplicationEquals('example:table --kanji', $expectedOutputWithKanji);
}
public function addDiscoveredCommands($factory, $commandFiles) {
foreach ($commandFiles as $path => $commandClass) {
$this->assertFileExists($path);
if (!class_exists($commandClass)) {
include $path;
}
$commandInstance = new $commandClass();
$commandList = $factory->createCommandsFromClass($commandInstance);
foreach ($commandList as $command) {
$this->application->add($command);
}
}
}
function assertRunCommandViaApplicationEquals($cmd, $expectedOutput, $expectedStatusCode = 0)
{
$input = new StringInput($cmd);
$output = new BufferedOutput();
$statusCode = $this->application->run($input, $output);
$commandOutput = trim($output->fetch());
$expectedOutput = $this->simplifyWhitespace($expectedOutput);
$commandOutput = $this->simplifyWhitespace($commandOutput);
$this->assertEquals($expectedOutput, $commandOutput);
$this->assertEquals($expectedStatusCode, $statusCode);
}
function assertRunCommandViaApplicationContains($cmd, $containsList, $doesNotContainList = [], $expectedStatusCode = 0)
{
$input = new StringInput($cmd);
$output = new BufferedOutput();
$containsList = (array) $containsList;
$statusCode = $this->application->run($input, $output);
$commandOutput = trim($output->fetch());
$commandOutput = $this->simplifyWhitespace($commandOutput);
foreach ($containsList as $expectedToContain) {
$this->assertContains($this->simplifyWhitespace($expectedToContain), $commandOutput);
}
foreach ($doesNotContainList as $expectedToNotContain) {
$this->assertNotContains($this->simplifyWhitespace($expectedToNotContain), $commandOutput);
}
$this->assertEquals($expectedStatusCode, $statusCode);
}
function simplifyWhitespace($data)
{
return trim(preg_replace('#[ \t]+$#m', '', $data));
}
function callProtected($object, $method, $args = [])
{
$r = new \ReflectionMethod($object, $method);
$r->setAccessible(true);
return $r->invokeArgs($object, $args);
}
}
class ExampleValidator implements ValidatorInterface
{
public function validate(CommandData $commandData)
{
$args = $commandData->arguments();
if (isset($args['one']) && ($args['one'] == 'bet')) {
$commandData->input()->setArgument('one', 'replaced');
return $args;
}
}
}
class ExampleResultProcessor implements ProcessResultInterface
{
public function process($result, CommandData $commandData)
{
if (is_array($result) && array_key_exists('item-list', $result)) {
return implode(',', $result['item-list']);
}
}
}
class ExampleResultAlterer implements AlterResultInterface
{
public function process($result, CommandData $commandData)
{
if (is_string($result) && ($result == 'Hello, World.')) {
return 'Hello, World!';
}
}
}
class ExampleStatusDeterminer implements StatusDeterminerInterface
{
public function determineStatusCode($result)
{
if (is_array($result) && array_key_exists('status-code', $result)) {
return $result['status-code'];
}
}
}
class ExampleOutputExtractor implements ExtractOutputInterface
{
public function extractOutput($result)
{
if (is_array($result) && array_key_exists('message', $result)) {
return $result['message'];
}
}
}
PK XAVq\ % tests/testAnnotatedCommandFactory.phpnu W+A commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testArithmatic');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:arithmatic', $command->getName());
$this->assertEquals('This is the test:arithmatic command', $command->getDescription());
$this->assertEquals("This command will add one and two. If the --negate flag\nis provided, then the result is negated.", $command->getHelp());
$this->assertEquals('arithmatic', implode(',', $command->getAliases()));
$this->assertEquals('test:arithmatic [--negate] [--] ', $command->getSynopsis());
$this->assertEquals('test:arithmatic 2 2 --negate', implode(',', $command->getUsages()));
$input = new StringInput('arithmatic 2 3 --negate');
$this->assertRunCommandViaApplicationEquals($command, $input, '-5');
}
/**
* Test CommandInfo command annotation altering.
*/
function testAnnotatedCommandInfoAlteration()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$annotationData = $command->getAnnotationData();
$this->assertTrue($annotationData->has('arbitrary'));
$this->assertFalse($annotationData->has('dynamic'));
$this->commandFactory->addCommandInfoAlterer(new ExampleCommandInfoAlterer());
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$annotationData = $command->getAnnotationData();
$this->assertTrue($annotationData->has('arbitrary'));
$this->assertTrue($annotationData->has('dynamic'));
}
function testMyCatCommand()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('my:cat', $command->getName());
$this->assertEquals('This is the my:cat command', $command->getDescription());
$this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp());
$this->assertEquals('c', implode(',', $command->getAliases()));
$this->assertEquals('my:cat [--flip] [--] []', $command->getSynopsis());
$this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages()));
$input = new StringInput('my:cat bet alpha --flip');
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet');
}
function testDefaultsCommand()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaults');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('defaults', $command->getName());
$this->assertEquals('Test default values in arguments', $command->getDescription());
$input = new StringInput('defaults');
$this->assertRunCommandViaApplicationEquals($command, $input, 'nothing provided');
$input = new StringInput('defaults ichi');
$this->assertRunCommandViaApplicationEquals($command, $input, 'only ichi');
$input = new StringInput('defaults I II');
$this->assertRunCommandViaApplicationEquals($command, $input, 'I and II');
}
function testCommandWithNoOptions()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoOptions');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('command:with-no-options', $command->getName());
$this->assertEquals('This is a command with no options', $command->getDescription());
$this->assertEquals("This command will concatenate two parameters.", $command->getHelp());
$this->assertEquals('nope', implode(',', $command->getAliases()));
$this->assertEquals('command:with-no-options []', $command->getSynopsis());
$this->assertEquals('command:with-no-options alpha bet', implode(',', $command->getUsages()));
$input = new StringInput('command:with-no-options something');
$this->assertRunCommandViaApplicationEquals($command, $input, 'somethingdefault');
}
function testCommandWithNoArguments()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoArguments');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('command:with-no-arguments', $command->getName());
$this->assertEquals('This command has no arguments--only options', $command->getDescription());
$this->assertEquals("Return a result only if not silent.", $command->getHelp());
$this->assertEquals('command:with-no-arguments [-s|--silent]', $command->getSynopsis());
$input = new StringInput('command:with-no-arguments');
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world');
$input = new StringInput('command:with-no-arguments -s');
$this->assertRunCommandViaApplicationEquals($command, $input, '');
$input = new StringInput('command:with-no-arguments --silent');
$this->assertRunCommandViaApplicationEquals($command, $input, '');
}
function testCommandWithShortcutOnAnnotation()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'shortcutOnAnnotation');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('shortcut:on-annotation', $command->getName());
$this->assertEquals('Shortcut on annotation', $command->getDescription());
$this->assertEquals("This command defines the option shortcut on the annotation instead of in the options array.", $command->getHelp());
$this->assertEquals('shortcut:on-annotation [-s|--silent]', $command->getSynopsis());
$input = new StringInput('shortcut:on-annotation');
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world');
$input = new StringInput('shortcut:on-annotation -s');
$this->assertRunCommandViaApplicationEquals($command, $input, '');
$input = new StringInput('shortcut:on-annotation --silent');
$this->assertRunCommandViaApplicationEquals($command, $input, '');
}
function testState()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile('secret secret');
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testState');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:state', $command->getName());
$input = new StringInput('test:state');
$this->assertRunCommandViaApplicationEquals($command, $input, 'secret secret');
}
function testPassthroughArray()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPassthrough');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:passthrough', $command->getName());
$input = new StringInput('test:passthrough a b c -- x y z');
$this->assertRunCommandViaApplicationEquals($command, $input, 'a,b,c,x,y,z');
}
function testPassThroughNonArray()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$input = new StringInput('my:join bet --flip -- x y z');
$this->assertRunCommandViaApplicationEquals($command, $input, 'zyxbet');
// Can't look at 'hasOption' until after the command initializes the
// option, because Symfony.
$this->assertTrue($input->hasOption('flip'));
}
function testPassThroughWithInputManipulation()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$input = new StringInput('my:join bet --repeat=2 -- x y z');
$this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz');
// Symfony does not allow us to manipulate the options via setOption until
// the definition from the command object has been set up.
$input->setOption('repeat', 3);
$this->assertEquals(3, $input->getOption('repeat'));
$input->setArgument(0, 'q');
// Manipulating $input does not work -- the changes are not effective.
// The end result here should be 'qx y yqx y yqx y y'
$this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz');
}
function testHookedCommand()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookTestHook', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:hook', $command->getName());
$input = new StringInput('test:hook bar');
$this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>');
}
function testPostCommandCalledAfterCommand()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPostCommandHook');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('post-command test:post-command', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::POST_COMMAND_HOOK]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookTestPostCommandHook', $hookCallback[0][1]);
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPreCommandHook');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('pre-command test:post-command', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::PRE_COMMAND_HOOK]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookTestPreCommandHook', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPostCommand');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:post-command', $command->getName());
$input = new StringInput('test:post-command bar');
$this->assertRunCommandViaApplicationEquals($command, $input, "foo\nbar\nbaz", 0, $this->commandFileInstance);
}
function testHookAllCommands()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleHookAllCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterAllCommands');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('alter', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('Consolidation\TestUtils\ExampleHookAllCommandFile', [HookManager::ALTER_RESULT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('alterAllCommands', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'doCat');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('do:cat', $command->getName());
$input = new StringInput('do:cat bar');
$this->assertRunCommandViaApplicationEquals($command, $input, '*** bar ***');
}
function testAnnotatedHookedCommand()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestAnnotatedHook');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('alter @hookme', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('@hookme', [HookManager::ALTER_RESULT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookTestAnnotatedHook', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testAnnotationHook');
$annotationData = $commandInfo->getRawAnnotations();
$this->assertEquals('hookme,before,after', implode(',', $annotationData->keys()));
$this->assertEquals('@hookme,@before,@after', implode(',', array_map(function ($item) { return "@$item"; }, $annotationData->keys())));
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:annotation-hook', $command->getName());
$input = new StringInput('test:annotation-hook baz');
$this->assertRunCommandViaApplicationEquals($command, $input, '>(baz)<');
}
function testHookHasCommandAnnotation()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookAddCommandName');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('alter @addmycommandname', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('@addmycommandname', [HookManager::ALTER_RESULT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookAddCommandName', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMe');
$annotationData = $commandInfo->getRawAnnotations();
$this->assertEquals('command,addmycommandname', implode(',', $annotationData->keys()));
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('alter-me', $command->getName());
$input = new StringInput('alter-me');
$this->assertRunCommandViaApplicationEquals($command, $input, 'splendiferous from alter-me');
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMeToo');
$annotationData = $commandInfo->getRawAnnotations();
$this->assertEquals('addmycommandname', implode(',', $annotationData->keys()));
$annotationData = $commandInfo->getAnnotations();
$this->assertEquals('addmycommandname,command', implode(',', $annotationData->keys()));
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('alter:me-too', $command->getName());
$input = new StringInput('alter:me-too');
$this->assertRunCommandViaApplicationEquals($command, $input, 'fantabulous from alter:me-too');
}
function testHookedCommandWithHookAddedLater()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:hook', $command->getName());
// Run the command once without the hook
$input = new StringInput('test:hook foo');
$this->assertRunCommandViaApplicationEquals($command, $input, '[foo]');
// Register the hook and run the command again
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook'));
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]);;
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('hookTestHook', $hookCallback[0][1]);
$input = new StringInput('test:hook bar');
$this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>');
}
function testInitializeHook()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'initializeTestHello');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals($hookInfo->getAnnotation('hook'), 'init test:hello');
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INITIALIZE]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('initializeTestHello', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:hello', $command->getName());
$commandGetNames = $this->callProtected($command, 'getNames');
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'init');
$this->assertTrue($hookCallback != null);
$this->assertEquals('initializeTestHello', $hookCallback[0][1]);
$input = new StringInput('test:hello');
$this->assertRunCommandViaApplicationEquals($command, $input, "Hello, Huey.");
}
function testCommandEventHook()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandEventTestHello');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals($hookInfo->getAnnotation('hook'), 'command-event test:hello');
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::COMMAND_EVENT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('commandEventTestHello', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:hello', $command->getName());
$commandGetNames = $this->callProtected($command, 'getNames');
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'command-event');
$this->assertTrue($hookCallback != null);
$this->assertEquals('commandEventTestHello', $hookCallback[0][1]);
$input = new StringInput('test:hello Pluto');
$this->assertRunCommandViaApplicationEquals($command, $input, "Here comes Pluto!\nHello, Pluto.");
}
function testInteractAndValidate()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
$this->commandFactory = new AnnotatedCommandFactory();
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'interactTestHello');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals($hookInfo->getAnnotation('hook'), 'interact test:hello');
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'validateTestHello');
$this->assertTrue($hookInfo->hasAnnotation('hook'));
$this->assertEquals($hookInfo->getAnnotation('hook'), 'validate test:hello');
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::ARGUMENT_VALIDATOR]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('validateTestHello', $hookCallback[0][1]);
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INTERACT]);
$this->assertTrue($hookCallback != null);
$this->assertEquals(1, count($hookCallback));
$this->assertEquals(2, count($hookCallback[0]));
$this->assertTrue(is_callable($hookCallback[0]));
$this->assertEquals('interactTestHello', $hookCallback[0][1]);
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('test:hello', $command->getName());
$commandGetNames = $this->callProtected($command, 'getNames');
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
$testInteractInput = new StringInput('test:hello');
$definition = new \Symfony\Component\Console\Input\InputDefinition(
[
new \Symfony\Component\Console\Input\InputArgument('application', \Symfony\Component\Console\Input\InputArgument::REQUIRED),
new \Symfony\Component\Console\Input\InputArgument('who', \Symfony\Component\Console\Input\InputArgument::REQUIRED),
]
);
$testInteractInput->bind($definition);
$testInteractOutput = new BufferedOutput();
$command->commandProcessor()->interact(
$testInteractInput,
$testInteractOutput,
$commandGetNames,
$command->getAnnotationData()
);
$this->assertEquals('Goofey', $testInteractInput->getArgument('who'));
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'interact');
$this->assertTrue($hookCallback != null);
$this->assertEquals('interactTestHello', $hookCallback[0][1]);
$input = new StringInput('test:hello "Mickey Mouse"');
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Mickey Mouse.');
$input = new StringInput('test:hello');
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Goofey.');
$input = new StringInput('test:hello "Donald Duck"');
$this->assertRunCommandViaApplicationEquals($command, $input, "I won't say hello to Donald Duck.", 1);
$input = new StringInput('test:hello "Drumph"');
$this->assertRunCommandViaApplicationEquals($command, $input, "Irrational value error.", 1);
// Try the last test again with a display error function installed.
$this->commandFactory->commandProcessor()->setDisplayErrorFunction(
function ($output, $message) {
$output->writeln("*** $message ****");
}
);
$input = new StringInput('test:hello "Drumph"');
$this->assertRunCommandViaApplicationEquals($command, $input, "*** Irrational value error. ****", 1);
}
function callProtected($object, $method, $args = [])
{
$r = new \ReflectionMethod($object, $method);
$r->setAccessible(true);
return $r->invokeArgs($object, $args);
}
function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0)
{
$output = new BufferedOutput();
if ($this->commandFileInstance && method_exists($this->commandFileInstance, 'setOutput')) {
$this->commandFileInstance->setOutput($output);
}
$application = new Application('TestApplication', '0.0.0');
$alterOptionsEventManager = new AlterOptionsCommandEvent($application);
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
$eventDispatcher->addSubscriber($alterOptionsEventManager);
$application->setDispatcher($eventDispatcher);
$application->setAutoExit(false);
$application->add($command);
$statusCode = $application->run($input, $output);
$commandOutput = trim($output->fetch());
$this->assertEquals($expectedOutput, $commandOutput);
$this->assertEquals($expectedStatusCode, $statusCode);
}
}
PK XAVg " tests/testCommandFileDiscovery.phpnu W+A setSearchPattern('*CommandFile.php')
->setSearchLocations(['alpha']);
chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
$commandFilePaths = array_keys($commandFiles);
$commandFileNamespaces = array_values($commandFiles);
// Ensure that the command files that we expected to
// find were all found. We don't find anything in
// 'beta' because only 'alpha' is in the search path.
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
$this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/Inclusive/IncludedCommandFile.php', $commandFilePaths);
// Make sure that there are no additional items found.
$this->assertEquals(4, count($commandFilePaths));
// Ensure that the command file namespaces that we expected
// to be generated all match.
$this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\alpha\Inclusive\IncludedCommandFile', $commandFileNamespaces);
// We do not need to test for additional namespace items, because we
// know that the length of the array_keys must be the same as the
// length of the array_values.
}
function testDeepCommandDiscovery()
{
$discovery = new CommandFileDiscovery();
$discovery
->setSearchPattern('*CommandFile.php')
->setSearchDepth(1)
->setSearchLocations([]);
chdir(__DIR__);
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
$commandFilePaths = array_keys($commandFiles);
$commandFileNamespaces = array_values($commandFiles);
// Ensure that the command files that we expected to
// find were all found. We find both 'alpha' and 'beta'
// items because the search locations is empty, which
// causes the search at the base directory to be deep.
// We do not find alpha/Inclusive, though, as the search
// depth is only 2, which excludes directories that are
// three levels deep.
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
$this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths);
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
$this->assertContains('./src/beta/BetaCommandFile.php', $commandFilePaths);
// Make sure that there are no additional items found.
$this->assertEquals(4, count($commandFilePaths));
// Ensure that the command file namespaces that we expected
// to be generated all match.
$this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces);
$this->assertContains('\Consolidation\TestUtils\beta\BetaCommandFile', $commandFileNamespaces);
// We do not need to test for additional namespace items, because we
// know that the length of the array_keys must be the same as the
// length of the array_values.
}
}
PK XAVV V tests/testCommandInfo.phpnu W+A $value) {
if (!is_string($value)) {
$value = var_export($value, true);
}
$result[] = "{$key}=>{$value}";
}
return implode("\n", $result);
}
/**
* Test CommandInfo command annotation parsing.
*/
function testParsing()
{
$commandInfo = new CommandInfo('\Consolidation\TestUtils\ExampleCommandFile', 'testArithmatic');
$this->assertEquals('test:arithmatic', $commandInfo->getName());
$this->assertEquals(
'This is the test:arithmatic command',
$commandInfo->getDescription()
);
$this->assertEquals(
"This command will add one and two. If the --negate flag\nis provided, then the result is negated.",
$commandInfo->getHelp()
);
$this->assertEquals('arithmatic', implode(',', $commandInfo->getAliases()));
$this->assertEquals(
'2 2 --negate=>Add two plus two and then negate.',
$this->flattenArray($commandInfo->getExampleUsages())
);
$this->assertEquals(
'The first number to add.',
$commandInfo->arguments()->getDescription('one')
);
$this->assertEquals(
'The other number to add.',
$commandInfo->arguments()->getDescription('two')
);
$this->assertEquals(
'Whether or not the result should be negated.',
$commandInfo->options()->getDescription('negate')
);
}
function testReturnValue()
{
$commandInfo = new CommandInfo('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$this->assertEquals('example:table', $commandInfo->getName());
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
}
}
PK XAV|.E E tests/testAnnotatedCommand.phpnu W+A assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
$this->assertEquals('my:cat', $command->getName());
$this->assertEquals('This is the my:cat command implemented as an AnnotatedCommand subclass.', $command->getDescription());
$this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp());
$this->assertEquals('c', implode(',', $command->getAliases()));
// Symfony Console composes the synopsis; perhaps we should not test it. Remove if this gives false failures.
$this->assertEquals('my:cat [--flip] [--] []', $command->getSynopsis());
$this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages()));
$input = new StringInput('my:cat bet alpha --flip');
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet');
}
// TODO: Make a base test class to hold this.
function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0)
{
$output = new BufferedOutput();
$application = new Application('TestApplication', '0.0.0');
$application->setAutoExit(false);
$application->add($command);
$statusCode = $application->run($input, $output);
$commandOutput = trim($output->fetch());
$this->assertEquals($expectedOutput, $commandOutput);
$this->assertEquals($expectedStatusCode, $statusCode);
}
}
PK XAVVbB~7 7 * tests/src/ApplicationWithTerminalWidth.phpnu W+A width = $width;
$this->height = $height;
}
public function getTerminalDimensions()
{
return [ $this->width, $this->height ];
}
}
PK XAVº $ $ % tests/src/ExampleAnnotatedCommand.phpnu W+A getArgument('one');
$two = $input->getArgument('two');
$flip = $input->getOption('flip');
$result = $this->myCat($one, $two, $flip);
// We could also just use $output->writeln($result) here,
// but calling processResults enables the use of output
// formatters. Note also that if you use processResults, you
// should correctly inject the command processor into your
// annotated command via AnnotatedCommand::setCommandProcessor().
return $this->processResults($input, $output, $result);
}
}
PK XAV~
# # tests/src/ExampleCommandFile.phpnu W+A state = $state;
}
public function setOutput($output)
{
$this->output = $output;
}
/**
* This is the my:cat command
*
* This command will concatenate two parameters. If the --flip flag
* is provided, then the result is the concatenation of two and one.
*
* @param string $one The first parameter.
* @param string $two The other parameter.
* @option boolean $flip Whether or not the second parameter should come first in the result.
* @aliases c
* @usage bet alpha --flip
* Concatenate "alpha" and "bet".
* @arbitrary This annotation is here merely as a marker used in testing.
*/
public function myCat($one, $two = '', $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
/**
* @command my:repeat
*/
public function myRepeat($one, $two = '', $options = ['repeat' => 1])
{
return str_repeat("{$one}{$two}", $options['repeat']);
}
/**
* @command my:join
*/
public function myJoin(array $args, $options = ['flip' => false, 'repeat' => 1])
{
if ($options['flip']) {
$args = array_reverse($args);
}
$result = implode('', $args);
return str_repeat($result, $options['repeat']);
}
/**
* This is a command with no options
*
* This command will concatenate two parameters.
*
* @param $one The first parameter.
* @param $two The other parameter.
* @aliases nope
* @usage alpha bet
* Concatenate "alpha" and "bet".
*/
public function commandWithNoOptions($one, $two = 'default')
{
return "{$one}{$two}";
}
/**
* This command has no arguments--only options
*
* Return a result only if not silent.
*
* @option silent Supress output.
*/
public function commandWithNoArguments($opts = ['silent|s' => false])
{
if (!$opts['silent']) {
return "Hello, world";
}
}
/**
* Shortcut on annotation
*
* This command defines the option shortcut on the annotation instead of in the options array.
*
* @param $opts The options
* @option silent|s Supress output.
*/
public function shortcutOnAnnotation($opts = ['silent' => false])
{
if (!$opts['silent']) {
return "Hello, world";
}
}
/**
* This is the test:arithmatic command
*
* This command will add one and two. If the --negate flag
* is provided, then the result is negated.
*
* @command test:arithmatic
* @param integer $one The first number to add.
* @param integer $two The other number to add.
* @option negate Whether or not the result should be negated.
* @aliases arithmatic
* @usage 2 2 --negate
* Add two plus two and then negate.
* @custom
*/
public function testArithmatic($one, $two, $options = ['negate' => false])
{
$result = $one + $two;
if ($options['negate']) {
$result = -$result;
}
// Integer return codes are exit codes (errors), so
// return a the result as a string so that it will be printed.
return "$result";
}
/**
* This is the test:state command
*
* This command tests to see if the state of the Commandfile instance
*/
public function testState()
{
return $this->state;
}
/**
* This is the test:passthrough command
*
* This command takes a variable number of parameters as
* an array and returns them as a csv.
*/
public function testPassthrough(array $params)
{
return implode(',', $params);
}
/**
* This command wraps its parameter in []; its alter hook
* then wraps the result in <>.
*/
public function testHook($parameter)
{
return "[$parameter]";
}
/**
* Wrap the results of test:hook in <>.
*
* @hook alter test:hook
*/
public function hookTestHook($result)
{
return "<$result>";
}
/**
* This test is very similar to the preceding test, except
* it uses an annotation hook instead of a named-function hook.
*
* @hookme
* @before >
* @after <
*/
public function testAnnotationHook($parameter)
{
return "($parameter)";
}
/**
* Wrap the results of test:hook in whatever the @before and @after
* annotations contain.
*
* @hook alter @hookme
*/
public function hookTestAnnotatedHook($result, CommandData $commandData)
{
$before = $commandData->annotationData()->get('before', '-');
$after = $commandData->annotationData()->get('after', '-');
return "$before$result$after";
}
/**
* Alter the results of the hook with its command name.
*
* @hook alter @addmycommandname
*/
public function hookAddCommandName($result, CommandData $commandData)
{
$annotationData = $commandData->annotationData();
return "$result from " . $annotationData['command'];
}
/**
* Here is a hook with an explicit command annotation that we will alter
* with the preceeding hook
*
* @command alter-me
* @addmycommandname
*/
public function alterMe()
{
return "splendiferous";
}
/**
* Here is another hook that has no command annotation that should be
* altered with the default value for the command name
*
* @addmycommandname
*/
public function alterMeToo()
{
return "fantabulous";
}
/**
* @hook pre-command test:post-command
*/
public function hookTestPreCommandHook(CommandData $commandData)
{
// Use 'writeln' to detect order that hooks are called
$this->output->writeln("foo");
}
/**
* @command test:post-command
*/
public function testPostCommand($value)
{
$this->output->writeln($value);
}
/**
* @hook post-command test:post-command
*/
public function hookTestPostCommandHook($result, CommandData $commandData)
{
// Use 'writeln' to detect order that hooks are called
$this->output->writeln("baz");
}
public function testHello($who)
{
return "Hello, $who.";
}
public function testException($what)
{
throw new \Exception($what);
}
/**
* @hook init test:hello
*/
public function initializeTestHello($input, AnnotationData $annotationData)
{
$who = $input->getArgument('who');
if (!$who) {
$input->setArgument('who', 'Huey');
}
}
/**
* @hook command-event test:hello
*/
public function commandEventTestHello(ConsoleCommandEvent $event)
{
// Note that Symfony Console will not allow us to alter the
// input from this hook, so we'll just print something to
// show that this hook was executed.
$input = $event->getInput();
$who = $input->getArgument('who');
$this->output->writeln("Here comes $who!");
}
/**
* @hook interact test:hello
*/
public function interactTestHello($input, $output)
{
$who = $input->getArgument('who');
if (!$who) {
$input->setArgument('who', 'Goofey');
}
}
/**
* @hook validate test:hello
*/
public function validateTestHello($commandData)
{
$args = $commandData->arguments();
if ($args['who'] == 'Donald Duck') {
return new CommandError("I won't say hello to Donald Duck.");
}
if ($args['who'] == 'Drumph') {
throw new \Exception('Irrational value error.');
}
}
/**
* Test default values in arguments
*
* @param string|null $one
* @param string|null $two
* @return string
*/
public function defaults($one = null, $two = null)
{
if ($one && $two) {
return "$one and $two";
}
if ($one) {
return "only $one";
}
return "nothing provided";
}
}
PK XAVG
" tests/src/beta/BetaCommandFile.phpnu W+A input()->getOption('chinese')) {
$result[] = [ 'first' => '壹', 'second' => '貳', 'third' => '叁' ];
}
return $result;
}
/**
* Demonstrate an alter hook with an option
*
* @hook alter *
* @option kanji Add a row with Kanji numbers.
* @usage example:table --kanji
*/
public function alterFormattersKanji($result, CommandData $commandData)
{
if ($commandData->input()->getOption('kanji')) {
$result[] = [ 'first' => '一', 'second' => '二', 'third' => '三' ];
}
return $result;
}
}
PK XAV)\
' tests/src/ExampleCommandInfoAlterer.phpnu W+A hasAnnotation('arbitrary')) {
$commandInfo->addAnnotation('dynamic', "This annotation was dynamically added by ExampleCommandInfoAlterer");
}
}
}
PK XAVu $ tests/src/alpha/AlphaCommandFile.phpnu W+A 42];
}
/**
* @command example:output
*/
public function exampleOutput()
{
return 'Hello, World.';
}
/**
* @command example:cat
*/
public function exampleCat($one, $two = '', $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
/**
* @command example:echo
*/
public function exampleEcho(array $args)
{
return ['item-list' => $args];
}
/**
* @command example:message
*/
public function exampleMessage()
{
return ['message' => 'Shipwrecked; send bananas.'];
}
/**
* Test command with formatters
*
* @command example:table
* @field-labels
* first: I
* second: II
* third: III
* @usage example:table --format=yaml
* @usage example:table --format=csv
* @usage example:table --fields=first,third
* @usage example:table --fields=III,II
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function exampleTable($options = ['format' => 'table', 'fields' => ''])
{
$outputData = [
[ 'first' => 'One', 'second' => 'Two', 'third' => 'Three' ],
[ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei' ],
[ 'first' => 'Ichi', 'second' => 'Ni', 'third' => 'San' ],
[ 'first' => 'Uno', 'second' => 'Dos', 'third' => 'Tres' ],
];
return new RowsOfFields($outputData);
}
/**
* Test word wrapping
*
* @command example:wrap
* @field-labels
* first: First
* second: Second
*
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function exampleWrap()
{
$data = [
[
'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
'second' => 'This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.',
]
];
return new RowsOfFields($data);
}
/**
* @hook option example:table
*/
public function additionalOptionForExampleTable($command, $annotationData)
{
$command->addOption(
'dynamic',
'',
InputOption::VALUE_NONE,
'Option added by @hook option example:table'
);
}
/**
* Demonstrate an alter hook with an option
*
* @hook alter example:table
* @option french Add a row with French numbers.
* @usage example:table --french
*/
public function alterFormatters($result, CommandData $commandData)
{
if ($commandData->input()->getOption('french')) {
$result[] = [ 'first' => 'Un', 'second' => 'Deux', 'third' => 'Trois' ];
}
return $result;
}
/**
* Test command with formatters using an associative list
*
* @command example:list
* @field-labels
* sftp_command: SFTP Command
* sftp_username: SFTP Username
* sftp_host: SFTP Host
* sftp_password: SFTP Password
* sftp_url: SFTP URL
* git_command: Git Command
* git_username: Git Username
* git_host: Git Host
* git_port: Git Port
* git_url: Git URL
* mysql_command: MySQL Command
* mysql_username: MySQL Username
* mysql_host: MySQL Host
* mysql_password: MySQL Password
* mysql_url: MySQL URL
* mysql_port: MySQL Port
* mysql_database: MySQL Database
* redis_command: Redis Command
* redis_port: Redis Port
* redis_url: Redis URL
* redis_password: Redis Password
* @default-fields *_command
* @return \Consolidation\OutputFormatters\StructuredData\AssociativeList
*/
public function exampleAssociativeList()
{
$outputData = [
'sftp_command' => 'sftp -o Port=2222 dev@appserver.dev.drush.in',
'sftp_username' => 'dev',
'sftp_host' => 'appserver.dev.drush.in',
'sftp_password' => 'Use your account password',
'sftp_url' => 'sftp://dev@appserver.dev.drush.in:2222',
'git_command' => 'git clone ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git wp-update',
'git_username' => 'codeserver.dev',
'git_host' => 'codeserver.dev.drush.in',
'git_port' => 2222,
'git_url' => 'ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git',
'mysql_command' => 'mysql -u pantheon -p4b33cb -h dbserver.dev.drush.in -P 16191 pantheon',
'mysql_username' => 'pantheon',
'mysql_host' => 'dbserver.dev.drush.in',
'mysql_password' => '4b33cb',
'mysql_url' => 'mysql://pantheon:4b33cb@dbserver.dev.drush.in:16191/pantheon',
'mysql_port' => 16191,
'mysql_database' => 'pantheon',
];
return new AssociativeList($outputData);
}
/**
* This command has no annotations; this means that it will not be
* found when createCommandsFromClass() is called with
* '$includeAllPublicMethods' set to false.
*/
public function withoutAnnotations()
{
return 'ok';
}
/**
* @command command:with-one-optional-argument
*
* This command has just one optional argument.
*
* Return a result only if not silent.
*
* @option silent Supress output.
*/
public function commandWithOneOptionalArgument($who = 'world', $opts = ['silent|s' => false])
{
if (!$opts['silent']) {
return "Hello, $who";
}
}
/**
* This should be a command, because it is annotated like one.
*
* @command get:serious
*/
public function getSerious()
{
return 'very serious';
}
/**
* This should not be a command, because it looks like an accessor and
* has no @command annotation.
*/
public function getLost()
{
return 'very lost';
}
}
PK XAVΫr r / tests/src/alpha/Exclude/ExcludedCommandFile.phpnu W+A false])
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
public function doRepeat($one, $two = '', $options = ['repeat' => 1])
{
return str_repeat("{$one}{$two}", $options['repeat']);
}
/**
* This hook function does not specify which command or annotation
* it is hooking; that makes it apply to every command in the same class.
*
* @hook alter
*/
public function alterAllCommands($result)
{
if (is_string($result)) {
$result = "*** $result ***";
}
return $result;
}
}
PK XAVkah) )
.gitignorenu W+A .DS_Store
phpunit.xml
vendor
build
.idea
PK XAV>e1E 1E README.mdnu W+A # Consolidation\AnnotatedCommand
Initialize Symfony Console commands from annotated command class methods.
[![Travis CI](https://travis-ci.org/consolidation/annotated-command.svg?branch=master)](https://travis-ci.org/consolidation/annotated-command) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/consolidation/annotated-command/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/consolidation/annotated-command/?branch=master) [![Coverage Status](https://coveralls.io/repos/github/consolidation/annotated-command/badge.svg?branch=master)](https://coveralls.io/github/consolidation/annotated-command?branch=master) [![License](https://poser.pugx.org/consolidation/annotated-command/license)](https://packagist.org/packages/consolidation/annotated-command)
## Component Status
Currently in use in [Robo](https://github.com/consolidation/Robo) (1.x+), [Drush](https://github.com/drush-ops/drush) (9.x+) and [Terminus](https://github.com/pantheon-systems/terminus) (1.x+).
## Motivation
Symfony Console provides a set of classes that are widely used to implement command line tools. Increasingly, it is becoming popular to use annotations to describe the characteristics of the command (e.g. its arguments, options and so on) implemented by the annotated method.
Extant commandline tools that utilize this technique include:
- [Robo](https://github.com/consolidation/Robo)
- [wp-cli](https://github.com/wp-cli/wp-cli)
- [Pantheon Terminus](https://github.com/pantheon-systems/terminus)
This library provides routines to produce the Symfony\Component\Console\Command\Command from all public methods defined in the provided class.
**Note** If you are looking for a very fast way to write a Symfony Console-base command-line tool, you should consider using [Robo](https://github.com/consolidation/Robo), which is built on top of this library, and adds additional conveniences to get you going quickly. See [Using Robo as a Framework](https://github.com/consolidation/Robo/docs/framework.md). It is possible to use this project without Robo if desired, of course.
## Library Usage
This is a library intended to be used in some other project. Require from your composer.json file:
```
"require": {
"consolidation/annotated-command": "~2"
},
```
## Example Annotated Command Class
The public methods of the command class define its commands, and the parameters of each method define its arguments and options. The command options, if any, are declared as the last parameter of the methods. The options will be passed in as an associative array; the default options of the last parameter should list the options recognized by the command.
The rest of the parameters are arguments. Parameters with a default value are optional; those without a default value are required.
```php
class MyCommandClass
{
/**
* This is the my:cat command
*
* This command will concatenate two parameters. If the --flip flag
* is provided, then the result is the concatenation of two and one.
*
* @command my:cat
* @param integer $one The first parameter.
* @param integer $two The other parameter.
* @option flip Whether or not the second parameter should come first in the result.
* @aliases c
* @usage bet alpha --flip
* Concatenate "alpha" and "bet".
*/
public function myCat($one, $two, $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
}
```
## Hooks
Commandfiles may provide hooks in addition to commands. A commandfile method that contains a @hook annotation is registered as a hook instead of a command. The format of the hook annotation is:
```
@hook type commandname|annotation
```
The commandname may be the command's primary name (e.g. `my:command`), it's method name (e.g. myCommand) or any of its aliases.
If an annotation is given instead, then this hook function will run for all commands with the specified annotation.
There are ten types of hooks supported:
- Command Event (Symfony)
- Option
- Initialize (Symfony)
- Interact (Symfony)
- Validate
- Command
- Process
- Alter
- Status
- Extract
Most of these also have "pre" and "post" varieties, to give more flexibility vis-a-vis hook ordering (and for consistency). Note that many validate, process and alter hooks may run, but the first status or extract hook that successfully returns a result will halt processing of further hooks of the same type.
Each hook has an interface that defines its calling conventions; however, any callable may be used when registering a hook, which is convenient if versions of PHP prior to 7.0 (with no anonymous classes) need to be supported.
### Command Event Hook
The command-event hook is called via the Symfony Console command event notification callback mechanism. This happens prior to event dispatching and command / option validation. Note that Symfony does not allow the $input object to be altered in this hook; any change made here will be reset, as Symfony re-parses the object. Changes to arguments and options should be done in the initialize hook (non-interactive alterations) or the interact hook (which is naturally for interactive alterations).
### Option Event Hook
The option event hook ([OptionHookInterface](src/Hooks/OptionHookInterface.php)) is called for a specific command, whenever it is executed, or its help command is called. Any additional options for the command may be added here by instantiating and returnng an InputOption array.
### Initialize Hook
The initialize hook ([InitializeHookInterface](src/Hooks/InitializeHookInterface.php)) runs prior to the interact hook. It may supply command arguments and options from a configuration file or other sources. It should never do any user interaction.
### Interact Hook
The interact hook ([InteractorInterface](src/Hooks/InteractorInterface.php)) runs prior to argument and option validation. Required arguments and options not supplied on the command line may be provided during this phase by prompting the user. Note that the interact hook is not called if the --no-interaction flag is supplied, whereas the command-event hook and the inject-configuration hook are.
### Validate Hook
The purpose of the validate hook ([ValidatorInterface](src/Hooks/ValidatorInterface.php)) is to ensure the state of the targets of the current command are usabe in the context required by that command. Symfony has already validated the arguments and options prior to this hook. It is possible to alter the values of the arguments and options if necessary, although this is better done in the configure hook. A validation hook may take one of several actions:
- Do nothing. This indicates that validation succeeded.
- Return a CommandError. Validation fails, and execution stops. The CommandError contains a status result code and a message, which is printed.
- Throw an exception. The exception is converted into a CommandError.
- Return false. Message is empty, and status is 1. Deprecated.
The validate hook may change the arguments and options of the command by modifying the Input object in the provided CommandData parameter. Any number of validation hooks may run, but if any fails, then execution of the command stops.
### Command Hook
The command hook is provided for semantic purposes. The pre-command and command hooks are equivalent to the post-validate hook, and should confirm to the interface ([ValidatorInterface](src/Hooks/ValidatorInterface.php)). All of the post-validate hooks will be called before the first pre-command hook is called. Similarly, the post-command hook is equivalent to the pre-process hook, and should implement the interface ([ProcessResultInterface](src/Hooks/ProcessResultInterface.php)).
The command callback itself (the method annotated @command) is called after the last command hook, and prior to the first post-command hook.
### Process Hook
The process hook ([ProcessResultInterface](src/Hooks/ProcessResultInterface.php)) is specifically designed to convert a series of processing instructions into a final result. An example of this is implemented in Robo; if a Robo command returns a TaskInterface, then a Robo process hook will execute the task and return the result. This allows a pre-process hook to alter the task, e.g. by adding more operations to a task collection.
The process hook should not be used for other purposes.
### Alter Hook
An alter hook ([AlterResultInterface](src/Hooks/AlterResultInterface.php)) changes the result object. Alter hooks should only operate on result objects of a type they explicitly recognize. They may return an object of the same type, or they may convert the object to some other type.
If something goes wrong, and the alter hooks wishes to force the command to fail, then it may either return a CommandError object, or throw an exception.
### Status Hook
The status hook ([StatusDeterminerInterface](src/Hooks/StatusDeterminerInterface.php)) is responsible for determing whether a command succeeded (status code 0) or failed (status code > 0). The result object returned by a command may be a compound object that contains multiple bits of information about the command result. If the result object implements [ExitCodeInterface](ExitCodeInterface.php), then the `getExitCode()` method of the result object is called to determine what the status result code for the command should be. If ExitCodeInterface is not implemented, then all of the status hooks attached to this command are executed; the first one that successfully returns a result will stop further execution of status hooks, and the result it returned will be used as the status result code for this operation.
If no status hook returns any result, then success is presumed.
### Extract Hook
The extract hook ([ExtractOutputInterface](src/Hooks/ExtractOutputInterface.php)) is responsible for determining what the actual rendered output for the command should be. The result object returned by a command may be a compound object that contains multiple bits of information about the command result. If the result object implements [OutputDataInterface](OutputDataInterface.php), then the `getOutputData()` method of the result object is called to determine what information should be displayed to the user as a result of the command's execution. If OutputDataInterface is not implemented, then all of the extract hooks attached to this command are executed; the first one that successfully returns output data will stop further execution of extract hooks.
If no extract hook returns any data, then the result object itself is printed if it is a string; otherwise, no output is emitted (other than any produced by the command itself).
## Output
If a command method returns an integer, it is used as the command exit status code. If the command method returns a string, it is printed.
If the [Consolidation/OutputFormatters](https://github.com/consolidation/output-formatters) project is used, then users may specify a --format option to select the formatter to use to transform the output from whatever form the command provides to a string. To make this work, the application must provide a formatter to the AnnotatedCommandFactory. See [API Usage](#api-usage) below.
## Logging
The Annotated-Command project is completely agnostic to logging. If a command wishes to log progress, then the CommandFile class should implement LoggerAwareInterface, and the Commandline tool should inject a logger for its use via the LoggerAwareTrait `setLogger()` method. Using [Robo](https://github.com/consolidation/robo) is recommended.
## Access to Symfony Objects
If you want to use annotations, but still want access to the Symfony Command, e.g. to get a reference to the helpers in order to call some legacy code, you may create an ordinary Symfony Command that extends \Consolidation\AnnotatedCommand\AnnotatedCommand, which is a \Symfony\Component\Console\Command\Command. Omit the configure method, and place your annotations on the `execute()` method.
It is also possible to add InputInterface or OutputInterface parameters to any annotated method of a command file.
## API Usage
If you would like to use Annotated Commands to build a commandline tool, it is recommended that you use [Robo as a framework](http://robo.li/framework.md), as it will set up all of the various command classes for you. If you would like to integrate Annotated Commands into some other framework, see the sections below.
### Set up Command Factory and Instantiate Commands
To use annotated commands in an application, pass an instance of your command class in to AnnotatedCommandFactory::createCommandsFromClass(). The result will be a list of Commands that may be added to your application.
```php
$myCommandClassInstance = new MyCommandClass();
$commandFactory = new AnnotatedCommandFactory();
$commandFactory->setIncludeAllPublicMethods(true);
$commandFactory->commandProcessor()->setFormatterManager(new FormatterManager());
$commandList = $commandFactory->createCommandsFromClass($myCommandClassInstance);
foreach ($commandList as $command) {
$application->add($command);
}
```
You may have more than one command class, if you wish. If so, simply call AnnotatedCommandFactory::createCommandsFromClass() multiple times.
If you do not wish every public method in your classes to be added as commands, use `AnnotatedCommandFactory::setIncludeAllPublicMethods(false)`, and only methods annotated with @command will become commands.
Note that the `setFormatterManager()` operation is optional; omit this if not using [Consolidation/OutputFormatters](https://github.com/consolidation/output-formatters).
A CommandInfoAltererInterface can be added via AnnotatedCommandFactory::addCommandInfoAlterer(); it will be given the opportunity to adjust every CommandInfo object parsed from a command file prior to the creation of commands.
### Command File Discovery
A discovery class, CommandFileDiscovery, is also provided to help find command files on the filesystem. Usage is as follows:
```php
$discovery = new CommandFileDiscovery();
$myCommandFiles = $discovery->discover($path, '\Drupal');
foreach ($myCommandFiles as $myCommandClass) {
$myCommandClassInstance = new $myCommandClass();
// ... as above
}
```
For a discussion on command file naming conventions and search locations, see https://github.com/consolidation/annotated-command/issues/12.
If different namespaces are used at different command file paths, change the call to discover as follows:
```php
$myCommandFiles = $discovery->discover(['\Ns1' => $path1, '\Ns2' => $path2]);
```
As a shortcut for the above, the method `discoverNamespaced()` will take the last directory name of each path, and append it to the base namespace provided. This matches the conventions used by Drupal modules, for example.
### Configuring Output Formatts (e.g. to enable wordwrap)
The Output Formatters project supports automatic formatting of tabular output. In order for wordwrapping to work correctly, the terminal width must be passed in to the Output Formatters handlers via `FormatterOptions::setWidth()`.
In the Annotated Commands project, this is done via dependency injection. If a `PrepareFormatter` object is passed to `CommandProcessor::addPrepareFormatter()`, then it will be given an opportunity to set properties on the `FormatterOptions` when it is created.
A `PrepareTerminalWidthOption` class is provided to use the Symfony Application class to fetch the terminal width, and provide it to the FormatterOptions. It is injected as follows:
```php
$terminalWidthOption = new PrepareTerminalWidthOption();
$terminalWidthOption->setApplication($application);
$commandFactory->commandProcessor()->addPrepareFormatter($terminalWidthOption);
```
To provide greater control over the width used, create your own `PrepareTerminalWidthOption` subclass, and adjust the width as needed.
## Other Callbacks
In addition to the hooks provided by the hook manager, there are additional callbacks available to alter the way the annotated command library operates.
### Factory Listeners
Factory listeners are notified every time a command file instance is used to create annotated commands.
```
public function AnnotatedCommandFactory::addListener(CommandCreationListenerInterface $listener);
```
Listeners can be used to construct command file instances as they are provided to the command factory.
### Option Providers
An option provider is given an opportunity to add options to a command as it is being constructed.
```
public function AnnotatedCommandFactory::addAutomaticOptionProvider(AutomaticOptionsProviderInterface $listener);
```
The complete CommandInfo record with all of the annotation data is available, so you can, for example, add an option `--foo` to every command whose method is annotated `@fooable`.
### CommandInfo Alterers
CommandInfo alterers can adjust information about a command immediately before it is created. Typically, these will be used to supply default values for annotations custom to the command, or take other actions based on the interfaces implemented by the commandfile instance.
```
public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance);
```
## Comparison to Existing Solutions
The existing solutions used their own hand-rolled regex-based parsers to process the contents of the DocBlock comments. consolidation/annotated-command uses the [phpdocumentor/reflection-docblock](https://github.com/phpDocumentor/ReflectionDocBlock) project (which is itself a regex-based parser) to interpret DocBlock contents.
PK XAVM&