composer update

This commit is contained in:
Oliver Davies 2019-01-24 08:00:03 +00:00
parent f6abc3dce2
commit 71dfaca858
1753 changed files with 45274 additions and 14619 deletions

586
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@ return array(
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',

View file

@ -16,6 +16,7 @@ return array(
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'Unish\\' => array($vendorDir . '/drush/drush/tests'),
'Twig\\' => array($vendorDir . '/twig/twig/src'),
'TYPO3\\PharStreamWrapper\\' => array($vendorDir . '/typo3/phar-stream-wrapper/src'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),

View file

@ -13,6 +13,7 @@ class ComposerStaticInit5b1c1b80ca16f098d2571547d6c6045f
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
@ -59,6 +60,7 @@ class ComposerStaticInit5b1c1b80ca16f098d2571547d6c6045f
'T' =>
array (
'Twig\\' => 5,
'TYPO3\\PharStreamWrapper\\' => 24,
),
'S' =>
array (
@ -204,6 +206,10 @@ class ComposerStaticInit5b1c1b80ca16f098d2571547d6c6045f
array (
0 => __DIR__ . '/..' . '/twig/twig/src',
),
'TYPO3\\PharStreamWrapper\\' =>
array (
0 => __DIR__ . '/..' . '/typo3/phar-stream-wrapper/src',
),
'Symfony\\Polyfill\\Php72\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
#!/bin/bash
SCENARIO=$1
DEPENDENCIES=${2-install}
# Convert the aliases 'highest', 'lowest' and 'lock' to
# the corresponding composer command to run.
case $DEPENDENCIES in
highest)
DEPENDENCIES=update
;;
lowest)
DEPENDENCIES='update --prefer-lowest'
;;
lock|default|"")
DEPENDENCIES=install
;;
esac
original_name=scenarios
recommended_name=".scenarios.lock"
base="$original_name"
if [ -d "$recommended_name" ] ; then
base="$recommended_name"
fi
# If scenario is not specified, install the lockfile at
# the root of the project.
dir="$base/${SCENARIO}"
if [ -z "$SCENARIO" ] || [ "$SCENARIO" == "default" ] ; then
SCENARIO=default
dir=.
fi
# Test to make sure that the selected scenario exists.
if [ ! -d "$dir" ] ; then
echo "Requested scenario '${SCENARIO}' does not exist."
exit 1
fi
echo
echo "::"
echo ":: Switch to ${SCENARIO} scenario"
echo "::"
echo
set -ex
composer -n validate --working-dir=$dir --no-check-all --ansi
composer -n --working-dir=$dir ${DEPENDENCIES} --prefer-dist --no-scripts
# If called from a CI context, print out some extra information about
# what we just installed.
if [[ -n "$CI" ]] ; then
composer -n --working-dir=$dir info
fi

View file

@ -0,0 +1 @@
vendor

View file

@ -0,0 +1,61 @@
{
"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.4",
"psr/log": "^1",
"symfony/console": "^2.8|^3|^4",
"symfony/event-dispatcher": "^2.5|^3|^4",
"symfony/finder": "^2.5|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2.7"
},
"config": {
"platform": {
"php": "5.4.8"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
},
"scripts": {
"cs": "phpcs --standard=PSR2 -n src",
"cbf": "phpcbf --standard=PSR2 -n src",
"unit": "SHELL_INTERACTIVE=true phpunit --colors=always",
"lint": [
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
"find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l"
],
"test": [
"@lint",
"@unit",
"@cs"
]
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
}
}

View file

@ -0,0 +1,2 @@
vendor
composer.lock

View file

@ -0,0 +1,61 @@
{
"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": {
"symfony/console": "^2.8",
"php": ">=5.4.0",
"consolidation/output-formatters": "^3.4",
"psr/log": "^1",
"symfony/event-dispatcher": "^2.5|^3|^4",
"symfony/finder": "^2.5|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2.7"
},
"config": {
"platform": {
"php": "5.4.8"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
},
"scripts": {
"cs": "phpcs --standard=PSR2 -n src",
"cbf": "phpcbf --standard=PSR2 -n src",
"unit": "SHELL_INTERACTIVE=true phpunit --colors=always",
"lint": [
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
"find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l"
],
"test": [
"@lint",
"@unit",
"@cs"
]
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
}
}

View file

@ -0,0 +1 @@
vendor

View file

@ -0,0 +1,62 @@
{
"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": {
"symfony/console": "^4.0",
"php": ">=5.4.0",
"consolidation/output-formatters": "^3.4",
"psr/log": "^1",
"symfony/event-dispatcher": "^2.5|^3|^4",
"symfony/finder": "^2.5|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "^6",
"php-coveralls/php-coveralls": "^1",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2.7"
},
"config": {
"platform": {
"php": "7.1.3"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
},
"scripts": {
"cs": "phpcs --standard=PSR2 -n src",
"cbf": "phpcbf --standard=PSR2 -n src",
"unit": "SHELL_INTERACTIVE=true phpunit --colors=always",
"lint": [
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
"find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l"
],
"test": [
"@lint",
"@unit",
"@cs"
]
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,19 @@
# Change Log
### 2.11.0
- Make injection of InputInterface / OutputInterface general-purpose (#179)
### 2.10.2 - 20 Dec 2018
- Fix commands that have a @param annotation for their InputInterface/OutputInterface params (#176)
### 2.10.1 - 13 Dec 2018
- Add stdin handler convenience class
- Add setter to AnnotationData to suppliment existing array acces
- Update to Composer Test Scenarios 3
### 2.10.0 - 14 Nov 2018
- Add a new data type, CommandResult (#167)

View file

@ -11,12 +11,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
DEPENDENCY LICENSES:
Name Version License
consolidation/output-formatters 3.4.0 MIT
dflydev/dot-access-data v1.1.0 MIT
psr/log 1.0.2 MIT
symfony/console v3.4.17 MIT
symfony/debug v3.4.17 MIT
symfony/event-dispatcher v3.4.17 MIT
symfony/finder v3.4.17 MIT
symfony/polyfill-mbstring v1.9.0 MIT
Name Version License
consolidation/output-formatters 3.4.0 MIT
dflydev/dot-access-data v1.1.0 MIT
psr/log 1.1.0 MIT
symfony/console v2.8.47 MIT
symfony/debug v2.8.47 MIT
symfony/event-dispatcher v2.8.47 MIT
symfony/finder v2.8.47 MIT
symfony/polyfill-mbstring v1.10.0 MIT

View file

@ -5,7 +5,7 @@ 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)
[![Windows CI](https://ci.appveyor.com/api/projects/status/c2c4lcf43ux4c30p?svg=true)](https://ci.appveyor.com/project/greg-1-anderson/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)
[![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
@ -31,7 +31,7 @@ This library provides routines to produce the Symfony\Component\Console\Command\
This is a library intended to be used in some other project. Require from your composer.json file:
```
"require": {
"consolidation/annotated-command": "~2"
"consolidation/annotated-command": "^2"
},
```
@ -43,12 +43,12 @@ The rest of the parameters are arguments. Parameters with a default value are op
class MyCommandClass
{
/**
* This is the my:cat command
* This is the my:echo 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
* @command my:echo
* @param integer $one The first parameter.
* @param integer $two The other parameter.
* @option arr An option that takes multiple values.
@ -57,7 +57,7 @@ class MyCommandClass
* @usage bet alpha --flip
* Concatenate "alpha" and "bet".
*/
public function myCat($one, $two, $options = ['flip' => false])
public function myEcho($one, $two, $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
@ -65,7 +65,7 @@ class MyCommandClass
return "{$one}{$two}";
}
}
```
```
## Option Default Values
The `$options` array must be an associative array whose key is the name of the option, and whose value is one of:
@ -103,6 +103,7 @@ The hook **target** specifies which command or commands the hook will be attache
- The command's primary name (e.g. `my:command`) or the command's method name (e.g. myCommand) will attach the hook to only that command.
- An annotation (e.g. `@foo`) will attach the hook to any command that is annotated with the given label.
- If the target is specified as `*`, then the hook will be attached to all commands.
- If the target is omitted, then the hook will be attached to every command defined in the same class as the hook implementation.
There are ten types of hooks in the command processing request flow:
@ -143,7 +144,7 @@ There are ten types of hooks in the command processing request flow:
- @status
- [Extract](#extract-hook)
- @extract
In addition to these, there are two more hooks available:
- [On-event](#on-event-hook)
@ -201,6 +202,42 @@ public function initSomeCommand(InputInterface $input, AnnotationData $annotatio
}
```
You may alter the AnnotationData here by using simple array syntax. Below, we
add an additional display field label for a Property List.
```
use Consolidation\AnnotatedCommand\AnnotationData;
use Symfony\Component\Console\Input\InputInterface;
/**
* @hook init some:command
*/
public function initSomeCommand(InputInterface $input, AnnotationData $annotationData)
{
$annotationData['field-labels'] .= "\n" . "new_field: My new field";
}
```
Alternately, you may use the `set()` or `append()` methods on the AnnotationData
class.
```
use Consolidation\AnnotatedCommand\AnnotationData;
use Symfony\Component\Console\Input\InputInterface;
/**
* @hook init some:command
*/
public function initSomeCommand(InputInterface $input, AnnotationData $annotationData)
{
// Add a line to the field labels.
$annotationData->append('field-labels', "\n" . "new_field: My new field");
// Replace all field labels.
$annotationData->set('field-labels', "one_field: My only field");
}
```
### 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 init hook are.
@ -407,8 +444,8 @@ class MyReplaceCommandHook {
/**
* @hook replace-command foo:bar
*
* Parameters must match original command method.
*
* Parameters must match original command method.
*/
public function myFooBarReplacement($value) {
print "Hello $value!";
@ -432,6 +469,46 @@ If you want to use annotations, but still want access to the Symfony Command, e.
It is also possible to add InputInterface and/or OutputInterface parameters to any annotated method of a command file (the parameters must go before command arguments).
## Parameter Injection
Just as this library will by default inject $input and/or $output at the head of the parameter list of any command function, it is also possible to add a handler to inject other objects as well.
Given an implementation of SymfonyStyleInjector similar to the example below:
```
use Consolidation\AnnotatedCommand\ParameterInjector
class SymfonyStyleInjector implements ParameterInjector
{
public function get(CommandData $commandData, $interfaceName)
{
return new MySymfonyStyle($commandData->input(), $commandData->output());
}
}
```
Then, an instance of 'MySymfonyStyle' will be provided to any command handler method that takes a SymfonyStyle parameter if the SymfonyStyleInjector is registered in your application's initialization code like so:
```
$commandProcessor->parameterInjection()->register('Symfony\Component\Console\Style\SymfonyStyle', new SymfonyStyleInjector);
```
## Handling Standard Input
Any Symfony command may use the provides StdinHandler to imlement commands that read from standard input.
```php
/**
* @command example
* @option string $file
* @default $file -
*/
public function example(InputInterface $input)
{
$data = StdinHandler::selectStream($input, 'file')->contents();
}
```
This example will read all of the data available from the stdin stream into $data, or, alternately, will read the entire contents of the file specified via the `--file=/path` option.
For more details, including examples of using the StdinHandle with a DI container, see the comments in [StdinHandler.php](src/Input/StdinHandler.php).
## 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), 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.
@ -504,7 +581,7 @@ Listeners can be used to construct command file instances as they are provided t
### Option Providers
An option provider is given an opportunity to add options to a command as it is being constructed.
An option provider is given an opportunity to add options to a command as it is being constructed.
```
public function AnnotatedCommandFactory::addAutomaticOptionProvider(AutomaticOptionsProviderInterface $listener);
```
@ -516,7 +593,3 @@ CommandInfo alterers can adjust information about a command immediately before i
```
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.

View file

@ -28,8 +28,8 @@
},
"require-dev": {
"phpunit/phpunit": "^6",
"satooshi/php-coveralls": "^2",
"g1a/composer-test-scenarios": "^2",
"php-coveralls/php-coveralls": "^1",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2.7"
},
"config": {
@ -51,16 +51,53 @@
"@lint",
"@unit",
"@cs"
],
"scenario": "scenarios/install",
"post-update-cmd": [
"create-scenario symfony4 'symfony/console:^4.0' --platform-php '7.1.3'",
"create-scenario symfony2 'symfony/console:^2.8' 'phpunit/phpunit:^4.8.36' --remove 'satooshi/php-coveralls' --platform-php '5.4' --no-lockfile",
"create-scenario phpunit4 'phpunit/phpunit:^4.8.36' --remove 'satooshi/php-coveralls' --platform-php '5.4'",
"dependency-licenses"
]
},
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
},
"scenario-options": {
"create-lockfile": "false"
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "2.x-dev"
}

View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6be8513127d28eadc852a80e0aa0c3d5",
"content-hash": "3c6b3e869447a986290d067cbf905c6f",
"packages": [
{
"name": "consolidation/output-formatters",
@ -123,16 +123,16 @@
},
{
"name": "psr/log",
"version": "1.0.2",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"shasum": ""
},
"require": {
@ -166,20 +166,20 @@
"psr",
"psr-3"
],
"time": "2016-10-10T12:19:37+00:00"
"time": "2018-11-20T15:27:04+00:00"
},
{
"name": "symfony/console",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b"
"reference": "1d228fb4602047d7b26a0554e0d3efd567da5803"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b",
"reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b",
"url": "https://api.github.com/repos/symfony/console/zipball/1d228fb4602047d7b26a0554e0d3efd567da5803",
"reference": "1d228fb4602047d7b26a0554e0d3efd567da5803",
"shasum": ""
},
"require": {
@ -235,20 +235,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:33:53+00:00"
"time": "2018-10-30T16:50:50+00:00"
},
{
"name": "symfony/debug",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6"
"reference": "fe9793af008b651c5441bdeab21ede8172dab097"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/0a612e9dfbd2ccce03eb174365f31ecdca930ff6",
"reference": "0a612e9dfbd2ccce03eb174365f31ecdca930ff6",
"url": "https://api.github.com/repos/symfony/debug/zipball/fe9793af008b651c5441bdeab21ede8172dab097",
"reference": "fe9793af008b651c5441bdeab21ede8172dab097",
"shasum": ""
},
"require": {
@ -291,20 +291,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:33:53+00:00"
"time": "2018-10-31T09:06:03+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb"
"reference": "db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb",
"reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14",
"reference": "db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14",
"shasum": ""
},
"require": {
@ -354,11 +354,11 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T09:06:28+00:00"
"time": "2018-10-30T16:50:50+00:00"
},
{
"name": "symfony/finder",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@ -407,16 +407,16 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.9.0",
"version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
"shasum": ""
},
"require": {
@ -462,7 +462,7 @@
"portable",
"shim"
],
"time": "2018-08-06T14:22:27+00:00"
"time": "2018-09-21T13:07:52+00:00"
}
],
"packages-dev": [
@ -522,24 +522,43 @@
},
{
"name": "g1a/composer-test-scenarios",
"version": "2.2.0",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/g1a/composer-test-scenarios.git",
"reference": "a166fd15191aceab89f30c097e694b7cf3db4880"
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/a166fd15191aceab89f30c097e694b7cf3db4880",
"reference": "a166fd15191aceab89f30c097e694b7cf3db4880",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0.0",
"php": ">=5.4"
},
"require-dev": {
"composer/composer": "^1.7",
"php-coveralls/php-coveralls": "^1.0",
"phpunit/phpunit": "^4.8.36|^6",
"squizlabs/php_codesniffer": "^2.8"
},
"bin": [
"scripts/create-scenario",
"scripts/dependency-licenses",
"scripts/install-scenario"
"scripts/dependency-licenses"
],
"type": "library",
"type": "composer-plugin",
"extra": {
"class": "ComposerTestScenarios\\Plugin",
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"ComposerTestScenarios\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
@ -551,47 +570,70 @@
}
],
"description": "Useful scripts for testing multiple sets of Composer dependencies.",
"time": "2018-08-08T23:37:23+00:00"
"time": "2018-11-22T05:10:20+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"name": "guzzle/guzzle",
"version": "v3.8.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
"reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
"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": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
"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": "6.3-dev"
"dev-master": "3.8-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
"psr-0": {
"Guzzle": "src/",
"Guzzle\\Tests": "tests/"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -603,9 +645,13 @@
"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",
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
@ -616,123 +662,8 @@
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
"abandoned": "guzzlehttp/guzzle",
"time": "2014-01-28T22:29:15+00:00"
},
{
"name": "myclabs/deep-copy",
@ -881,6 +812,67 @@
"description": "Library for handling version information and constraints",
"time": "2017-03-05T17:38:23+00:00"
},
{
"name": "php-coveralls/php-coveralls",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-coveralls/php-coveralls.git",
"reference": "37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad",
"reference": "37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-simplexml": "*",
"guzzle/guzzle": "^2.8 || ^3.0",
"php": "^5.3.3 || ^7.0",
"psr/log": "^1.0",
"symfony/config": "^2.1 || ^3.0 || ^4.0",
"symfony/console": "^2.1 || ^3.0 || ^4.0",
"symfony/stopwatch": "^2.0 || ^3.0 || ^4.0",
"symfony/yaml": "^2.0 || ^3.0 || ^4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.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/php-coveralls/php-coveralls",
"keywords": [
"ci",
"coverage",
"github",
"test"
],
"time": "2017-12-06T23:17:56+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0.1",
@ -1488,140 +1480,6 @@
],
"time": "2018-08-09T05:50:03+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "satooshi/php-coveralls",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-coveralls/php-coveralls.git",
"reference": "3eaf7eb689cdf6b86801a3843940d974dc657068"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/3eaf7eb689cdf6b86801a3843940d974dc657068",
"reference": "3eaf7eb689cdf6b86801a3843940d974dc657068",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.0",
"php": "^5.5 || ^7.0",
"psr/log": "^1.0",
"symfony/config": "^2.1 || ^3.0 || ^4.0",
"symfony/console": "^2.1 || ^3.0 || ^4.0",
"symfony/stopwatch": "^2.0 || ^3.0 || ^4.0",
"symfony/yaml": "^2.0 || ^3.0 || ^4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0"
},
"suggest": {
"symfony/http-kernel": "Allows Symfony integration"
},
"bin": [
"bin/php-coveralls"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"PhpCoveralls\\": "src/"
}
},
"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",
"role": "Original creator"
},
{
"name": "Takashi Matsuo",
"email": "tmatsuo@google.com"
},
{
"name": "Google Inc"
},
{
"name": "Dariusz Ruminski",
"email": "dariusz.ruminski@gmail.com",
"homepage": "https://github.com/keradus"
},
{
"name": "Contributors",
"homepage": "https://github.com/php-coveralls/php-coveralls/graphs/contributors"
}
],
"description": "PHP client library for Coveralls API",
"homepage": "https://github.com/php-coveralls/php-coveralls",
"keywords": [
"ci",
"coverage",
"github",
"test"
],
"abandoned": "php-coveralls/php-coveralls",
"time": "2017-12-08T14:28:16+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.1",
@ -2183,16 +2041,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "2.9.1",
"version": "2.9.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "dcbed1074f8244661eecddfc2a675430d8d33f62"
"reference": "2acf168de78487db620ab4bc524135a13cfe6745"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62",
"reference": "dcbed1074f8244661eecddfc2a675430d8d33f62",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745",
"reference": "2acf168de78487db620ab4bc524135a13cfe6745",
"shasum": ""
},
"require": {
@ -2257,20 +2115,20 @@
"phpcs",
"standards"
],
"time": "2017-05-22T02:43:20+00:00"
"time": "2018-11-07T22:31:41+00:00"
},
{
"name": "symfony/config",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "e5389132dc6320682de3643091121c048ff796b3"
"reference": "99b2fa8acc244e656cdf324ff419fbe6fd300a4d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/e5389132dc6320682de3643091121c048ff796b3",
"reference": "e5389132dc6320682de3643091121c048ff796b3",
"url": "https://api.github.com/repos/symfony/config/zipball/99b2fa8acc244e656cdf324ff419fbe6fd300a4d",
"reference": "99b2fa8acc244e656cdf324ff419fbe6fd300a4d",
"shasum": ""
},
"require": {
@ -2321,11 +2179,11 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-09-08T13:15:14+00:00"
"time": "2018-10-31T09:06:03+00:00"
},
{
"name": "symfony/filesystem",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@ -2375,7 +2233,7 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.9.0",
"version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -2433,7 +2291,7 @@
},
{
"name": "symfony/stopwatch",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
@ -2482,7 +2340,7 @@
},
{
"name": "symfony/yaml",
"version": "v3.4.17",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",

View file

@ -9,6 +9,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Consolidation\AnnotatedCommand\Help\HelpDocumentBuilder;
/**
* AnnotatedCommands are created automatically by the
@ -32,9 +33,8 @@ class AnnotatedCommand extends Command implements HelpDocumentAlter
protected $annotationData;
protected $examples = [];
protected $topics = [];
protected $usesInputInterface;
protected $usesOutputInterface;
protected $returnType;
protected $injectedClasses = [];
public function __construct($name = null)
{
@ -153,118 +153,16 @@ class AnnotatedCommand extends Command implements HelpDocumentAlter
public function helpAlter(\DomDocument $originalDom)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $this->getName());
$commandXML->setAttribute('name', $this->getName());
// Get the original <command> element and its top-level elements.
$originalCommandXML = $this->getSingleElementByTagName($dom, $originalDom, 'command');
$originalUsagesXML = $this->getSingleElementByTagName($dom, $originalCommandXML, 'usages');
$originalDescriptionXML = $this->getSingleElementByTagName($dom, $originalCommandXML, 'description');
$originalHelpXML = $this->getSingleElementByTagName($dom, $originalCommandXML, 'help');
$originalArgumentsXML = $this->getSingleElementByTagName($dom, $originalCommandXML, 'arguments');
$originalOptionsXML = $this->getSingleElementByTagName($dom, $originalCommandXML, 'options');
// Keep only the first of the <usage> elements
$newUsagesXML = $dom->createElement('usages');
$firstUsageXML = $this->getSingleElementByTagName($dom, $originalUsagesXML, 'usage');
$newUsagesXML->appendChild($firstUsageXML);
// Create our own <example> elements
$newExamplesXML = $dom->createElement('examples');
foreach ($this->examples as $usage => $description) {
$newExamplesXML->appendChild($exampleXML = $dom->createElement('example'));
$exampleXML->appendChild($usageXML = $dom->createElement('usage', $usage));
$exampleXML->appendChild($descriptionXML = $dom->createElement('description', $description));
}
// Create our own <alias> elements
$newAliasesXML = $dom->createElement('aliases');
foreach ($this->getAliases() as $alias) {
$newAliasesXML->appendChild($dom->createElement('alias', $alias));
}
// Create our own <topic> elements
$newTopicsXML = $dom->createElement('topics');
foreach ($this->getTopics() as $topic) {
$newTopicsXML->appendChild($topicXML = $dom->createElement('topic', $topic));
}
// Place the different elements into the <command> element in the desired order
$commandXML->appendChild($newUsagesXML);
$commandXML->appendChild($newExamplesXML);
$commandXML->appendChild($originalDescriptionXML);
$commandXML->appendChild($originalArgumentsXML);
$commandXML->appendChild($originalOptionsXML);
$commandXML->appendChild($originalHelpXML);
$commandXML->appendChild($newAliasesXML);
$commandXML->appendChild($newTopicsXML);
return $dom;
}
protected function getSingleElementByTagName($dom, $parent, $tagName)
{
// There should always be exactly one '<command>' element.
$elements = $parent->getElementsByTagName($tagName);
$result = $elements->item(0);
$result = $dom->importNode($result, true);
return $result;
return HelpDocumentBuilder::alter($originalDom, $this);
}
protected function setCommandArguments($commandInfo)
{
$this->setUsesInputInterface($commandInfo);
$this->setUsesOutputInterface($commandInfo);
$this->injectedClasses = $commandInfo->getInjectedClasses();
$this->setCommandArgumentsFromParameters($commandInfo);
return $this;
}
/**
* Check whether the first parameter is an InputInterface.
*/
protected function checkUsesInputInterface($params)
{
/** @var \ReflectionParameter $firstParam */
$firstParam = reset($params);
return $firstParam && $firstParam->getClass() && $firstParam->getClass()->implementsInterface(
'\\Symfony\\Component\\Console\\Input\\InputInterface'
);
}
/**
* Determine whether this command wants to get its inputs
* via an InputInterface or via its command parameters
*/
protected function setUsesInputInterface($commandInfo)
{
$params = $commandInfo->getParameters();
$this->usesInputInterface = $this->checkUsesInputInterface($params);
return $this;
}
/**
* Determine whether this command wants to send its output directly
* to the provided OutputInterface, or whether it will returned
* structured output to be processed by the command processor.
*/
protected function setUsesOutputInterface($commandInfo)
{
$params = $commandInfo->getParameters();
$index = $this->checkUsesInputInterface($params) ? 1 : 0;
$this->usesOutputInterface =
(count($params) > $index) &&
$params[$index]->getClass() &&
$params[$index]->getClass()->implementsInterface(
'\\Symfony\\Component\\Console\\Output\\OutputInterface'
)
;
return $this;
}
protected function setCommandArgumentsFromParameters($commandInfo)
{
$args = $commandInfo->arguments()->getValues();
@ -437,10 +335,10 @@ class AnnotatedCommand extends Command implements HelpDocumentAlter
$output
);
$commandData->setUseIOInterfaces(
$this->usesInputInterface,
$this->usesOutputInterface
);
// Fetch any classes (e.g. InputInterface / OutputInterface) that
// this command's callback wants passed as a parameter and inject
// it into the command data.
$this->commandProcessor()->injectIntoCommandData($commandData, $this->injectedClasses);
// Allow the commandData to cache the list of options with
// special default values ('null' and 'true'), as these will

View file

@ -24,4 +24,21 @@ class AnnotationData extends \ArrayObject
{
return array_keys($this->getArrayCopy());
}
public function set($key, $value = '')
{
$this->offsetSet($key, $value);
return $this;
}
public function append($key, $value = '')
{
$data = $this->offsetGet($key);
if (is_array($data)) {
$this->offsetSet($key, array_merge($data, $value));
} elseif (is_scalar($data)) {
$this->offsetSet($key, $data . $value);
}
return $this;
}
}

View file

@ -1,6 +1,7 @@
<?php
namespace Consolidation\AnnotatedCommand;
use Consolidation\OutputFormatters\Options\FormatterOptions;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -14,43 +15,44 @@ class CommandData
/** var OutputInterface */
protected $output;
/** var boolean */
protected $usesInputInterface;
/** var boolean */
protected $usesOutputInterface;
/** var boolean */
protected $includeOptionsInArgs;
/** var array */
protected $specialDefaults = [];
/** @var string[] */
protected $injectedInstances = [];
/** @var FormatterOptions */
protected $formatterOptions;
public function __construct(
AnnotationData $annotationData,
InputInterface $input,
OutputInterface $output,
$usesInputInterface = false,
$usesOutputInterface = false
OutputInterface $output
) {
$this->annotationData = $annotationData;
$this->input = $input;
$this->output = $output;
$this->usesInputInterface = false;
$this->usesOutputInterface = false;
$this->includeOptionsInArgs = true;
}
/**
* For internal use only; indicates that the function to be called
* should be passed an InputInterface &/or an OutputInterface.
* @param booean $usesInputInterface
* @param boolean $usesOutputInterface
* @return self
* For internal use only; inject an instance to be passed back
* to the command callback as a parameter.
*/
public function setUseIOInterfaces($usesInputInterface, $usesOutputInterface)
public function injectInstance($injectedInstance)
{
$this->usesInputInterface = $usesInputInterface;
$this->usesOutputInterface = $usesOutputInterface;
array_unshift($this->injectedInstances, $injectedInstance);
return $this;
}
/**
* Provide a reference to the instances that will be added to the
* beginning of the parameter list when the command callback is invoked.
*/
public function injectedInstances()
{
return $this->injectedInstances;
}
/**
* For backwards-compatibility mode only: disable addition of
* options on the end of the arguments list.
@ -66,6 +68,16 @@ class CommandData
return $this->annotationData;
}
public function formatterOptions()
{
return $this->formatterOptions;
}
public function setFormatterOptions($formatterOptions)
{
$this->formatterOptions = $formatterOptions;
}
public function input()
{
return $this->input;
@ -174,14 +186,6 @@ class CommandData
array_shift($args);
}
if ($this->usesOutputInterface) {
array_unshift($args, $this->output());
}
if ($this->usesInputInterface) {
array_unshift($args, $this->input());
}
return $args;
}

View file

@ -31,16 +31,18 @@ class CommandProcessor implements LoggerAwareInterface
{
use LoggerAwareTrait;
/** var HookManager */
/** @var HookManager */
protected $hookManager;
/** var FormatterManager */
/** @var FormatterManager */
protected $formatterManager;
/** var callable */
protected $displayErrorFunction;
/** var PrepareFormatterOptions[] */
/** @var PrepareFormatterOptions[] */
protected $prepareOptionsList = [];
/** var boolean */
/** @var boolean */
protected $passExceptions;
/** @var ResultWriter */
protected $resultWriter;
/** @var ParameterInjection */
protected $parameterInjection;
public function __construct(HookManager $hookManager)
{
@ -56,6 +58,32 @@ class CommandProcessor implements LoggerAwareInterface
return $this->hookManager;
}
public function resultWriter()
{
if (!$this->resultWriter) {
$this->setResultWriter(new ResultWriter());
}
return $this->resultWriter;
}
public function setResultWriter($resultWriter)
{
$this->resultWriter = $resultWriter;
}
public function parameterInjection()
{
if (!$this->parameterInjection) {
$this->setParameterInjection(new ParameterInjection());
}
return $this->parameterInjection;
}
public function setParameterInjection($parameterInjection)
{
$this->parameterInjection = $parameterInjection;
}
public function addPrepareFormatter(PrepareFormatter $preparer)
{
$this->prepareOptionsList[] = $preparer;
@ -64,13 +92,13 @@ class CommandProcessor implements LoggerAwareInterface
public function setFormatterManager(FormatterManager $formatterManager)
{
$this->formatterManager = $formatterManager;
$this->resultWriter()->setFormatterManager($formatterManager);
return $this;
}
public function setDisplayErrorFunction(callable $fn)
{
$this->displayErrorFunction = $fn;
return $this;
$this->resultWriter()->setDisplayErrorFunction($fn);
}
/**
@ -169,6 +197,9 @@ class CommandProcessor implements LoggerAwareInterface
return $validated;
}
// Once we have validated the optins, create the formatter options.
$this->createFormatterOptions($commandData);
$replaceDispatcher = new ReplaceCommandHookDispatcher($this->hookManager(), $names);
if ($this->logger) {
$replaceDispatcher->setLogger($this->logger);
@ -188,130 +219,6 @@ class CommandProcessor implements LoggerAwareInterface
return $processDispatcher->process($result, $commandData);
}
/**
* Handle the result output and status code calculation.
*/
public function handleResults(OutputInterface $output, $names, $result, CommandData $commandData)
{
$statusCodeDispatcher = new StatusDeterminerHookDispatcher($this->hookManager(), $names);
// A little messy, for backwards compatibility: if the result implements
// ExitCodeInterface, then use that as the exit code. If a status code
// dispatcher returns a non-zero result, then we will never print a
// result.
if ($result instanceof ExitCodeInterface) {
$status = $result->getExitCode();
} else {
$status = $statusCodeDispatcher->determineStatusCode($result);
if (isset($status) && ($status != 0)) {
return $status;
}
}
// If the result is an integer and no separate status code was provided, then use the result as the status and do no output.
if (is_integer($result) && !isset($status)) {
return $result;
}
$status = $this->interpretStatusCode($status);
// Get the structured output, the output stream and the formatter
$extractDispatcher = new ExtracterHookDispatcher($this->hookManager(), $names);
$structuredOutput = $extractDispatcher->extractOutput($result);
if (($status != 0) && is_string($structuredOutput)) {
$output = $this->chooseOutputStream($output, $status);
return $this->writeErrorMessage($output, $status, $structuredOutput, $result);
}
if ($this->dataCanBeFormatted($structuredOutput) && isset($this->formatterManager)) {
return $this->writeUsingFormatter($output, $structuredOutput, $commandData, $status);
}
return $this->writeCommandOutput($output, $structuredOutput, $status);
}
protected function dataCanBeFormatted($structuredOutput)
{
if (!isset($this->formatterManager)) {
return false;
}
return
is_object($structuredOutput) ||
is_array($structuredOutput);
}
/**
* Run the main command callback
*/
protected function runCommandCallback($commandCallback, CommandData $commandData)
{
$result = false;
try {
$args = $commandData->getArgsAndOptions();
$result = call_user_func_array($commandCallback, $args);
} catch (\Exception $e) {
$result = $this->commandErrorForException($e);
}
return $result;
}
/**
* Determine the formatter that should be used to render
* output.
*
* If the user specified a format via the --format option,
* then always return that. Otherwise, return the default
* format, unless --pipe was specified, in which case
* return the default pipe format, format-pipe.
*
* n.b. --pipe is a handy option introduced in Drush 2
* (or perhaps even Drush 1) that indicates that the command
* should select the output format that is most appropriate
* for use in scripts (e.g. to pipe to another command).
*
* @return string
*/
protected function getFormat(FormatterOptions $options)
{
// In Symfony Console, there is no way for us to differentiate
// between the user specifying '--format=table', and the user
// not specifying --format when the default value is 'table'.
// Therefore, we must make --field always override --format; it
// cannot become the default value for --format.
if ($options->get('field')) {
return 'string';
}
$defaults = [];
if ($options->get('pipe')) {
return $options->get('pipe-format', [], 'tsv');
}
return $options->getFormat($defaults);
}
/**
* Determine whether we should use stdout or stderr.
*/
protected function chooseOutputStream(OutputInterface $output, $status)
{
// If the status code indicates an error, then print the
// result to stderr rather than stdout
if ($status && ($output instanceof ConsoleOutputInterface)) {
return $output->getErrorOutput();
}
return $output;
}
/**
* Call the formatter to output the provided data.
*/
protected function writeUsingFormatter(OutputInterface $output, $structuredOutput, CommandData $commandData, $status = 0)
{
$formatterOptions = $this->createFormatterOptions($commandData);
$format = $this->getFormat($formatterOptions);
$this->formatterManager->write(
$output,
$format,
$structuredOutput,
$formatterOptions
);
return $status;
}
/**
* Create a FormatterOptions object for use in writing the formatted output.
* @param CommandData $commandData
@ -324,52 +231,38 @@ class CommandProcessor implements LoggerAwareInterface
foreach ($this->prepareOptionsList as $preparer) {
$preparer->prepare($commandData, $formatterOptions);
}
$commandData->setFormatterOptions($formatterOptions);
return $formatterOptions;
}
/**
* Description
* @param OutputInterface $output
* @param int $status
* @param string $structuredOutput
* @param mixed $originalResult
* @return type
* Handle the result output and status code calculation.
*/
protected function writeErrorMessage($output, $status, $structuredOutput, $originalResult)
public function handleResults(OutputInterface $output, $names, $result, CommandData $commandData)
{
if (isset($this->displayErrorFunction)) {
call_user_func($this->displayErrorFunction, $output, $structuredOutput, $status, $originalResult);
} else {
$this->writeCommandOutput($output, $structuredOutput);
}
return $status;
$statusCodeDispatcher = new StatusDeterminerHookDispatcher($this->hookManager(), $names);
$extractDispatcher = new ExtracterHookDispatcher($this->hookManager(), $names);
return $this->resultWriter()->handle($output, $result, $commandData, $statusCodeDispatcher, $extractDispatcher);
}
/**
* If the result object is a string, then print it.
* Run the main command callback
*/
protected function writeCommandOutput(
OutputInterface $output,
$structuredOutput,
$status = 0
) {
// If there is no formatter, we will print strings,
// but can do no more than that.
if (is_string($structuredOutput)) {
$output->writeln($structuredOutput);
protected function runCommandCallback($commandCallback, CommandData $commandData)
{
$result = false;
try {
$args = $this->parameterInjection()->args($commandData);
$result = call_user_func_array($commandCallback, $args);
} catch (\Exception $e) {
$result = $this->commandErrorForException($e);
}
return $status;
return $result;
}
/**
* If a status code was set, then return it; otherwise,
* presume success.
*/
protected function interpretStatusCode($status)
public function injectIntoCommandData($commandData, $injectedClasses)
{
if (isset($status)) {
return $status;
}
return 0;
$this->parameterInjection()->injectIntoCommandData($commandData, $injectedClasses);
}
}

View file

@ -41,7 +41,7 @@ class CommandResult implements ExitCodeInterface, OutputDataInterface
public static function exitCode($exitCode)
{
return new self($null, $exitCode);
return new self(null, $exitCode);
}
public static function data($data)

View file

@ -0,0 +1,76 @@
<?php
namespace Consolidation\AnnotatedCommand\Help;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Consolidation\AnnotatedCommand\AnnotatedCommand;
class HelpDocumentBuilder
{
public static function alter(\DomDocument $originalDom, AnnotatedCommand $command)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $command->getName());
$commandXML->setAttribute('name', $command->getName());
// Get the original <command> element and its top-level elements.
$originalCommandXML = static::getSingleElementByTagName($dom, $originalDom, 'command');
$originalUsagesXML = static::getSingleElementByTagName($dom, $originalCommandXML, 'usages');
$originalDescriptionXML = static::getSingleElementByTagName($dom, $originalCommandXML, 'description');
$originalHelpXML = static::getSingleElementByTagName($dom, $originalCommandXML, 'help');
$originalArgumentsXML = static::getSingleElementByTagName($dom, $originalCommandXML, 'arguments');
$originalOptionsXML = static::getSingleElementByTagName($dom, $originalCommandXML, 'options');
// Keep only the first of the <usage> elements
$newUsagesXML = $dom->createElement('usages');
$firstUsageXML = static::getSingleElementByTagName($dom, $originalUsagesXML, 'usage');
$newUsagesXML->appendChild($firstUsageXML);
// Create our own <example> elements
$newExamplesXML = $dom->createElement('examples');
foreach ($command->getExampleUsages() as $usage => $description) {
$newExamplesXML->appendChild($exampleXML = $dom->createElement('example'));
$exampleXML->appendChild($usageXML = $dom->createElement('usage', $usage));
$exampleXML->appendChild($descriptionXML = $dom->createElement('description', $description));
}
// Create our own <alias> elements
$newAliasesXML = $dom->createElement('aliases');
foreach ($command->getAliases() as $alias) {
$newAliasesXML->appendChild($dom->createElement('alias', $alias));
}
// Create our own <topic> elements
$newTopicsXML = $dom->createElement('topics');
foreach ($command->getTopics() as $topic) {
$newTopicsXML->appendChild($topicXML = $dom->createElement('topic', $topic));
}
// Place the different elements into the <command> element in the desired order
$commandXML->appendChild($newUsagesXML);
$commandXML->appendChild($newExamplesXML);
$commandXML->appendChild($originalDescriptionXML);
$commandXML->appendChild($originalArgumentsXML);
$commandXML->appendChild($originalOptionsXML);
$commandXML->appendChild($originalHelpXML);
$commandXML->appendChild($newAliasesXML);
$commandXML->appendChild($newTopicsXML);
return $dom;
}
protected static function getSingleElementByTagName($dom, $parent, $tagName)
{
// There should always be exactly one '<command>' element.
$elements = $parent->getElementsByTagName($tagName);
$result = $elements->item(0);
$result = $dom->importNode($result, true);
return $result;
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace Consolidation\AnnotatedCommand\Input;
/**
* StdinAwareInterface should be implemented by classes that read from
* standard input. This class contains facilities to redirect stdin to
* instead read from a file, e.g. in response to an option or argument
* value.
*
* Using StdinAwareInterface is preferable to reading from php://stdin
* directly, as it provides a mechanism to instead inject an instance
* of StdinHandler that reads from a file, e.g. in tests.
*
* n.b. If the standard input handler is fetched prior to any code
* injecting an stdin handler, you will get an object that is configured
* to read from php://stdin.
*/
interface StdinAwareInterface
{
/**
* Sets the standard input handler.
*
* @param StdinHandler
*/
public function setStdinHandler(StdinHandler $stdin);
/**
* Returns the standard input handler.
*
* @return StdinHandler
*/
public function stdin();
}

View file

@ -0,0 +1,30 @@
<?php
namespace Consolidation\AnnotatedCommand\Input;
/**
* StdinAwareTrait provides the implementation for StdinAwareInterface.
*/
trait StdinAwareTrait
{
protected $stdinHandler;
/**
* @inheritdoc
*/
public function setStdinHandler(StdinHandler $stdin)
{
$this->stdinHandler = $stdin;
}
/**
* @inheritdoc
*/
public function stdin()
{
if (!$this->stdinHandler) {
$this->stdinHandler = new StdinHandler();
}
return $this->stdinHandler;
}
}

View file

@ -0,0 +1,247 @@
<?php
namespace Consolidation\AnnotatedCommand\Input;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Input\InputInterface;
/**
* StdinHandler is a thin wrapper around php://stdin. It provides
* methods for redirecting input from a file, possibly conditionally
* under the control of an Input object.
*
* Example trivial usage (always reads from stdin):
*
* class Example implements StdinAwareInterface
* {
* /**
* * @command cat
* * @param string $file
* * @default $file -
* * /
* public function cat()
* {
* print($this->stdin()->contents());
* }
* }
*
* Command that reads from stdin or file via an option:
*
* /**
* * @command cat
* * @param string $file
* * @default $file -
* * /
* public function cat(InputInterface $input)
* {
* $data = $this->stdin()->select($input, 'file')->contents();
* }
*
* Command that reads from stdin or file via an option:
*
* /**
* * @command cat
* * @option string $file
* * @default $file -
* * /
* public function cat(InputInterface $input)
* {
* $data = $this->stdin()->select($input, 'file')->contents();
* }
*
* It is also possible to inject the selected stream into the input object,
* e.g. if you want the contents of the source file to be fed to any Question
* helper et. al. that the $input object is used with.
*
* /**
* * @command example
* * @option string $file
* * @default $file -
* * /
* public function example(InputInterface $input)
* {
* $this->stdin()->setStream($input, 'file');
* }
*
*
* Inject an alternate source for standard input in tests. Presumes that
* the object under test gets a reference to the StdinHandler via dependency
* injection from the container.
*
* $container->get('stdinHandler')->redirect($pathToTestStdinFileFixture);
*
* You may also inject your stdin file fixture stream into the $input object
* as usual, and then use it with 'select()' or 'setStream()' as shown above.
*
* Finally, this class may also be used in absence of a dependency injection
* container by using the static 'selectStream()' method:
*
* /**
* * @command example
* * @option string $file
* * @default $file -
* * /
* public function example(InputInterface $input)
* {
* $data = StdinHandler::selectStream($input, 'file')->contents();
* }
*
* To test a method that uses this technique, simply inject your stdin
* fixture into the $input object in your test:
*
* $input->setStream(fopen($pathToFixture, 'r'));
*/
class StdinHandler
{
protected $path;
protected $stream;
public static function selectStream(InputInterface $input, $optionOrArg)
{
$handler = new Self();
return $handler->setStream($input, $optionOrArg);
}
/**
* hasPath returns 'true' if the stdin handler has a path to a file.
*
* @return bool
*/
public function hasPath()
{
// Once the stream has been opened, we mask the existence of the path.
return !$this->hasStream() && !empty($this->path);
}
/**
* hasStream returns 'true' if the stdin handler has opened a stream.
*
* @return bool
*/
public function hasStream()
{
return !empty($this->stream);
}
/**
* path returns the path to any file that was set as a redirection
* source, or `php://stdin` if none have been.
*
* @return string
*/
public function path()
{
return $this->path ?: 'php://stdin';
}
/**
* close closes the input stream if it was opened.
*/
public function close()
{
if ($this->hasStream()) {
fclose($this->stream);
$this->stream = null;
}
return $this;
}
/**
* redirect specifies a path to a file that should serve as the
* source to read from. If the input path is '-' or empty,
* then output will be taken from php://stdin (or whichever source
* was provided via the 'redirect' method).
*
* @return $this
*/
public function redirect($path)
{
if ($this->pathProvided($path)) {
$this->path = $path;
}
return $this;
}
/**
* select chooses the source of the input stream based on whether or
* not the user provided the specified option or argument on the commandline.
* Stdin is selected if there is no user selection.
*
* @param InputInterface $input
* @param string $optionOrArg
* @return $this
*/
public function select(InputInterface $input, $optionOrArg)
{
$this->redirect($this->getOptionOrArg($input, $optionOrArg));
if (!$this->hasPath() && ($input instanceof StreamableInputInterface)) {
$this->stream = $input->getStream();
}
return $this;
}
/**
* getStream opens and returns the stdin stream (or redirect file).
*/
public function getStream()
{
if (!$this->hasStream()) {
$this->stream = fopen($this->path(), 'r');
}
return $this->stream;
}
/**
* setStream functions like 'select', and also sets up the $input
* object to read from the selected input stream e.g. when used
* with a question helper.
*/
public function setStream(InputInterface $input, $optionOrArg)
{
$this->select($input, $optionOrArg);
if ($input instanceof StreamableInputInterface) {
$stream = $this->getStream();
$input->setStream($stream);
}
return $this;
}
/**
* contents reads the entire contents of the standard input stream.
*
* @return string
*/
public function contents()
{
// Optimization: use file_get_contents if we have a path to a file
// and the stream has not been opened yet.
if (!$this->hasStream()) {
return file_get_contents($this->path());
}
$stream = $this->getStream();
stream_set_blocking($stream, false); // TODO: We did this in backend invoke. Necessary here?
$contents = stream_get_contents($stream);
$this->close();
return $contents;
}
/**
* Returns 'true' if a path was specfied, and that path was not '-'.
*/
protected function pathProvided($path)
{
return !empty($path) && ($path != '-');
}
protected function getOptionOrArg(InputInterface $input, $optionOrArg)
{
if ($input->hasOption($optionOrArg)) {
return $input->getOption($optionOrArg);
}
return $input->getArgument($optionOrArg);
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace Consolidation\AnnotatedCommand;
/**
* Prepare parameter list for execurion. Handle injection of any
* special values (e.g. $input and $output) into the parameter list.
*/
class ParameterInjection implements ParameterInjector
{
public function __construct()
{
$this->register('Symfony\Component\Console\Input\InputInterface', $this);
$this->register('Symfony\Component\Console\Output\OutputInterface', $this);
}
public function register($interfaceName, ParameterInjector $injector)
{
$this->injectors[$interfaceName] = $injector;
}
public function args($commandData)
{
return array_merge(
$commandData->injectedInstances(),
$commandData->getArgsAndOptions()
);
}
public function injectIntoCommandData($commandData, $injectedClasses)
{
foreach ($injectedClasses as $injectedClass) {
$injectedInstance = $this->getInstanceToInject($commandData, $injectedClass);
$commandData->injectInstance($injectedInstance);
}
}
protected function getInstanceToInject(CommandData $commandData, $interfaceName)
{
if (!isset($this->injectors[$interfaceName])) {
return null;
}
return $this->injectors[$interfaceName]->get($commandData, $interfaceName);
}
public function get(CommandData $commandData, $interfaceName)
{
switch ($interfaceName) {
case 'Symfony\Component\Console\Input\InputInterface':
return $commandData->input();
case 'Symfony\Component\Console\Output\OutputInterface':
return $commandData->output();
}
return null;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Consolidation\AnnotatedCommand;
/**
* Provide an object for the specified interface or class name.
*/
interface ParameterInjector
{
public function get(CommandData $commandData, $interfaceName);
}

View file

@ -88,6 +88,11 @@ class CommandInfo
*/
protected $returnType;
/**
* @var string[]
*/
protected $injectedClasses = [];
/**
* Create a new CommandInfo class for a particular method of a class.
*
@ -203,6 +208,12 @@ class CommandInfo
return $this->returnType;
}
public function getInjectedClasses()
{
$this->parseDocBlock();
return $this->injectedClasses;
}
public function setReturnType($returnType)
{
$this->returnType = $returnType;
@ -634,6 +645,11 @@ class CommandInfo
if ($this->lastParameterIsOptionsArray()) {
array_pop($params);
}
while (!empty($params) && ($params[0]->getClass() != null)) {
$param = array_shift($params);
$injectedClass = $param->getClass()->getName();
array_unshift($this->injectedClasses, $injectedClass);
}
foreach ($params as $param) {
$this->addParameterToResult($result, $param);
}

View file

@ -20,7 +20,7 @@ class BespokeDocBlockParser
'command' => 'processCommandTag',
'name' => 'processCommandTag',
'arg' => 'processArgumentTag',
'param' => 'processArgumentTag',
'param' => 'processParamTag',
'return' => 'processReturnTag',
'option' => 'processOptionTag',
'default' => 'processDefaultTag',
@ -83,6 +83,31 @@ class BespokeDocBlockParser
$this->commandInfo->setDescription($tag->getContent());
}
/**
* Store the data from a @param annotation in our argument descriptions.
*/
protected function processParamTag($tag)
{
if ($tag->hasTypeVariableAndDescription($matches)) {
if ($this->ignoredParamType($matches['type'])) {
return;
}
}
return $this->processArgumentTag($tag);
}
protected function ignoredParamType($paramType)
{
// TODO: We should really only allow a couple of types here,
// e.g. 'string', 'array', 'bool'. Blacklist things we do not
// want for now to avoid breaking commands with weird types.
// Fix in the next major version.
//
// This works:
// return !in_array($paramType, ['string', 'array', 'integer', 'bool']);
return preg_match('#(InputInterface|OutputInterface)$#', $paramType);
}
/**
* Store the data from a @arg annotation in our argument descriptions.
*/

View file

@ -0,0 +1,210 @@
<?php
namespace Consolidation\AnnotatedCommand;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ReplaceCommandHookDispatcher;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Consolidation\OutputFormatters\FormatterManager;
use Consolidation\OutputFormatters\Options\FormatterOptions;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Consolidation\AnnotatedCommand\Options\PrepareFormatter;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\OptionsHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\InteractHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ValidateHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ProcessResultHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\StatusDeterminerHookDispatcher;
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ExtracterHookDispatcher;
/**
* Write the results of a command. Inject your ResultWriter
* into the CommandProcessor.
*/
class ResultWriter
{
/** var FormatterManager */
protected $formatterManager;
/** @var callable */
protected $displayErrorFunction;
public function setFormatterManager(FormatterManager $formatterManager)
{
$this->formatterManager = $formatterManager;
return $this;
}
/**
* Return the formatter manager
* @return FormatterManager
*/
public function formatterManager()
{
return $this->formatterManager;
}
public function setDisplayErrorFunction(callable $fn)
{
$this->displayErrorFunction = $fn;
return $this;
}
/**
* Handle the result output and status code calculation.
*/
public function handle(OutputInterface $output, $result, CommandData $commandData, $statusCodeDispatcher = null, $extractDispatcher = null)
{
// A little messy, for backwards compatibility: if the result implements
// ExitCodeInterface, then use that as the exit code. If a status code
// dispatcher returns a non-zero result, then we will never print a
// result.
$status = null;
if ($result instanceof ExitCodeInterface) {
$status = $result->getExitCode();
} elseif (isset($statusCodeDispatcher)) {
$status = $statusCodeDispatcher->determineStatusCode($result);
if (isset($status) && ($status != 0)) {
return $status;
}
}
// If the result is an integer and no separate status code was provided, then use the result as the status and do no output.
if (is_integer($result) && !isset($status)) {
return $result;
}
$status = $this->interpretStatusCode($status);
// Get the structured output, the output stream and the formatter
$structuredOutput = $result;
if (isset($extractDispatcher)) {
$structuredOutput = $extractDispatcher->extractOutput($result);
}
if (($status != 0) && is_string($structuredOutput)) {
$output = $this->chooseOutputStream($output, $status);
return $this->writeErrorMessage($output, $status, $structuredOutput, $result);
}
if ($this->dataCanBeFormatted($structuredOutput) && isset($this->formatterManager)) {
return $this->writeUsingFormatter($output, $structuredOutput, $commandData, $status);
}
return $this->writeCommandOutput($output, $structuredOutput, $status);
}
protected function dataCanBeFormatted($structuredOutput)
{
if (!isset($this->formatterManager)) {
return false;
}
return
is_object($structuredOutput) ||
is_array($structuredOutput);
}
/**
* Determine the formatter that should be used to render
* output.
*
* If the user specified a format via the --format option,
* then always return that. Otherwise, return the default
* format, unless --pipe was specified, in which case
* return the default pipe format, format-pipe.
*
* n.b. --pipe is a handy option introduced in Drush 2
* (or perhaps even Drush 1) that indicates that the command
* should select the output format that is most appropriate
* for use in scripts (e.g. to pipe to another command).
*
* @return string
*/
protected function getFormat(FormatterOptions $options)
{
// In Symfony Console, there is no way for us to differentiate
// between the user specifying '--format=table', and the user
// not specifying --format when the default value is 'table'.
// Therefore, we must make --field always override --format; it
// cannot become the default value for --format.
if ($options->get('field')) {
return 'string';
}
$defaults = [];
if ($options->get('pipe')) {
return $options->get('pipe-format', [], 'tsv');
}
return $options->getFormat($defaults);
}
/**
* Determine whether we should use stdout or stderr.
*/
protected function chooseOutputStream(OutputInterface $output, $status)
{
// If the status code indicates an error, then print the
// result to stderr rather than stdout
if ($status && ($output instanceof ConsoleOutputInterface)) {
return $output->getErrorOutput();
}
return $output;
}
/**
* Call the formatter to output the provided data.
*/
protected function writeUsingFormatter(OutputInterface $output, $structuredOutput, CommandData $commandData, $status = 0)
{
$formatterOptions = $commandData->formatterOptions();
$format = $this->getFormat($formatterOptions);
$this->formatterManager->write(
$output,
$format,
$structuredOutput,
$formatterOptions
);
return $status;
}
/**
* Description
* @param OutputInterface $output
* @param int $status
* @param string $structuredOutput
* @param mixed $originalResult
* @return type
*/
protected function writeErrorMessage($output, $status, $structuredOutput, $originalResult)
{
if (isset($this->displayErrorFunction)) {
call_user_func($this->displayErrorFunction, $output, $structuredOutput, $status, $originalResult);
} else {
$this->writeCommandOutput($output, $structuredOutput);
}
return $status;
}
/**
* If the result object is a string, then print it.
*/
protected function writeCommandOutput(
OutputInterface $output,
$structuredOutput,
$status = 0
) {
// If there is no formatter, we will print strings,
// but can do no more than that.
if (is_string($structuredOutput)) {
$output->writeln($structuredOutput);
}
return $status;
}
/**
* If a status code was set, then return it; otherwise,
* presume success.
*/
protected function interpretStatusCode($status)
{
if (isset($status)) {
return $status;
}
return 0;
}
}

View file

@ -0,0 +1,57 @@
#!/bin/bash
SCENARIO=$1
DEPENDENCIES=${2-install}
# Convert the aliases 'highest', 'lowest' and 'lock' to
# the corresponding composer command to run.
case $DEPENDENCIES in
highest)
DEPENDENCIES=update
;;
lowest)
DEPENDENCIES='update --prefer-lowest'
;;
lock|default|"")
DEPENDENCIES=install
;;
esac
original_name=scenarios
recommended_name=".scenarios.lock"
base="$original_name"
if [ -d "$recommended_name" ] ; then
base="$recommended_name"
fi
# If scenario is not specified, install the lockfile at
# the root of the project.
dir="$base/${SCENARIO}"
if [ -z "$SCENARIO" ] || [ "$SCENARIO" == "default" ] ; then
SCENARIO=default
dir=.
fi
# Test to make sure that the selected scenario exists.
if [ ! -d "$dir" ] ; then
echo "Requested scenario '${SCENARIO}' does not exist."
exit 1
fi
echo
echo "::"
echo ":: Switch to ${SCENARIO} scenario"
echo "::"
echo
set -ex
composer -n validate --working-dir=$dir --no-check-all --ansi
composer -n --working-dir=$dir ${DEPENDENCIES} --prefer-dist --no-scripts
# If called from a CI context, print out some extra information about
# what we just installed.
if [[ -n "$CI" ]] ; then
composer -n --working-dir=$dir info
fi

View file

@ -0,0 +1 @@
vendor

View file

@ -8,26 +8,25 @@
"email": "greg.1.anderson@greenknowe.org"
}
],
"autoload":{
"psr-4":{
"Consolidation\\Log\\": "src"
"autoload": {
"psr-4": {
"Consolidation\\Log\\": "../../src"
}
},
"autoload-dev": {
"psr-4": {
"Consolidation\\TestUtils\\": "tests/src"
"Consolidation\\TestUtils\\": "../../tests/src"
}
},
"require": {
"php": ">=5.5.0",
"psr/log": "~1.0"
"php": ">=5.4.5",
"psr/log": "^1.0",
"symfony/console": "^2.8|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"g1a/composer-test-scenarios": "^1",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "2.*",
"symfony/console": "^4.0"
"phpunit/phpunit": "^4.8.36",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2"
},
"minimum-stability": "stable",
"scripts": {
@ -42,11 +41,6 @@
"@lint",
"@unit",
"@cs"
],
"scenario": "scenarios/install",
"post-update-cmd": [
"create-scenario symfony4 'symfony/console:^4.0'",
"create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.5' --no-lockfile"
]
},
"extra": {
@ -56,8 +50,10 @@
},
"config": {
"platform": {
"php": "5.4.8"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
vendor

View file

@ -8,26 +8,25 @@
"email": "greg.1.anderson@greenknowe.org"
}
],
"autoload":{
"psr-4":{
"Consolidation\\Log\\": "src"
"autoload": {
"psr-4": {
"Consolidation\\Log\\": "../../src"
}
},
"autoload-dev": {
"psr-4": {
"Consolidation\\TestUtils\\": "tests/src"
"Consolidation\\TestUtils\\": "../../tests/src"
}
},
"require": {
"php": ">=5.5.0",
"psr/log": "~1.0"
"symfony/console": "^2.8",
"php": ">=5.4.5",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"g1a/composer-test-scenarios": "^1",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "2.*",
"symfony/console": "^2.8"
"phpunit/phpunit": "^4.8.36",
"g1a/composer-test-scenarios": "^3",
"squizlabs/php_codesniffer": "^2"
},
"minimum-stability": "stable",
"scripts": {
@ -42,11 +41,6 @@
"@lint",
"@unit",
"@cs"
],
"scenario": "scenarios/install",
"post-update-cmd": [
"create-scenario symfony4 'symfony/console:^4.0'",
"create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.5' --no-lockfile"
]
},
"extra": {
@ -56,8 +50,10 @@
},
"config": {
"platform": {
"php": "5.5"
"php": "5.4.8"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
vendor

View file

@ -0,0 +1,60 @@
{
"name": "consolidation/log",
"description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
"license": "MIT",
"authors": [
{
"name": "Greg Anderson",
"email": "greg.1.anderson@greenknowe.org"
}
],
"autoload": {
"psr-4": {
"Consolidation\\Log\\": "../../src"
}
},
"autoload-dev": {
"psr-4": {
"Consolidation\\TestUtils\\": "../../tests/src"
}
},
"require": {
"symfony/console": "^4.0",
"php": ">=5.4.5",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^6",
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"squizlabs/php_codesniffer": "^2"
},
"minimum-stability": "stable",
"scripts": {
"cs": "phpcs -n --standard=PSR2 src",
"cbf": "phpcbf -n --standard=PSR2 src",
"unit": "phpunit",
"lint": [
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
"find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l"
],
"test": [
"@lint",
"@unit",
"@cs"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"config": {
"platform": {
"php": "7.1.3"
},
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "../../vendor"
}
}

File diff suppressed because it is too large Load diff

View file

@ -9,15 +9,18 @@ branches:
matrix:
include:
- php: 7.2
env: 'SCENARIO=symfony4 HIGHEST_LOWEST="update"'
env: 'SCENARIO=symfony4 DEPENDENCIES=highest'
- php: 7.1
env: 'SCENARIO=symfony4'
- php: 7.0.11
env: 'HIGHEST_LOWEST="update"'
- php: 7.0.11
- php: 7.0
env: 'DEPENDENCIES=highest'
- php: 7.0
- php: 5.6
env: 'SCENARIO=phpunit4'
- php: 5.5
env: 'SCENARIO=symfony2 HIGHEST_LOWEST="update --prefer-lowest'
env: 'SCENARIO=phpunit4'
- php: 5.4
env: 'SCENARIO=symfony2 DEPENDENCIES=lowest'
sudo: false
@ -27,10 +30,10 @@ cache:
- $HOME/.composer/cache
install:
- 'composer scenario "${SCENARIO}" "${HIGHEST_LOWEST-install}"'
- '.scenarios.lock/install "${SCENARIO}" "${DEPENDENCIES}"'
script:
- composer test
after_success:
- travis_retry php vendor/bin/coveralls -v
- 'travis_retry php vendor/bin/php-coveralls -v'

35
vendor/consolidation/log/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,35 @@
# Change Log
### 1.1.1: 2019-1-1
- Allow logger manager to manage a global style for loggers (#12)
### 1.1.0: 2018-12-29
- Add a logger manager (#11)
- Update to Composer Test Scenarios 3 (#10)
### 1.0.6: 2018-05-25
- Use g1a/composer-test-scenarios (#9)
### 1.0.5: 2017-11-28
- Test Symfony version 2, 3 and 4 with different versions of php. (#5)
### 1.0.4: 2017-11-18
- Support for Symfony 4 by Tobias Nyholm (#4)
### 1.0.3: 2016-03-23
- Split up the log() method a bit.
- Run code sniffer prior to running tests to ensure PSR-2 compliance.
### 1.0.2: 2016-03-22
- Remove unused components accidentally left in composer.json.
### 1.0.1: 2016-03-19
- Add a license file.

View file

@ -1,4 +1,4 @@
Copyright (c) 2016 Consolidation Org Developers
Copyright (c) 2016-2018 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:
@ -6,3 +6,11 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
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.
DEPENDENCY LICENSES:
Name Version License
psr/log 1.1.0 MIT
symfony/console v2.8.49 MIT
symfony/debug v2.8.49 MIT
symfony/polyfill-mbstring v1.10.0 MIT

View file

@ -2,7 +2,7 @@
Improved [PSR-3](http://www.php-fig.org/psr/psr-3/) [Psr\Log](https://github.com/php-fig/log) logger based on Symfony Console components.
[![Travis CI](https://travis-ci.org/consolidation-org/log.svg?branch=master)](https://travis-ci.org/consolidation-org/log) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/consolidation-org/log/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/consolidation-org/log/?branch=master) [![Coverage Status](https://coveralls.io/repos/github/consolidation-org/log/badge.svg?branch=master)](https://coveralls.io/github/consolidation-org/log?branch=master) [![License](https://poser.pugx.org/consolidation/log/license)](https://packagist.org/packages/consolidation/log)
[![Travis CI](https://travis-ci.org/consolidation/log.svg?branch=master)](https://travis-ci.org/consolidation/log) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/consolidation/log/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/consolidation/log/?branch=master) [![Coverage Status](https://coveralls.io/repos/github/consolidation/log/badge.svg?branch=master)](https://coveralls.io/github/consolidation/log?branch=master) [![License](https://poser.pugx.org/consolidation/log/license)](https://packagist.org/packages/consolidation/log)
## Component Status
@ -10,7 +10,7 @@ In use in [Robo](https://github.com/Codegyre/Robo).
## Motivation
Consolidation\Log provides a Psr-3 compatible logger that provides styled log output to the standard error (stderr) stream. By default, styling is provided by the SymfonyStyle class from the Symfony Console component; however, alternative stylers may be provided if desired.
Consolidation\Log provides a PSR-3 compatible logger that provides styled log output to the standard error (stderr) stream. By default, styling is provided by the SymfonyStyle class from the Symfony Console component; however, alternative stylers may be provided if desired.
## Usage
```
@ -18,10 +18,17 @@ $logger = new \Consolidation\Log\Logger($output);
$logger->setLogOutputStyler(new LogOutputStyler()); // optional
$logger->warning('The file {name} does not exist.', ['name' => $filename]);
```
String interpolation -- that is, the substitution of replacements, such as `{name}` in the example above, is not required by Psr-3, and is not implemented by default in the Psr\Log project. However, it is recommended by PRS-3, and is often done, e.g. in the Symfony Console logger.
String interpolation -- that is, the substitution of replacements, such as `{name}` in the example above, is not required by PSR-3, and is not implemented by default in the Psr\Log project. However, it is recommended by PRS-3, and is often done, e.g. in the Symfony Console logger.
Consolidation\Log supports string interpolation.
A logger manager can be used to delegate all log messages to one or more loggers.
```
$logger = new \Consolidation\Log\LoggerManager();
$logger->add('default', new \Consolidation\Log\Logger($output));
```
This is useful if, for example, you need to inject a logger into application objects early (e.g. into a dependency injection container), but the output object to log to will not be available until later.
## Comparison to Existing Solutions
Many Symfony Console compoenents use SymfonyStyle to format their output messages. This helper class has methods named things like `success` and `warning`, making it seem like a natural choice for reporting status.

View file

@ -19,15 +19,15 @@
}
},
"require": {
"php": ">=5.5.0",
"psr/log": "~1.0",
"php": ">=5.4.5",
"psr/log": "^1.0",
"symfony/console": "^2.8|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"g1a/composer-test-scenarios": "^1",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "2.*"
"phpunit/phpunit": "^6",
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"squizlabs/php_codesniffer": "^2"
},
"minimum-stability": "stable",
"scripts": {
@ -42,21 +42,59 @@
"@lint",
"@unit",
"@cs"
],
"scenario": "scenarios/install",
"post-update-cmd": [
"create-scenario symfony4 'symfony/console:^4.0'",
"create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.5' --no-lockfile"
]
},
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"config": {
"optimize-autoloader": true,
"sort-packages": true,
"platform": {
"php": "5.6"
"php": "7.0.8"
}
}
}

1171
vendor/consolidation/log/composer.lock generated vendored

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="log">
<directory prefix="test" suffix=".php">tests</directory>
<directory suffix="Tests.php">tests</directory>
</testsuite>
</testsuites>
<logging>

View file

@ -1,28 +0,0 @@
#!/bin/bash
SCENARIO=$1
ACTION=${2-install}
dir=scenarios/${SCENARIO}
if [ -z "$SCENARIO" ] ; then
SCENARIO=default
dir=.
fi
if [ ! -d "$dir" ] ; then
echo "Requested scenario '${SCENARIO}' does not exist."
exit 1
fi
echo
echo "::"
echo ":: Switch to ${SCENARIO} scenario"
echo "::"
echo
set -ex
composer -n validate --working-dir=$dir --no-check-all --ansi
composer -n --working-dir=$dir ${ACTION} --prefer-dist --no-scripts
composer -n --working-dir=$dir info

View file

@ -1 +0,0 @@
vendor

View file

@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\StringInput;
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
class Logger extends AbstractLogger // extends ConsoleLogger
class Logger extends AbstractLogger implements StylableLoggerInterface // extends ConsoleLogger
{
/**
* @var OutputInterface

View file

@ -0,0 +1,121 @@
<?php
namespace Consolidation\Log;
use Psr\Log\AbstractLogger;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
/**
* LoggerManager is a PSR-3 logger that can delegate
* log messages to other loggers. This is ideal if
* you need to inject a logger into various objects
* in your application, but need to change the way that
* the application logs later.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
class LoggerManager extends AbstractLogger implements StylableLoggerInterface
{
/** @var LoggerInterface[] */
protected $loggers = [];
/** @var LoggerInterface */
protected $fallbackLogger = null;
/** @var LogOutputStylerInterface */
protected $outputStyler;
/** @var array */
protected $formatFunctionMap = [];
/**
* reset removes all loggers from the manager.
*/
public function reset()
{
$this->loggers = [];
return $this;
}
/**
* setLogOutputStyler will remember a style that
* should be applied to every stylable logger
* added to this manager.
*/
public function setLogOutputStyler(LogOutputStylerInterface $outputStyler, array $formatFunctionMap = array())
{
$this->outputStyler = $outputStyler;
$this->formatFunctionMap = $this->formatFunctionMap;
}
/**
* add adds a named logger to the manager,
* replacing any logger of the same name.
*
* @param string $name Name of logger to add
* @param LoggerInterface $logger Logger to send messages to
*/
public function add($name, LoggerInterface $logger)
{
// If this manager has been given a log style,
// and the logger being added accepts a log
// style, then copy our style to the logger
// being added.
if ($this->outputStyler && $logger instanceof StylableLoggerInterface) {
$logger->setLogOutputStyler($this->outputStyler, $this->formatFunctionMap);
}
$this->loggers[$name] = $logger;
return $this;
}
/**
* remove a named logger from the manager.
*
* @param string $name Name of the logger to remove.
*/
public function remove($name)
{
unset($this->loggers[$name]);
return $this;
}
/**
* fallbackLogger provides a logger that will
* be used only in instances where someone logs
* to the logger manager at a time when there
* are no other loggers registered. If there is
* no fallback logger, then the log messages
* are simply dropped.
*
* @param LoggerInterface $logger Logger to use as the fallback logger
*/
public function fallbackLogger(LoggerInterface $logger)
{
$this->fallbackLogger = $logger;
return $this;
}
/**
* {@inheritdoc}
*/
public function log($level, $message, array $context = array())
{
foreach ($this->getLoggers() as $logger) {
$logger->log($level, $message, $context);
}
}
/**
* Return either the list of registered loggers,
* or a single-element list containing only the
* fallback logger.
*/
protected function getLoggers()
{
if (!empty($this->loggers)) {
return $this->loggers;
}
if (isset($this->fallbackLogger)) {
return [ $this->fallbackLogger ];
}
return [];
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\StringInput;
/**
* StylableLoggerInterface indicates that a logger
* can receive a LogOutputStyler.
*
* @author Greg Anderson <greg.1.anderson@greenknowe.org>
*/
interface StylableLoggerInterface
{
public function setLogOutputStyler(LogOutputStylerInterface $outputStyler, array $formatFunctionMap = array());
}

View file

@ -3,8 +3,9 @@ namespace Consolidation\Log;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use PHPUnit\Framework\TestCase;
class LogMethodTests extends \PHPUnit_Framework_TestCase
class LogMethodTests extends TestCase
{
protected $output;
protected $logger;

View file

@ -0,0 +1,69 @@
<?php
namespace Consolidation\Log;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use PHPUnit\Framework\TestCase;
class LoggerManagerTests extends TestCase
{
protected $output;
protected $logger;
function testLoggerManager()
{
$fallbackOutput = new BufferedOutput();
$fallbackOutput->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
$fallbackLogger = new Logger($fallbackOutput);
$fallbackLogger->notice('This is the fallback logger');
$primaryOutput = new BufferedOutput();
$primaryOutput->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
$primaryLogger = new Logger($primaryOutput);
$primaryLogger->notice('This is the primary logger');
$replacementOutput = new BufferedOutput();
$replacementOutput->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
$replacementLogger = new Logger($replacementOutput);
$replacementLogger->notice('This is the replacement logger');
$logger = new LoggerManager();
$logger->notice('Uninitialized logger.');
$logger->fallbackLogger($fallbackLogger);
$logger->notice('Logger with fallback.');
$logger->add('default', $primaryLogger);
$logger->notice('Primary logger');
$logger->add('default', $replacementLogger);
$logger->notice('Replaced logger');
$logger->reset();
$logger->notice('Reset loggers');
$fallbackActual = rtrim($fallbackOutput->fetch());
$primaryActual = rtrim($primaryOutput->fetch());
$replacementActual = rtrim($replacementOutput->fetch());
$actual = "Fallback:\n====\n$fallbackActual\nPrimary:\n====\n$primaryActual\nReplacement:\n====\n$replacementActual";
$actual = preg_replace('# *$#ms', '', $actual);
$actual = preg_replace('#^ *$\n#ms', '', $actual);
$expected = <<< __EOT__
Fallback:
====
! [NOTE] This is the fallback logger
! [NOTE] Logger with fallback.
! [NOTE] Reset loggers
Primary:
====
! [NOTE] This is the primary logger
! [NOTE] Primary logger
Replacement:
====
! [NOTE] This is the replacement logger
! [NOTE] Replaced logger
__EOT__;
$this->assertEquals($expected, $actual);
}
}

View file

@ -4,10 +4,11 @@ namespace Consolidation\Log;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use PHPUnit\Framework\TestCase;
use Consolidation\TestUtils\TestDataPermuter;
class LoggerVerbosityAndStyleTests extends \PHPUnit_Framework_TestCase
class LoggerVerbosityAndStyleTests extends TestCase
{
protected $output;
protected $logger;

View file

@ -28,7 +28,7 @@
"league/container": "^2.2",
"consolidation/log": "~1",
"consolidation/config": "^1.0.10",
"consolidation/annotated-command": "^2.8.2",
"consolidation/annotated-command": "^2.10.2",
"consolidation/output-formatters": "^3.1.13",
"consolidation/self-update": "^1",
"grasmash/yaml-expander": "^1.3",
@ -77,7 +77,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-master": "2.x-dev"
}
},
"suggest": {

View file

@ -28,7 +28,7 @@
"league/container": "^2.2",
"consolidation/log": "~1",
"consolidation/config": "^1.0.10",
"consolidation/annotated-command": "^2.8.2",
"consolidation/annotated-command": "^2.10.2",
"consolidation/output-formatters": "^3.1.13",
"consolidation/self-update": "^1",
"grasmash/yaml-expander": "^1.3",
@ -78,7 +78,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-master": "2.x-dev"
}
},
"suggest": {

View file

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7dc7608acabca5feeb8dc77bfe4e8584",
"content-hash": "1a9adc60403e6c6b6117a465e9afca9f",
"packages": [
{
"name": "consolidation/annotated-command",
"version": "2.10.0",
"version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/consolidation/annotated-command.git",
"reference": "8e7d1a05230dc1159c751809e98b74f2b7f71873"
"reference": "edea407f57104ed518cc3c3b47d5b84403ee267a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/8e7d1a05230dc1159c751809e98b74f2b7f71873",
"reference": "8e7d1a05230dc1159c751809e98b74f2b7f71873",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/edea407f57104ed518cc3c3b47d5b84403ee267a",
"reference": "edea407f57104ed518cc3c3b47d5b84403ee267a",
"shasum": ""
},
"require": {
@ -29,13 +29,57 @@
"symfony/finder": "^2.5|^3|^4"
},
"require-dev": {
"g1a/composer-test-scenarios": "^2",
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"phpunit/phpunit": "^6",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "^2.7"
},
"type": "library",
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
},
"scenario-options": {
"create-lockfile": "false"
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "2.x-dev"
}
@ -56,7 +100,7 @@
}
],
"description": "Initialize Symfony Console commands from annotated command class methods.",
"time": "2018-11-15T01:46:18+00:00"
"time": "2018-12-29T04:43:17+00:00"
},
{
"name": "consolidation/config",
@ -114,31 +158,72 @@
},
{
"name": "consolidation/log",
"version": "1.0.6",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/consolidation/log.git",
"reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395"
"reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/log/zipball/dfd8189a771fe047bf3cd669111b2de5f1c79395",
"reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395",
"url": "https://api.github.com/repos/consolidation/log/zipball/b2e887325ee90abc96b0a8b7b474cd9e7c896e3a",
"reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"psr/log": "~1.0",
"php": ">=5.4.5",
"psr/log": "^1.0",
"symfony/console": "^2.8|^3|^4"
},
"require-dev": {
"g1a/composer-test-scenarios": "^1",
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "2.*"
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^2"
},
"type": "library",
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "1.x-dev"
}
@ -159,7 +244,7 @@
}
],
"description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
"time": "2018-05-25T18:14:39+00:00"
"time": "2019-01-01T17:30:51+00:00"
},
{
"name": "consolidation/output-formatters",
@ -615,20 +700,21 @@
},
{
"name": "symfony/console",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "432122af37d8cd52fba1b294b11976e0d20df595"
"reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595",
"reference": "432122af37d8cd52fba1b294b11976e0d20df595",
"url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0",
"reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/contracts": "^1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@ -652,7 +738,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -679,25 +765,94 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:30:44+00:00"
"time": "2018-11-27T07:40:44+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.1.7",
"name": "symfony/contracts",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "552541dad078c85d9414b09c041ede488b456cd5"
"url": "https://github.com/symfony/contracts.git",
"reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5",
"reference": "552541dad078c85d9414b09c041ede488b456cd5",
"url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf",
"reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"require-dev": {
"psr/cache": "^1.0",
"psr/container": "^1.0"
},
"suggest": {
"psr/cache": "When using the Cache contracts",
"psr/container": "When using the Service contracts",
"symfony/cache-contracts-implementation": "",
"symfony/service-contracts-implementation": "",
"symfony/translation-contracts-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\": ""
},
"exclude-from-classmap": [
"**/Tests/"
]
},
"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": "A set of abstractions extracted out of the Symfony components",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"time": "2018-12-05T08:06:11+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "921f49c3158a276d27c0d770a5a347a3b718b328"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328",
"reference": "921f49c3158a276d27c0d770a5a347a3b718b328",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/contracts": "^1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
},
@ -715,7 +870,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -742,20 +897,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-10-10T13:52:42+00:00"
"time": "2018-12-01T08:52:38+00:00"
},
{
"name": "symfony/filesystem",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981"
"reference": "2f4c8b999b3b7cadb2a69390b01af70886753710"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2f4c8b999b3b7cadb2a69390b01af70886753710",
"reference": "2f4c8b999b3b7cadb2a69390b01af70886753710",
"shasum": ""
},
"require": {
@ -765,7 +920,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -792,20 +947,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-10-30T13:18:25+00:00"
"time": "2018-11-11T19:52:12+00:00"
},
{
"name": "symfony/finder",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d"
"reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d",
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d",
"url": "https://api.github.com/repos/symfony/finder/zipball/6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442",
"reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442",
"shasum": ""
},
"require": {
@ -841,7 +996,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2018-10-03T08:46:40+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -962,16 +1117,16 @@
},
{
"name": "symfony/process",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "3e83acef94d979b1de946599ef86b3a352abcdc9"
"reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/3e83acef94d979b1de946599ef86b3a352abcdc9",
"reference": "3e83acef94d979b1de946599ef86b3a352abcdc9",
"url": "https://api.github.com/repos/symfony/process/zipball/2b341009ccec76837a7f46f59641b431e4d4c2b0",
"reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0",
"shasum": ""
},
"require": {
@ -980,7 +1135,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -1007,20 +1162,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2018-10-14T20:48:13+00:00"
"time": "2018-11-20T16:22:05+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9"
"reference": "c41175c801e3edfda90f32e292619d10c27103d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9",
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9",
"url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7",
"reference": "c41175c801e3edfda90f32e292619d10c27103d7",
"shasum": ""
},
"require": {
@ -1039,7 +1194,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -1066,7 +1221,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:36:10+00:00"
"time": "2018-11-11T19:52:12+00:00"
}
],
"packages-dev": [
@ -1174,16 +1329,16 @@
},
{
"name": "codeception/base",
"version": "2.5.1",
"version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/Codeception/base.git",
"reference": "ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de"
"reference": "50aaf8bc032823018aed8d14114843b4a2c52a48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/base/zipball/ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de",
"reference": "ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de",
"url": "https://api.github.com/repos/Codeception/base/zipball/50aaf8bc032823018aed8d14114843b4a2c52a48",
"reference": "50aaf8bc032823018aed8d14114843b4a2c52a48",
"shasum": ""
},
"require": {
@ -1260,25 +1415,25 @@
"functional testing",
"unit testing"
],
"time": "2018-10-29T21:37:15+00:00"
"time": "2019-01-01T21:20:37+00:00"
},
{
"name": "codeception/phpunit-wrapper",
"version": "6.0.12",
"version": "6.0.13",
"source": {
"type": "git",
"url": "https://github.com/Codeception/phpunit-wrapper.git",
"reference": "de922c760dfddf8a33c4a066efcd0cd93576d957"
"reference": "d25db254173582bc27aa8c37cb04ce2481675bcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/de922c760dfddf8a33c4a066efcd0cd93576d957",
"reference": "de922c760dfddf8a33c4a066efcd0cd93576d957",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/d25db254173582bc27aa8c37cb04ce2481675bcd",
"reference": "d25db254173582bc27aa8c37cb04ce2481675bcd",
"shasum": ""
},
"require": {
"phpunit/php-code-coverage": ">=4.0.4 <6.0",
"phpunit/phpunit": ">=5.7.27 <7.0",
"phpunit/phpunit": ">=5.7.27 <6.5.13",
"sebastian/comparator": ">=1.2.4 <3.0",
"sebastian/diff": ">=1.4 <4.0"
},
@ -1306,7 +1461,7 @@
}
],
"description": "PHPUnit classes used by Codeception",
"time": "2018-09-12T20:19:47+00:00"
"time": "2019-01-01T15:39:52+00:00"
},
{
"name": "codeception/stub",
@ -1552,16 +1707,16 @@
},
{
"name": "g1a/composer-test-scenarios",
"version": "3.0.0",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/g1a/composer-test-scenarios.git",
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78"
"reference": "224531e20d13a07942a989a70759f726cd2df9a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/224531e20d13a07942a989a70759f726cd2df9a1",
"reference": "224531e20d13a07942a989a70759f726cd2df9a1",
"shasum": ""
},
"require": {
@ -1600,7 +1755,7 @@
}
],
"description": "Useful scripts for testing multiple sets of Composer dependencies.",
"time": "2018-11-22T05:10:20+00:00"
"time": "2018-11-27T05:58:39+00:00"
},
{
"name": "goaop/framework",
@ -1811,32 +1966,33 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
"reference": "9f83dded91781a01c63574e387eaa769be769115"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
"reference": "9f83dded91781a01c63574e387eaa769be769115",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
"dev-master": "1.5-dev"
}
},
"autoload": {
@ -1866,13 +2022,14 @@
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
"time": "2018-12-04T20:46:45+00:00"
},
{
"name": "jakubledl/dissect",
@ -2124,16 +2281,16 @@
},
{
"name": "pear/archive_tar",
"version": "1.4.3",
"version": "1.4.4",
"source": {
"type": "git",
"url": "https://github.com/pear/Archive_Tar.git",
"reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb"
"reference": "b005152d4ed8f23bcc93637611fa94f39ef5b904"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
"reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/b005152d4ed8f23bcc93637611fa94f39ef5b904",
"reference": "b005152d4ed8f23bcc93637611fa94f39ef5b904",
"shasum": ""
},
"require": {
@ -2144,8 +2301,8 @@
"phpunit/phpunit": "*"
},
"suggest": {
"ext-bz2": "bz2 compression support.",
"ext-xz": "lzma2 compression support.",
"ext-bz2": "Bz2 compression support.",
"ext-xz": "Lzma2 compression support.",
"ext-zlib": "Gzip compression support."
},
"type": "library",
@ -2180,13 +2337,13 @@
"email": "mrook@php.net"
}
],
"description": "Tar file management class",
"description": "Tar file management class with compression support (gzip, bzip2, lzma2)",
"homepage": "https://github.com/pear/Archive_Tar",
"keywords": [
"archive",
"tar"
],
"time": "2017-06-11T17:28:11+00:00"
"time": "2018-12-20T20:47:24+00:00"
},
{
"name": "pear/console_getopt",
@ -2237,20 +2394,20 @@
},
{
"name": "pear/pear-core-minimal",
"version": "v1.10.6",
"version": "v1.10.7",
"source": {
"type": "git",
"url": "https://github.com/pear/pear-core-minimal.git",
"reference": "052868b244d31f822796e7e9981f62557eb256d4"
"reference": "19a3e0fcd50492c4357372f623f55f1b144346da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/052868b244d31f822796e7e9981f62557eb256d4",
"reference": "052868b244d31f822796e7e9981f62557eb256d4",
"url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/19a3e0fcd50492c4357372f623f55f1b144346da",
"reference": "19a3e0fcd50492c4357372f623f55f1b144346da",
"shasum": ""
},
"require": {
"pear/console_getopt": "~1.3",
"pear/console_getopt": "~1.4",
"pear/pear_exception": "~1.0"
},
"replace": {
@ -2277,7 +2434,7 @@
}
],
"description": "Minimal set of PEAR core files to be used as composer dependency",
"time": "2018-08-22T19:28:09+00:00"
"time": "2018-12-05T20:03:52+00:00"
},
{
"name": "pear/pear_exception",
@ -3050,6 +3207,46 @@
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "~3.7.0",
"satooshi/php-coveralls": ">=1.0"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.1",
@ -3643,16 +3840,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd"
"reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/c55fe9257003b2d95c0211b3f6941e8dfd26dffd",
"reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/db7e59fec9c82d45e745eb500e6ede2d96f4a6e9",
"reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9",
"shasum": ""
},
"require": {
@ -3669,7 +3866,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3696,20 +3893,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T09:10:45+00:00"
"time": "2018-11-26T11:49:31+00:00"
},
{
"name": "symfony/config",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238"
"reference": "005d9a083d03f588677d15391a716b1ac9b887c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"url": "https://api.github.com/repos/symfony/config/zipball/005d9a083d03f588677d15391a716b1ac9b887c0",
"reference": "005d9a083d03f588677d15391a716b1ac9b887c0",
"shasum": ""
},
"require": {
@ -3732,7 +3929,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3759,20 +3956,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:09:42+00:00"
"time": "2018-11-30T22:21:14+00:00"
},
{
"name": "symfony/css-selector",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "d67de79a70a27d93c92c47f37ece958bf8de4d8a"
"reference": "aa9fa526ba1b2ec087ffdfb32753803d999fcfcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/d67de79a70a27d93c92c47f37ece958bf8de4d8a",
"reference": "d67de79a70a27d93c92c47f37ece958bf8de4d8a",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/aa9fa526ba1b2ec087ffdfb32753803d999fcfcd",
"reference": "aa9fa526ba1b2ec087ffdfb32753803d999fcfcd",
"shasum": ""
},
"require": {
@ -3781,7 +3978,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3812,20 +4009,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:36:10+00:00"
"time": "2018-11-11T19:52:12+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "80e60271bb288de2a2259662cff125cff4f93f95"
"reference": "7438a32108fdd555295f443605d6de2cce473159"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/80e60271bb288de2a2259662cff125cff4f93f95",
"reference": "80e60271bb288de2a2259662cff125cff4f93f95",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7438a32108fdd555295f443605d6de2cce473159",
"reference": "7438a32108fdd555295f443605d6de2cce473159",
"shasum": ""
},
"require": {
@ -3842,7 +4039,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3869,29 +4066,30 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:40:59+00:00"
"time": "2018-11-26T10:55:26+00:00"
},
{
"name": "symfony/stopwatch",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "5bfc064125b73ff81229e19381ce1c34d3416f4b"
"reference": "ec076716412274e51f8a7ea675d9515e5c311123"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/5bfc064125b73ff81229e19381ce1c34d3416f4b",
"reference": "5bfc064125b73ff81229e19381ce1c34d3416f4b",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/ec076716412274e51f8a7ea675d9515e5c311123",
"reference": "ec076716412274e51f8a7ea675d9515e5c311123",
"shasum": ""
},
"require": {
"php": "^7.1.3"
"php": "^7.1.3",
"symfony/contracts": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3918,24 +4116,25 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:40:59+00:00"
"time": "2018-11-11T19:52:12+00:00"
},
{
"name": "webmozart/assert",
"version": "1.3.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a"
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a",
"url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
"php": "^5.3.3 || ^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
@ -3968,7 +4167,7 @@
"check",
"validate"
],
"time": "2018-01-29T19:49:41+00:00"
"time": "2018-12-25T11:19:39+00:00"
}
],
"aliases": [],

View file

@ -1,5 +1,20 @@
# Changelog
### 1.4.0 - 1.4.3 1/2/2019
* BUGFIX: Back out 1.3.5, which contained breaking changes. Create a 1.x branch for continuation of compatible versions, and move breaking code to 2.x development (on master branch).
### 1.3.4 12/20/2018
* Allow for aborting completions or rollbacks by James Sansbury (#815)
* BUGFIX: Allow commands to declare '@param InputInterface' to satisfy code style checks
### 1.3.3 12/13/2018
* Add StdinHandler to the standard Robo DI container (#814)
* BUGFIX: Add test to ensure rollback order is in reverse by James Sansbury (#812)
* BUGFIX: Fix the main Robo script entrypoint to work as a phar. (#811)
### 1.3.2 11/21/2018
* Update to Composer Test Scenarios 3 (#803)

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2018 Codegyre Developers Team, Consolidation Team
Copyright (c) 2014-2019 Codegyre Developers Team, Consolidation Team
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
@ -22,9 +22,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
DEPENDENCY LICENSES:
Name Version License
consolidation/annotated-command 2.10.0 MIT
consolidation/annotated-command 2.11.0 MIT
consolidation/config 1.1.1 MIT
consolidation/log 1.0.6 MIT
consolidation/log 1.1.1 MIT
consolidation/output-formatters 3.4.0 MIT
consolidation/self-update 1.1.5 MIT
container-interop/container-interop 1.2.0 MIT
@ -34,11 +34,11 @@ grasmash/yaml-expander 1.4.0 MIT
league/container 2.4.1 MIT
psr/container 1.0.0 MIT
psr/log 1.1.0 MIT
symfony/console v4.1.7 MIT
symfony/event-dispatcher v4.1.7 MIT
symfony/filesystem v4.1.7 MIT
symfony/finder v3.4.18 MIT
symfony/console v4.2.1 MIT
symfony/event-dispatcher v4.2.1 MIT
symfony/filesystem v4.2.1 MIT
symfony/finder v3.4.20 MIT
symfony/polyfill-ctype v1.10.0 MIT
symfony/polyfill-mbstring v1.10.0 MIT
symfony/process v4.1.7 MIT
symfony/yaml v4.1.7 MIT
symfony/process v4.2.1 MIT
symfony/yaml v4.2.1 MIT

View file

@ -1,8 +1,10 @@
# RoboTask
_This is the 1.x (stable) branch of the Robo task runner. Development for Robo 2.x (future) is happening on the [master](https://github.com/consolidation/Robo/tree/master) branch._
**Modern and simple PHP task runner** inspired by Gulp and Rake aimed to automate common tasks:
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/consolidation-org/Robo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/consolidation/Robo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Latest Stable Version](https://poser.pugx.org/consolidation/robo/v/stable.png)](https://packagist.org/packages/consolidation/robo)
[![Latest Unstable Version](https://poser.pugx.org/consolidation/robo/v/unstable.png)](https://packagist.org/packages/consolidation/robo)
[![Total Downloads](https://poser.pugx.org/consolidation/robo/downloads.png)](https://packagist.org/packages/consolidation/robo)
@ -56,7 +58,7 @@ All protected methods in traits that start with `task` prefix are tasks and can
## Examples
The best way to learn Robo by example is to take a look into [its own RoboFile](https://github.com/consolidation-org/Robo/blob/master/RoboFile.php)
The best way to learn Robo by example is to take a look into [its own RoboFile](https://github.com/consolidation/Robo/blob/master/RoboFile.php)
or [RoboFile of Codeception project](https://github.com/Codeception/Codeception/blob/2.4/RoboFile.php). There are also some basic example commands in examples/RoboFile.php.
Here are some snippets from them:

View file

@ -101,7 +101,7 @@ class RoboFile extends \Robo\Tasks
$this->taskGitStack()
->tag($version)
->push('origin master --tags')
->push('origin 1.x --tags')
->run();
if ($stable) {
@ -320,7 +320,7 @@ class RoboFile extends \Robo\Tasks
return $this->collectionBuilder()
->taskGitStack()
->checkout('site')
->merge('master')
->merge('1.x')
->completion($this->taskGitStack()->checkout($current_branch))
->taskFilesystemStack()
->copy('CHANGELOG.md', 'docs/changelog.md')
@ -467,7 +467,7 @@ class RoboFile extends \Robo\Tasks
->add('robotheme/robo.phar')
->commit('Update robo.phar to ' . \Robo\Robo::VERSION)
->push('origin site')
->checkout('master')
->checkout('1.x')
->run();
}
}

View file

@ -25,7 +25,7 @@
"league/container": "^2.2",
"consolidation/log": "~1",
"consolidation/config": "^1.0.10",
"consolidation/annotated-command": "^2.8.2",
"consolidation/annotated-command": "^2.10.2",
"consolidation/output-formatters": "^3.1.13",
"consolidation/self-update": "^1",
"grasmash/yaml-expander": "^1.3",
@ -103,7 +103,7 @@
}
},
"branch-alias": {
"dev-master": "1.x-dev"
"dev-master": "2.x-dev"
}
},
"suggest": {

View file

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "07b63861fb5a551c082ad59662288f07",
"content-hash": "9c5c482a5c2448a1c439a441f3da2529",
"packages": [
{
"name": "consolidation/annotated-command",
"version": "2.10.0",
"version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/consolidation/annotated-command.git",
"reference": "8e7d1a05230dc1159c751809e98b74f2b7f71873"
"reference": "edea407f57104ed518cc3c3b47d5b84403ee267a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/8e7d1a05230dc1159c751809e98b74f2b7f71873",
"reference": "8e7d1a05230dc1159c751809e98b74f2b7f71873",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/edea407f57104ed518cc3c3b47d5b84403ee267a",
"reference": "edea407f57104ed518cc3c3b47d5b84403ee267a",
"shasum": ""
},
"require": {
@ -29,13 +29,57 @@
"symfony/finder": "^2.5|^3|^4"
},
"require-dev": {
"g1a/composer-test-scenarios": "^2",
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"phpunit/phpunit": "^6",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "^2.7"
},
"type": "library",
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
},
"scenario-options": {
"create-lockfile": "false"
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "2.x-dev"
}
@ -56,7 +100,7 @@
}
],
"description": "Initialize Symfony Console commands from annotated command class methods.",
"time": "2018-11-15T01:46:18+00:00"
"time": "2018-12-29T04:43:17+00:00"
},
{
"name": "consolidation/config",
@ -114,31 +158,72 @@
},
{
"name": "consolidation/log",
"version": "1.0.6",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/consolidation/log.git",
"reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395"
"reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/log/zipball/dfd8189a771fe047bf3cd669111b2de5f1c79395",
"reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395",
"url": "https://api.github.com/repos/consolidation/log/zipball/b2e887325ee90abc96b0a8b7b474cd9e7c896e3a",
"reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"psr/log": "~1.0",
"php": ">=5.4.5",
"psr/log": "^1.0",
"symfony/console": "^2.8|^3|^4"
},
"require-dev": {
"g1a/composer-test-scenarios": "^1",
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "^2",
"squizlabs/php_codesniffer": "2.*"
"g1a/composer-test-scenarios": "^3",
"php-coveralls/php-coveralls": "^1",
"phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^2"
},
"type": "library",
"extra": {
"scenarios": {
"symfony4": {
"require": {
"symfony/console": "^4.0"
},
"config": {
"platform": {
"php": "7.1.3"
}
}
},
"symfony2": {
"require": {
"symfony/console": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
},
"phpunit4": {
"require-dev": {
"phpunit/phpunit": "^4.8.36"
},
"remove": [
"php-coveralls/php-coveralls"
],
"config": {
"platform": {
"php": "5.4.8"
}
}
}
},
"branch-alias": {
"dev-master": "1.x-dev"
}
@ -159,7 +244,7 @@
}
],
"description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
"time": "2018-05-25T18:14:39+00:00"
"time": "2019-01-01T17:30:51+00:00"
},
{
"name": "consolidation/output-formatters",
@ -615,16 +700,16 @@
},
{
"name": "symfony/console",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "1d228fb4602047d7b26a0554e0d3efd567da5803"
"reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/1d228fb4602047d7b26a0554e0d3efd567da5803",
"reference": "1d228fb4602047d7b26a0554e0d3efd567da5803",
"url": "https://api.github.com/repos/symfony/console/zipball/8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb",
"reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb",
"shasum": ""
},
"require": {
@ -680,20 +765,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-10-30T16:50:50+00:00"
"time": "2018-11-26T12:48:07+00:00"
},
{
"name": "symfony/debug",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "fe9793af008b651c5441bdeab21ede8172dab097"
"reference": "a2233f555ddf55e5600f386fba7781cea1cb82d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/fe9793af008b651c5441bdeab21ede8172dab097",
"reference": "fe9793af008b651c5441bdeab21ede8172dab097",
"url": "https://api.github.com/repos/symfony/debug/zipball/a2233f555ddf55e5600f386fba7781cea1cb82d3",
"reference": "a2233f555ddf55e5600f386fba7781cea1cb82d3",
"shasum": ""
},
"require": {
@ -736,20 +821,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:06:03+00:00"
"time": "2018-11-27T12:43:10+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14"
"reference": "cc35e84adbb15c26ae6868e1efbf705a917be6b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14",
"reference": "db9e829c8f34c3d35cf37fcd4cdb4293bc4a2f14",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/cc35e84adbb15c26ae6868e1efbf705a917be6b5",
"reference": "cc35e84adbb15c26ae6868e1efbf705a917be6b5",
"shasum": ""
},
"require": {
@ -799,20 +884,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-10-30T16:50:50+00:00"
"time": "2018-11-30T18:07:24+00:00"
},
{
"name": "symfony/filesystem",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "d69930fc337d767607267d57c20a7403d0a822a4"
"reference": "b49b1ca166bd109900e6a1683d9bb1115727ef2d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d69930fc337d767607267d57c20a7403d0a822a4",
"reference": "d69930fc337d767607267d57c20a7403d0a822a4",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b49b1ca166bd109900e6a1683d9bb1115727ef2d",
"reference": "b49b1ca166bd109900e6a1683d9bb1115727ef2d",
"shasum": ""
},
"require": {
@ -849,20 +934,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:28:39+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/finder",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d"
"reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d",
"reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d",
"url": "https://api.github.com/repos/symfony/finder/zipball/6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442",
"reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442",
"shasum": ""
},
"require": {
@ -898,7 +983,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2018-10-03T08:46:40+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -1019,16 +1104,16 @@
},
{
"name": "symfony/process",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "35c2914a9f50519bd207164c353ae4d59182c2cb"
"reference": "abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/35c2914a9f50519bd207164c353ae4d59182c2cb",
"reference": "35c2914a9f50519bd207164c353ae4d59182c2cb",
"url": "https://api.github.com/repos/symfony/process/zipball/abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2",
"reference": "abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2",
"shasum": ""
},
"require": {
@ -1064,20 +1149,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2018-10-14T17:33:21+00:00"
"time": "2018-11-20T16:10:26+00:00"
},
{
"name": "symfony/yaml",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f"
"reference": "291e13d808bec481eab83f301f7bff3e699ef603"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f",
"reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f",
"url": "https://api.github.com/repos/symfony/yaml/zipball/291e13d808bec481eab83f301f7bff3e699ef603",
"reference": "291e13d808bec481eab83f301f7bff3e699ef603",
"shasum": ""
},
"require": {
@ -1123,7 +1208,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:33:53+00:00"
"time": "2018-11-11T19:48:54+00:00"
}
],
"packages-dev": [
@ -1231,16 +1316,16 @@
},
{
"name": "codeception/base",
"version": "2.5.1",
"version": "2.5.2",
"source": {
"type": "git",
"url": "https://github.com/Codeception/base.git",
"reference": "ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de"
"reference": "50aaf8bc032823018aed8d14114843b4a2c52a48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/base/zipball/ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de",
"reference": "ec6b7bd4d78c1adba3dbd5c3c52fc683e8aef6de",
"url": "https://api.github.com/repos/Codeception/base/zipball/50aaf8bc032823018aed8d14114843b4a2c52a48",
"reference": "50aaf8bc032823018aed8d14114843b4a2c52a48",
"shasum": ""
},
"require": {
@ -1317,25 +1402,25 @@
"functional testing",
"unit testing"
],
"time": "2018-10-29T21:37:15+00:00"
"time": "2019-01-01T21:20:37+00:00"
},
{
"name": "codeception/phpunit-wrapper",
"version": "6.0.12",
"version": "6.0.13",
"source": {
"type": "git",
"url": "https://github.com/Codeception/phpunit-wrapper.git",
"reference": "de922c760dfddf8a33c4a066efcd0cd93576d957"
"reference": "d25db254173582bc27aa8c37cb04ce2481675bcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/de922c760dfddf8a33c4a066efcd0cd93576d957",
"reference": "de922c760dfddf8a33c4a066efcd0cd93576d957",
"url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/d25db254173582bc27aa8c37cb04ce2481675bcd",
"reference": "d25db254173582bc27aa8c37cb04ce2481675bcd",
"shasum": ""
},
"require": {
"phpunit/php-code-coverage": ">=4.0.4 <6.0",
"phpunit/phpunit": ">=5.7.27 <7.0",
"phpunit/phpunit": ">=5.7.27 <6.5.13",
"sebastian/comparator": ">=1.2.4 <3.0",
"sebastian/diff": ">=1.4 <4.0"
},
@ -1363,7 +1448,7 @@
}
],
"description": "PHPUnit classes used by Codeception",
"time": "2018-09-12T20:19:47+00:00"
"time": "2019-01-01T15:39:52+00:00"
},
{
"name": "codeception/stub",
@ -1609,16 +1694,16 @@
},
{
"name": "g1a/composer-test-scenarios",
"version": "3.0.0",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/g1a/composer-test-scenarios.git",
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78"
"reference": "224531e20d13a07942a989a70759f726cd2df9a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"reference": "2a7156f1572898888ea50ad1d48a6b4d3f9fbf78",
"url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/224531e20d13a07942a989a70759f726cd2df9a1",
"reference": "224531e20d13a07942a989a70759f726cd2df9a1",
"shasum": ""
},
"require": {
@ -1657,7 +1742,7 @@
}
],
"description": "Useful scripts for testing multiple sets of Composer dependencies.",
"time": "2018-11-22T05:10:20+00:00"
"time": "2018-11-27T05:58:39+00:00"
},
{
"name": "goaop/framework",
@ -1868,32 +1953,33 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
"reference": "9f83dded91781a01c63574e387eaa769be769115"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
"reference": "9f83dded91781a01c63574e387eaa769be769115",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
"dev-master": "1.5-dev"
}
},
"autoload": {
@ -1923,13 +2009,14 @@
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
"time": "2018-12-04T20:46:45+00:00"
},
{
"name": "jakubledl/dissect",
@ -2178,16 +2265,16 @@
},
{
"name": "pear/archive_tar",
"version": "1.4.3",
"version": "1.4.4",
"source": {
"type": "git",
"url": "https://github.com/pear/Archive_Tar.git",
"reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb"
"reference": "b005152d4ed8f23bcc93637611fa94f39ef5b904"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
"reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/b005152d4ed8f23bcc93637611fa94f39ef5b904",
"reference": "b005152d4ed8f23bcc93637611fa94f39ef5b904",
"shasum": ""
},
"require": {
@ -2198,8 +2285,8 @@
"phpunit/phpunit": "*"
},
"suggest": {
"ext-bz2": "bz2 compression support.",
"ext-xz": "lzma2 compression support.",
"ext-bz2": "Bz2 compression support.",
"ext-xz": "Lzma2 compression support.",
"ext-zlib": "Gzip compression support."
},
"type": "library",
@ -2234,13 +2321,13 @@
"email": "mrook@php.net"
}
],
"description": "Tar file management class",
"description": "Tar file management class with compression support (gzip, bzip2, lzma2)",
"homepage": "https://github.com/pear/Archive_Tar",
"keywords": [
"archive",
"tar"
],
"time": "2017-06-11T17:28:11+00:00"
"time": "2018-12-20T20:47:24+00:00"
},
{
"name": "pear/console_getopt",
@ -2291,20 +2378,20 @@
},
{
"name": "pear/pear-core-minimal",
"version": "v1.10.6",
"version": "v1.10.7",
"source": {
"type": "git",
"url": "https://github.com/pear/pear-core-minimal.git",
"reference": "052868b244d31f822796e7e9981f62557eb256d4"
"reference": "19a3e0fcd50492c4357372f623f55f1b144346da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/052868b244d31f822796e7e9981f62557eb256d4",
"reference": "052868b244d31f822796e7e9981f62557eb256d4",
"url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/19a3e0fcd50492c4357372f623f55f1b144346da",
"reference": "19a3e0fcd50492c4357372f623f55f1b144346da",
"shasum": ""
},
"require": {
"pear/console_getopt": "~1.3",
"pear/console_getopt": "~1.4",
"pear/pear_exception": "~1.0"
},
"replace": {
@ -2331,7 +2418,7 @@
}
],
"description": "Minimal set of PEAR core files to be used as composer dependency",
"time": "2018-08-22T19:28:09+00:00"
"time": "2018-12-05T20:03:52+00:00"
},
{
"name": "pear/pear_exception",
@ -3098,6 +3185,46 @@
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "~3.7.0",
"satooshi/php-coveralls": ">=1.0"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.1",
@ -3691,16 +3818,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "f6668d1a6182d5a8dec65a1c863a4c1d963816c0"
"reference": "49465af22d94c8d427c51facbf8137eb285b9726"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/f6668d1a6182d5a8dec65a1c863a4c1d963816c0",
"reference": "f6668d1a6182d5a8dec65a1c863a4c1d963816c0",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/49465af22d94c8d427c51facbf8137eb285b9726",
"reference": "49465af22d94c8d427c51facbf8137eb285b9726",
"shasum": ""
},
"require": {
@ -3744,20 +3871,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T09:06:28+00:00"
"time": "2018-11-26T10:17:44+00:00"
},
{
"name": "symfony/config",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "99b2fa8acc244e656cdf324ff419fbe6fd300a4d"
"reference": "8a660daeb65dedbe0b099529f65e61866c055081"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/99b2fa8acc244e656cdf324ff419fbe6fd300a4d",
"reference": "99b2fa8acc244e656cdf324ff419fbe6fd300a4d",
"url": "https://api.github.com/repos/symfony/config/zipball/8a660daeb65dedbe0b099529f65e61866c055081",
"reference": "8a660daeb65dedbe0b099529f65e61866c055081",
"shasum": ""
},
"require": {
@ -3808,20 +3935,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:06:03+00:00"
"time": "2018-11-26T10:17:44+00:00"
},
{
"name": "symfony/css-selector",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb"
"reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/345b9a48595d1ab9630db791dbc3e721bf0233e8",
"reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8",
"shasum": ""
},
"require": {
@ -3861,20 +3988,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:33:53+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "c705bee03ade5b47c087807dd9ffaaec8dda2722"
"reference": "b6e94248eb4f8602a5825301b0bea1eb8cc82cfa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c705bee03ade5b47c087807dd9ffaaec8dda2722",
"reference": "c705bee03ade5b47c087807dd9ffaaec8dda2722",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b6e94248eb4f8602a5825301b0bea1eb8cc82cfa",
"reference": "b6e94248eb4f8602a5825301b0bea1eb8cc82cfa",
"shasum": ""
},
"require": {
@ -3918,20 +4045,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:28:39+00:00"
"time": "2018-11-26T10:17:44+00:00"
},
{
"name": "symfony/stopwatch",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "05e52a39de52ba690aebaed462b2bc8a9649f0a4"
"reference": "0f43969ab2718de55c1c1158dce046668079788d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/05e52a39de52ba690aebaed462b2bc8a9649f0a4",
"reference": "05e52a39de52ba690aebaed462b2bc8a9649f0a4",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/0f43969ab2718de55c1c1158dce046668079788d",
"reference": "0f43969ab2718de55c1c1158dce046668079788d",
"shasum": ""
},
"require": {
@ -3967,24 +4094,25 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:28:39+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "webmozart/assert",
"version": "1.3.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a"
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a",
"url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
"php": "^5.3.3 || ^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
@ -4017,7 +4145,7 @@
"check",
"validate"
],
"time": "2018-01-29T19:49:41+00:00"
"time": "2018-12-25T11:19:39+00:00"
}
],
"aliases": [],

View file

@ -1,21 +1,41 @@
#!/usr/bin/env php
<?php
/**
* if we're running from phar load the phar autoload,
* If we're running from phar load the phar autoload,
* else let the script 'robo' search for the autoloader.
* If we cannot find a vendor/autoload.php file, then
* we will go ahead and try the phar.
*/
$pharPath = \Phar::running(true);
if ($pharPath) {
$autoloaderPath = "$pharPath/vendor/autoload.php";
} else {
if (file_exists(__DIR__.'/vendor/autoload.php')) {
$autoloaderPath = __DIR__.'/vendor/autoload.php';
} elseif (file_exists(__DIR__.'/../../autoload.php')) {
$autoloaderPath = __DIR__ . '/../../autoload.php';
// Hack: \Phar::running() cannot be used reliably here to determine
// if we are running as a phar or not (works when phar is built with
// box, but does not work when phar is built with the Robo phar task.)
// We will use __FILE__ to determine our phar path; however, we cannot
// distinguish whether a __FILE__ of "/path/robo" is this file, or a
// 'robo.phar' that has been renamed to 'robo'. We will use the file
// size to differentiate.
// Recommendation: Use box to build your phar. See https://github.com/g1a/starter
$isPhar = (filesize(__FILE__) > 500000);
// Non-phar autoloader paths
$candidates = [
__DIR__.'/vendor/autoload.php',
__DIR__.'/../../autoload.php',
];
// Use our phar alias path
if ($isPhar) {
array_unshift($candidates, 'phar://robo.phar/vendor/autoload.php');
}
$autoloaderPath = false;
foreach ($candidates as $candidate) {
if (file_exists($candidate)) {
$autoloaderPath = $candidate;
break;
}
}
if (!$autoloaderPath) {
die("Could not find autoloader. Run 'composer install'.");
}
$classLoader = require $autoloaderPath;
$configFilePath = getenv('ROBO_CONFIG') ?: getenv('HOME') . '/.robo/robo.yml';
$runner = new \Robo\Runner();

View file

@ -1,6 +1,7 @@
<?php
namespace Robo\Collection;
use Robo\Exception\AbortTasksException;
use Robo\Result;
use Robo\State\Data;
use Psr\Log\LogLevel;
@ -254,6 +255,8 @@ class Collection extends BaseTask implements CollectionInterface, CommandInterfa
$message = $result->getMessage();
$data = $result->getData();
$data['exitcode'] = $result->getExitCode();
} catch (AbortTasksException $abortTasksException) {
throw $abortTasksException;
} catch (\Exception $e) {
$message = $e->getMessage();
}
@ -419,7 +422,7 @@ class Collection extends BaseTask implements CollectionInterface, CommandInterfa
return $this->parentCollection->registerRollback($rollbackTask);
}
if ($rollbackTask) {
$this->rollbackStack[] = $rollbackTask;
array_unshift($this->rollbackStack, $rollbackTask);
}
}
@ -735,6 +738,10 @@ class Collection extends BaseTask implements CollectionInterface, CommandInterfa
/**
* Run all of the tasks in a provided list, ignoring failures.
*
* You may force a failure by throwing a ForcedException in your rollback or
* completion task or callback.
*
* This is used to roll back or complete.
*
* @param TaskInterface[] $taskList
@ -744,6 +751,12 @@ class Collection extends BaseTask implements CollectionInterface, CommandInterfa
foreach ($taskList as $task) {
try {
$this->runSubtask($task);
} catch (AbortTasksException $abortTasksException) {
// If there's a forced exception, end the loop of tasks.
if ($message = $abortTasksException->getMessage()) {
$this->logger()->notice($message);
}
break;
} catch (\Exception $e) {
// Ignore rollback failures.
}

View file

@ -0,0 +1,13 @@
<?php
namespace Robo\Exception;
/**
* By default, rollbacks and completions tasks or callbacks continue even if
* errors occur. If you would like to explicitly cancel or abort the rollback or
* completion, you may throw this exception to abort the subsequent tasks in the
* rollback or completion task list.
*/
class AbortTasksException extends \Exception
{
}

View file

@ -20,7 +20,7 @@ use Symfony\Component\Process\Process;
class Robo
{
const APPLICATION_NAME = 'Robo';
const VERSION = '1.3.2';
const VERSION = '1.4.3';
/**
* The currently active container object, or NULL if not initialized yet.
@ -250,6 +250,7 @@ class Robo
}
]
);
$container->share('stdinHandler', \Consolidation\AnnotatedCommand\Input\StdinHandler::class);
$container->share('commandFactory', \Consolidation\AnnotatedCommand\AnnotatedCommandFactory::class)
->withMethodCall('setCommandProcessor', ['commandProcessor']);
$container->share('relativeNamespaceDiscovery', \Robo\ClassDiscovery\RelativeNamespaceDiscovery::class)
@ -307,6 +308,8 @@ class Robo
->invokeMethod('setHookManager', ['hookManager']);
$container->inflector(\Robo\Contract\VerbosityThresholdInterface::class)
->invokeMethod('setOutputAdapter', ['outputAdapter']);
$container->inflector(\Consolidation\AnnotatedCommand\Input\StdinAwareInterface::class)
->invokeMethod('setStdinHandler', ['stdinHandler']);
}
/**

9
vendor/guzzlehttp/psr7/.editorconfig vendored Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

View file

@ -1,32 +1,82 @@
# CHANGELOG
# Change Log
## 1.4.2 - 2017-03-20
* Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.5.2] - 2018-12-04
### Fixed
- Check body size when getting the message summary
## [1.5.1] - 2018-12-04
### Fixed
- Get the summary of a body only if it is readable
## [1.5.0] - 2018-12-03
### Added
- Response first-line to response string exception (fixes #145)
- A test for #129 behavior
- `get_message_body_summary` function in order to get the message summary
- `3gp` and `mkv` mime types
### Changed
- Clarify exception message when stream is detached
### Deprecated
- Deprecated parsing folded header lines as per RFC 7230
### Fixed
- Fix `AppendStream::detach` to not close streams
- `InflateStream` preserves `isSeekable` attribute of the underlying stream
- `ServerRequest::getUriFromGlobals` to support URLs in query parameters
Several other fixes and improvements.
## [1.4.2] - 2017-03-20
### Fixed
- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing
calls to `trigger_error` when deprecated methods are invoked.
## 1.4.1 - 2017-02-27
* Reverted BC break by reintroducing behavior to automagically fix a URI with a
## [1.4.1] - 2017-02-27
### Added
- Rriggering of silenced deprecation warnings.
### Fixed
- Reverted BC break by reintroducing behavior to automagically fix a URI with a
relative path and an authority by adding a leading slash to the path. It's only
deprecated now.
* Added triggering of silenced deprecation warnings.
## 1.4.0 - 2017-02-21
* Fix `Stream::read` when length parameter <= 0.
* `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
* Fix `ServerRequest::getUriFromGlobals` when `Host` header contains port.
* Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
* Allow `parse_response` to parse a response without delimiting space and reason.
* Ensure each URI modification results in a valid URI according to PSR-7 discussions.
Invalid modifications will throw an exception instead of returning a wrong URI or
doing some magic.
- `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
because the path of a URI with an authority must start with a slash "/" or be empty
- `(new Uri())->withScheme('http')` will return `'http://localhost'`
* Fix compatibility of URIs with `file` scheme and empty host.
* Added common URI utility methods based on RFC 3986 (see documentation in the readme):
## [1.4.0] - 2017-02-21
### Added
- Added common URI utility methods based on RFC 3986 (see documentation in the readme):
- `Uri::isDefaultPort`
- `Uri::isAbsolute`
- `Uri::isNetworkPathReference`
@ -37,69 +87,117 @@
- `UriNormalizer::normalize`
- `UriNormalizer::isEquivalent`
- `UriResolver::relativize`
* Deprecated `Uri::resolve` in favor of `UriResolver::resolve`
* Deprecated `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
## 1.3.1 - 2016-06-25
### Changed
* Fix `Uri::__toString` for network path references, e.g. `//example.org`.
* Fix missing lowercase normalization for host.
* Fix handling of URI components in case they are `'0'` in a lot of places,
- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.
- Allow `parse_response` to parse a response without delimiting space and reason.
- Ensure each URI modification results in a valid URI according to PSR-7 discussions.
Invalid modifications will throw an exception instead of returning a wrong URI or
doing some magic.
- `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception
because the path of a URI with an authority must start with a slash "/" or be empty
- `(new Uri())->withScheme('http')` will return `'http://localhost'`
### Deprecated
- `Uri::resolve` in favor of `UriResolver::resolve`
- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`
### Fixed
- `Stream::read` when length parameter <= 0.
- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.
- `ServerRequest::getUriFromGlobals` when `Host` header contains port.
- Compatibility of URIs with `file` scheme and empty host.
## [1.3.1] - 2016-06-25
### Fixed
- `Uri::__toString` for network path references, e.g. `//example.org`.
- Missing lowercase normalization for host.
- Handling of URI components in case they are `'0'` in a lot of places,
e.g. as a user info password.
* Fix `Uri::withAddedHeader` to correctly merge headers with different case.
* Fix trimming of header values in `Uri::withAddedHeader`. Header values may
- `Uri::withAddedHeader` to correctly merge headers with different case.
- Trimming of header values in `Uri::withAddedHeader`. Header values may
be surrounded by whitespace which should be ignored according to RFC 7230
Section 3.2.4. This does not apply to header names.
* Fix `Uri::withAddedHeader` with an array of header values.
* Fix `Uri::resolve` when base path has no slash and handling of fragment.
* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the
- `Uri::withAddedHeader` with an array of header values.
- `Uri::resolve` when base path has no slash and handling of fragment.
- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the
key/value both in encoded as well as decoded form to those methods. This is
consistent with withPath, withQuery etc.
* Fix `ServerRequest::withoutAttribute` when attribute value is null.
- `ServerRequest::withoutAttribute` when attribute value is null.
## 1.3.0 - 2016-04-13
* Added remaining interfaces needed for full PSR7 compatibility
## [1.3.0] - 2016-04-13
### Added
- Remaining interfaces needed for full PSR7 compatibility
(ServerRequestInterface, UploadedFileInterface, etc.).
* Added support for stream_for from scalars.
* Can now extend Uri.
* Fixed a bug in validating request methods by making it more permissive.
- Support for stream_for from scalars.
## 1.2.3 - 2016-02-18
### Changed
* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
- Can now extend Uri.
### Fixed
- A bug in validating request methods by making it more permissive.
## [1.2.3] - 2016-02-18
### Fixed
- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote
streams, which can sometimes return fewer bytes than requested with `fread`.
* Fixed handling of gzipped responses with FNAME headers.
- Handling of gzipped responses with FNAME headers.
## 1.2.2 - 2016-01-22
* Added support for URIs without any authority.
* Added support for HTTP 451 'Unavailable For Legal Reasons.'
* Added support for using '0' as a filename.
* Added support for including non-standard ports in Host headers.
## [1.2.2] - 2016-01-22
## 1.2.1 - 2015-11-02
### Added
* Now supporting negative offsets when seeking to SEEK_END.
- Support for URIs without any authority.
- Support for HTTP 451 'Unavailable For Legal Reasons.'
- Support for using '0' as a filename.
- Support for including non-standard ports in Host headers.
## 1.2.0 - 2015-08-15
* Body as `"0"` is now properly added to a response.
* Now allowing forward seeking in CachingStream.
* Now properly parsing HTTP requests that contain proxy targets in
## [1.2.1] - 2015-11-02
### Changes
- Now supporting negative offsets when seeking to SEEK_END.
## [1.2.0] - 2015-08-15
### Changed
- Body as `"0"` is now properly added to a response.
- Now allowing forward seeking in CachingStream.
- Now properly parsing HTTP requests that contain proxy targets in
`parse_request`.
* functions.php is now conditionally required.
* user-info is no longer dropped when resolving URIs.
- functions.php is now conditionally required.
- user-info is no longer dropped when resolving URIs.
## 1.1.0 - 2015-06-24
* URIs can now be relative.
* `multipart/form-data` headers are now overridden case-insensitively.
* URI paths no longer encode the following characters because they are allowed
## [1.1.0] - 2015-06-24
### Changed
- URIs can now be relative.
- `multipart/form-data` headers are now overridden case-insensitively.
- URI paths no longer encode the following characters because they are allowed
in URIs: "(", ")", "*", "!", "'"
* A port is no longer added to a URI when the scheme is missing and no port is
- A port is no longer added to a URI when the scheme is missing and no port is
present.
## 1.0.0 - 2015-05-19
Initial release.
@ -108,3 +206,20 @@ Currently unsupported:
- `Psr\Http\Message\ServerRequestInterface`
- `Psr\Http\Message\UploadedFileInterface`
[Unreleased]: https://github.com/guzzle/psr7/compare/1.5.2...HEAD
[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2
[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1
[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0
[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2
[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1
[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0
[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1
[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0
[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3
[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2
[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1
[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0

View file

@ -372,7 +372,7 @@ This method accepts the following `$resource` types:
$stream = GuzzleHttp\Psr7\stream_for('foo');
$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
$generator function ($bytes) {
$generator = function ($bytes) {
for ($i = 0; $i < $bytes; $i++) {
yield ' ';
}
@ -606,6 +606,12 @@ Creates a new URI with a specific query string value. Any existing query string
provided key are removed and replaced with the given key value pair. A value of null will set the query string
key without a value, e.g. "key" instead of "key=value".
### `GuzzleHttp\Psr7\Uri::withQueryValues`
`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`
Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an
associative array of key => value.
### `GuzzleHttp\Psr7\Uri::withoutQueryValue`

View file

@ -2,7 +2,7 @@
"name": "guzzlehttp/psr7",
"type": "library",
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": ["request", "response", "message", "stream", "http", "uri", "url"],
"keywords": ["request", "response", "message", "stream", "http", "uri", "url", "psr-7"],
"license": "MIT",
"authors": [
{
@ -17,10 +17,11 @@
],
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"provide": {
"psr/http-message-implementation": "1.0"
@ -31,9 +32,14 @@
},
"files": ["src/functions_include.php"]
},
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Tests\\Psr7\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
"dev-master": "1.5-dev"
}
}
}

View file

@ -16,7 +16,6 @@ class AppendStream implements StreamInterface
private $seekable = true;
private $current = 0;
private $pos = 0;
private $detached = false;
/**
* @param StreamInterface[] $streams Streams to decorate. Each stream must
@ -73,6 +72,7 @@ class AppendStream implements StreamInterface
public function close()
{
$this->pos = $this->current = 0;
$this->seekable = true;
foreach ($this->streams as $stream) {
$stream->close();
@ -82,14 +82,22 @@ class AppendStream implements StreamInterface
}
/**
* Detaches each attached stream
* Detaches each attached stream.
*
* Returns null as it's not clear which underlying stream resource to return.
*
* {@inheritdoc}
*/
public function detach()
{
$this->close();
$this->detached = true;
$this->pos = $this->current = 0;
$this->seekable = true;
foreach ($this->streams as $stream) {
$stream->detach();
}
$this->streams = [];
}
public function tell()

View file

@ -52,6 +52,15 @@ class FnStream implements StreamInterface
}
}
/**
* An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
* @throws \LogicException
*/
public function __wakeup()
{
throw new \LogicException('FnStream should never be unserialized');
}
/**
* Adds custom functionality to an underlying stream by intercepting
* specific method calls.

View file

@ -27,7 +27,7 @@ class InflateStream implements StreamInterface
$stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength);
$resource = StreamWrapper::getResource($stream);
stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
$this->stream = new Stream($resource);
$this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource));
}
/**

View file

@ -45,7 +45,7 @@ class Request implements RequestInterface
$this->setHeaders($headers);
$this->protocol = $version;
if (!$this->hasHeader('Host')) {
if (!isset($this->headerNames['host'])) {
$this->updateHostFromUri();
}
@ -110,7 +110,7 @@ class Request implements RequestInterface
$new = clone $this;
$new->uri = $uri;
if (!$preserveHost) {
if (!$preserveHost || !isset($this->headerNames['host'])) {
$new->updateHostFromUri();
}

View file

@ -93,6 +93,10 @@ class Response implements ResponseInterface
$version = '1.1',
$reason = null
) {
if (filter_var($status, FILTER_VALIDATE_INT) === false) {
throw new \InvalidArgumentException('Status code must be an integer value.');
}
$this->statusCode = (int) $status;
if ($body !== '' && $body !== null) {

18
vendor/guzzlehttp/psr7/src/Rfc7230.php vendored Normal file
View file

@ -0,0 +1,18 @@
<?php
namespace GuzzleHttp\Psr7;
final class Rfc7230
{
/**
* Header related regular expressions (copied from amphp/http package)
* (Note: once we require PHP 7.x we could just depend on the upstream package)
*
* Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons.
*
* @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15
* @license https://github.com/amphp/http/blob/v1.0.1/LICENSE
*/
const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m";
const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
}

View file

@ -166,7 +166,7 @@ class ServerRequest extends Request implements ServerRequestInterface
public static function fromGlobals()
{
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
$headers = function_exists('getallheaders') ? getallheaders() : [];
$headers = getallheaders();
$uri = self::getUriFromGlobals();
$body = new LazyOpenStream('php://input', 'r+');
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
@ -180,23 +180,41 @@ class ServerRequest extends Request implements ServerRequestInterface
->withUploadedFiles(self::normalizeFiles($_FILES));
}
private static function extractHostAndPortFromAuthority($authority)
{
$uri = 'http://'.$authority;
$parts = parse_url($uri);
if (false === $parts) {
return [null, null];
}
$host = isset($parts['host']) ? $parts['host'] : null;
$port = isset($parts['port']) ? $parts['port'] : null;
return [$host, $port];
}
/**
* Get a Uri populated with values from $_SERVER.
*
* @return UriInterface
*/
public static function getUriFromGlobals() {
public static function getUriFromGlobals()
{
$uri = new Uri('');
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
$hasPort = false;
if (isset($_SERVER['HTTP_HOST'])) {
$hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']);
$uri = $uri->withHost($hostHeaderParts[0]);
if (isset($hostHeaderParts[1])) {
list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
if ($host !== null) {
$uri = $uri->withHost($host);
}
if ($port !== null) {
$hasPort = true;
$uri = $uri->withPort($hostHeaderParts[1]);
$uri = $uri->withPort($port);
}
} elseif (isset($_SERVER['SERVER_NAME'])) {
$uri = $uri->withHost($_SERVER['SERVER_NAME']);
@ -210,7 +228,7 @@ class ServerRequest extends Request implements ServerRequestInterface
$hasQuery = false;
if (isset($_SERVER['REQUEST_URI'])) {
$requestUriParts = explode('?', $_SERVER['REQUEST_URI']);
$requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);
$uri = $uri->withPath($requestUriParts[0]);
if (isset($requestUriParts[1])) {
$hasQuery = true;

View file

@ -24,11 +24,11 @@ class Stream implements StreamInterface
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
'x+t' => true, 'c+t' => true, 'a+' => true
'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true,
],
'write' => [
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true,
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
]
@ -70,15 +70,6 @@ class Stream implements StreamInterface
$this->uri = $this->getMetadata('uri');
}
public function __get($name)
{
if ($name == 'stream') {
throw new \RuntimeException('The stream is detached');
}
throw new \BadMethodCallException('No value for ' . $name);
}
/**
* Closes the stream when the destructed
*/
@ -99,6 +90,10 @@ class Stream implements StreamInterface
public function getContents()
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
$contents = stream_get_contents($this->stream);
if ($contents === false) {
@ -173,11 +168,19 @@ class Stream implements StreamInterface
public function eof()
{
return !$this->stream || feof($this->stream);
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
return feof($this->stream);
}
public function tell()
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
$result = ftell($this->stream);
if ($result === false) {
@ -194,9 +197,13 @@ class Stream implements StreamInterface
public function seek($offset, $whence = SEEK_SET)
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->seekable) {
throw new \RuntimeException('Stream is not seekable');
} elseif (fseek($this->stream, $offset, $whence) === -1) {
}
if (fseek($this->stream, $offset, $whence) === -1) {
throw new \RuntimeException('Unable to seek to stream position '
. $offset . ' with whence ' . var_export($whence, true));
}
@ -204,6 +211,9 @@ class Stream implements StreamInterface
public function read($length)
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->readable) {
throw new \RuntimeException('Cannot read from non-readable stream');
}
@ -225,6 +235,9 @@ class Stream implements StreamInterface
public function write($string)
{
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
if (!$this->writable) {
throw new \RuntimeException('Cannot write to a non-writable stream');
}

View file

@ -38,9 +38,21 @@ class StreamWrapper
. 'writable, or both.');
}
return fopen('guzzle://stream', $mode, null, stream_context_create([
return fopen('guzzle://stream', $mode, null, self::createStreamContext($stream));
}
/**
* Creates a stream context that can be used to open a stream as a php stream resource.
*
* @param StreamInterface $stream
*
* @return resource
*/
public static function createStreamContext(StreamInterface $stream)
{
return stream_context_create([
'guzzle' => ['stream' => $stream]
]));
]);
}
/**
@ -94,12 +106,21 @@ class StreamWrapper
return true;
}
public function stream_cast($cast_as)
{
$stream = clone($this->stream);
return $stream->detach();
}
public function stream_stat()
{
static $modeMap = [
'r' => 33060,
'rb' => 33060,
'r+' => 33206,
'w' => 33188
'w' => 33188,
'wb' => 33188
];
return [
@ -118,4 +139,23 @@ class StreamWrapper
'blocks' => 0
];
}
public function url_stat($path, $flags)
{
return [
'dev' => 0,
'ino' => 0,
'mode' => 0,
'nlink' => 0,
'uid' => 0,
'gid' => 0,
'rdev' => 0,
'size' => 0,
'atime' => 0,
'mtime' => 0,
'ctime' => 0,
'blksize' => 0,
'blocks' => 0
];
}
}

View file

@ -301,15 +301,7 @@ class Uri implements UriInterface
*/
public static function withoutQueryValue(UriInterface $uri, $key)
{
$current = $uri->getQuery();
if ($current === '') {
return $uri;
}
$decodedKey = rawurldecode($key);
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
});
$result = self::getFilteredQueryString($uri, [$key]);
return $uri->withQuery(implode('&', $result));
}
@ -331,26 +323,29 @@ class Uri implements UriInterface
*/
public static function withQueryValue(UriInterface $uri, $key, $value)
{
$current = $uri->getQuery();
$result = self::getFilteredQueryString($uri, [$key]);
if ($current === '') {
$result = [];
} else {
$decodedKey = rawurldecode($key);
$result = array_filter(explode('&', $current), function ($part) use ($decodedKey) {
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
});
}
$result[] = self::generateQueryString($key, $value);
// Query string separators ("=", "&") within the key or value need to be encoded
// (while preventing double-encoding) before setting the query string. All other
// chars that need percent-encoding will be encoded by withQuery().
$key = strtr($key, self::$replaceQuery);
return $uri->withQuery(implode('&', $result));
}
if ($value !== null) {
$result[] = $key . '=' . strtr($value, self::$replaceQuery);
} else {
$result[] = $key;
/**
* Creates a new URI with multiple specific query string values.
*
* It has the same behavior as withQueryValue() but for an associative array of key => value.
*
* @param UriInterface $uri URI to use as a base.
* @param array $keyValueArray Associative array of key and values
*
* @return UriInterface
*/
public static function withQueryValues(UriInterface $uri, array $keyValueArray)
{
$result = self::getFilteredQueryString($uri, array_keys($keyValueArray));
foreach ($keyValueArray as $key => $value) {
$result[] = self::generateQueryString($key, $value);
}
return $uri->withQuery(implode('&', $result));
@ -620,6 +615,47 @@ class Uri implements UriInterface
return $port;
}
/**
* @param UriInterface $uri
* @param array $keys
*
* @return array
*/
private static function getFilteredQueryString(UriInterface $uri, array $keys)
{
$current = $uri->getQuery();
if ($current === '') {
return [];
}
$decodedKeys = array_map('rawurldecode', $keys);
return array_filter(explode('&', $current), function ($part) use ($decodedKeys) {
return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true);
});
}
/**
* @param string $key
* @param string|null $value
*
* @return string
*/
private static function generateQueryString($key, $value)
{
// Query string separators ("=", "&") within the key or value need to be encoded
// (while preventing double-encoding) before setting the query string. All other
// chars that need percent-encoding will be encoded by withQuery().
$queryString = strtr($key, self::$replaceQuery);
if ($value !== null) {
$queryString .= '=' . strtr($value, self::$replaceQuery);
}
return $queryString;
}
private function removeDefaultPort()
{
if ($this->port !== null && self::isDefaultPort($this)) {

View file

@ -69,10 +69,10 @@ function uri_for($uri)
* - metadata: Array of custom metadata.
* - size: Size of the stream.
*
* @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data
* @param array $options Additional options
* @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data
* @param array $options Additional options
*
* @return Stream
* @return StreamInterface
* @throws \InvalidArgumentException if the $resource arg is not valid.
*/
function stream_for($resource = '', array $options = [])
@ -238,7 +238,7 @@ function modify_request(RequestInterface $request, array $changes)
}
if ($request instanceof ServerRequestInterface) {
return new ServerRequest(
return (new ServerRequest(
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
$uri,
$headers,
@ -247,7 +247,11 @@ function modify_request(RequestInterface $request, array $changes)
? $changes['version']
: $request->getProtocolVersion(),
$request->getServerParams()
);
))
->withParsedBody($request->getParsedBody())
->withQueryParams($request->getQueryParams())
->withCookieParams($request->getCookieParams())
->withUploadedFiles($request->getUploadedFiles());
}
return new Request(
@ -431,7 +435,7 @@ function hash(
* @param StreamInterface $stream Stream to read from
* @param int $maxLength Maximum buffer length
*
* @return string|bool
* @return string
*/
function readline(StreamInterface $stream, $maxLength = null)
{
@ -495,7 +499,7 @@ function parse_response($message)
// between status-code and reason-phrase is required. But browsers accept
// responses without space and reason as well.
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
throw new \InvalidArgumentException('Invalid response string');
throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
}
$parts = explode(' ', $data['start-line'], 3);
@ -516,8 +520,8 @@ function parse_response($message)
* PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
* be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
*
* @param string $str Query string to parse
* @param bool|string $urlEncoding How the query string is encoded
* @param string $str Query string to parse
* @param int|bool $urlEncoding How the query string is encoded
*
* @return array
*/
@ -533,9 +537,9 @@ function parse_query($str, $urlEncoding = true)
$decoder = function ($value) {
return rawurldecode(str_replace('+', ' ', $value));
};
} elseif ($urlEncoding == PHP_QUERY_RFC3986) {
} elseif ($urlEncoding === PHP_QUERY_RFC3986) {
$decoder = 'rawurldecode';
} elseif ($urlEncoding == PHP_QUERY_RFC1738) {
} elseif ($urlEncoding === PHP_QUERY_RFC1738) {
$decoder = 'urldecode';
} else {
$decoder = function ($str) { return $str; };
@ -633,6 +637,7 @@ function mimetype_from_filename($filename)
function mimetype_from_extension($extension)
{
static $mimetypes = [
'3gp' => 'video/3gpp',
'7z' => 'application/x-7z-compressed',
'aac' => 'audio/x-aac',
'ai' => 'application/postscript',
@ -680,6 +685,7 @@ function mimetype_from_extension($extension)
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mov' => 'video/quicktime',
'mkv' => 'video/x-matroska',
'mp3' => 'audio/mpeg',
'mp4' => 'video/mp4',
'mp4a' => 'audio/mp4',
@ -758,29 +764,53 @@ function _parse_message($message)
throw new \InvalidArgumentException('Invalid message');
}
// Iterate over each line in the message, accounting for line endings
$lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
$result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => ''];
array_shift($lines);
$message = ltrim($message, "\r\n");
for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
$line = $lines[$i];
// If two line breaks were encountered, then this is the end of body
if (empty($line)) {
if ($i < $totalLines - 1) {
$result['body'] = implode('', array_slice($lines, $i + 2));
}
break;
}
if (strpos($line, ':')) {
$parts = explode(':', $line, 2);
$key = trim($parts[0]);
$value = isset($parts[1]) ? trim($parts[1]) : '';
$result['headers'][$key][] = $value;
}
$messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
if ($messageParts === false || count($messageParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
}
return $result;
list($rawHeaders, $body) = $messageParts;
$rawHeaders .= "\r\n"; // Put back the delimiter we split previously
$headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
if ($headerParts === false || count($headerParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing status line');
}
list($startLine, $rawHeaders) = $headerParts;
if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
$rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
}
/** @var array[] $headerLines */
$count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
// If these aren't the same, then one line didn't match and there's an invalid header.
if ($count !== substr_count($rawHeaders, "\n")) {
// Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
}
throw new \InvalidArgumentException('Invalid header syntax');
}
$headers = [];
foreach ($headerLines as $headerLine) {
$headers[$headerLine[1]][] = $headerLine[2];
}
return [
'start-line' => $startLine,
'headers' => $headers,
'body' => $body,
];
}
/**
@ -809,6 +839,46 @@ function _parse_request_uri($path, array $headers)
return $scheme . '://' . $host . '/' . ltrim($path, '/');
}
/**
* Get a short summary of the message body
*
* Will return `null` if the response is not printable.
*
* @param MessageInterface $message The message to get the body summary
* @param int $truncateAt The maximum allowed size of the summary
*
* @return null|string
*/
function get_message_body_summary(MessageInterface $message, $truncateAt = 120)
{
$body = $message->getBody();
if (!$body->isSeekable() || !$body->isReadable()) {
return null;
}
$size = $body->getSize();
if ($size === 0) {
return null;
}
$summary = $body->read($truncateAt);
$body->rewind();
if ($size > $truncateAt) {
$summary .= ' (truncated...)';
}
// Matches any printable character, including unicode characters:
// letters, marks, numbers, punctuation, spacing, and separators.
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
return null;
}
return $summary;
}
/** @internal */
function _caseless_remove($keys, array $data)
{

View file

@ -1,4 +1,5 @@
vendor/
scratch.php
composer.lock
build/
build/
.php_cs.cache

14
vendor/masterminds/html5/.php_cs.dist vendored Normal file
View file

@ -0,0 +1,14 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
;
return PhpCsFixer\Config::create()
->setRules(array(
'@Symfony' => true,
'concat_space' => array('spacing' => 'one'),
'phpdoc_annotation_without_dot' => false,
))
->setFinder($finder)
;

View file

@ -1,39 +1,42 @@
language: php
dist: trusty
sudo: false
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm
matrix:
include:
- php: 5.3
dist: precise
fast_finish: true
dist: trusty
include:
- php: 5.3
dist: precise
env: COMPOSER_FLAGS="--prefer-lowest"
- php: 5.4
- php: 5.5
- php: 5.6
env: SCRUTINIZER=1
- php: 7.0
env: COMPOSER_FLAGS="--prefer-lowest"
- php: 7.1
env: CS_FIXER=1
- php: 7.2
env: BENCHMARK=1
- php: hhvm
fast_finish: true
cache:
directories:
- $HOME/.composer/cache
notifications:
irc: "irc.freenode.net#masterminds"
before_script:
- composer self-update
- composer install
- composer update $COMPOSER_FLAGS --prefer-dist
script:
- stty cols 120
- if [ "$CS_FIXER" == 1 ]; then wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.13.1/php-cs-fixer.phar && php php-cs-fixer.phar fix --dry-run --diff; fi
- mkdir -p build/logs
- ./vendor/bin/phpunit --coverage-clover=coverage.xml
after_script:
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then wget https://scrutinizer-ci.com/ocular.phar; fi;'
- bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then php ocular.phar code-coverage:upload --format=php-clover coverage.xml; fi;'
- php test/benchmark/run.php 10
- if [ "$SCRUTINIZER" == 1 ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.xml; fi
- if [ "$BENCHMARK" == 1 ]; then php test/benchmark/run.php 10; fi
notifications:
irc: "irc.freenode.net#masterminds"

View file

@ -2,7 +2,7 @@
HTML5 is a standards-compliant HTML5 parser and writer written entirely in PHP.
It is stable and used in many production websites, and has
well over [one million downloads](https://packagist.org/packages/masterminds/html5).
well over [five million downloads](https://packagist.org/packages/masterminds/html5).
HTML5 provides the following features.
@ -24,21 +24,21 @@ HTML5 provides the following features.
Install HTML5-PHP using [composer](http://getcomposer.org/).
To install, add `masterminds/html5` to your `composer.json` file:
By adding the `masterminds/html5` dependency to your `composer.json` file:
```json
{
"require" : {
"masterminds/html5": "2.*"
"masterminds/html5": "^2.0"
},
}
```
(You may substitute `2.*` for a more specific release tag, of
course.)
By invoking require command via composer executable:
From there, use the `composer install` or `composer update` commands to
install.
```bash
composer require masterminds/html5
```
## Basic Usage

View file

@ -1,5 +1,13 @@
# Release Notes
2.5.0 (2018-12-27)
- #162, #161, #155, #154, #153, #151: big performance improvements
- #156: fixed typos
- #160: adopt and enforce code style
- #159: remove deprecated php unit base test case
- #150: backport changes from old master branch
2.4.0 (2018-11-17)
- #148: Improve performance by moving sequence matching

View file

@ -11,16 +11,16 @@ $json = json_decode($payload);
$table = array();
foreach ($json as $name => $obj) {
$sname = substr($name, 1, -1);
$table[$sname] = $obj->characters;
$sname = substr($name, 1, -1);
$table[$sname] = $obj->characters;
}
print '<?php
echo '<?php
namespace Masterminds\\HTML5;
/** Entity lookup tables. This class is automatically generated. */
class Entities {
public static $byName = ';
var_export($table);
print ';
echo ';
}' . PHP_EOL;
//print serialize($table);

View file

@ -27,7 +27,7 @@
},
"require-dev": {
"satooshi/php-coveralls": "1.0.*",
"phpunit/phpunit" : "4.*",
"phpunit/phpunit" : "^4.8.35",
"sami/sami": "~2.0"
},
"autoload": {
@ -38,7 +38,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-master": "2.4-dev"
}
}
}

View file

@ -1,9 +1,8 @@
<?php
require "vendor/autoload.php";
require 'vendor/autoload.php';
use Masterminds\HTML5;
$html = <<< 'HERE'
<html>
<head>
@ -28,6 +27,6 @@ HERE;
$html5 = new HTML5();
$dom = $html5->loadHTML($html);
print "Converting to HTML 5\n";
echo "Converting to HTML 5\n";
$html5->save($dom, fopen("php://stdin", 'w'));
$html5->save($dom, fopen('php://stdin', 'w'));

View file

@ -2,9 +2,9 @@
use Sami\Sami;
return new Sami(__DIR__ . '/src' , array(
'title' => 'HTML5-PHP API',
'build_dir' => __DIR__.'/build/apidoc',
'cache_dir' => __DIR__.'/build/sami-cache',
return new Sami(__DIR__ . '/src', array(
'title' => 'HTML5-PHP API',
'build_dir' => __DIR__ . '/build/apidoc',
'cache_dir' => __DIR__ . '/build/sami-cache',
'default_opened_level' => 1,
));
));

View file

@ -1,9 +1,7 @@
<?php
namespace Masterminds;
use Masterminds\HTML5\Parser\FileInputStream;
use Masterminds\HTML5\Parser\InputStream;
use Masterminds\HTML5\Parser\StringInputStream;
use Masterminds\HTML5\Parser\DOMTreeBuilder;
use Masterminds\HTML5\Parser\Scanner;
use Masterminds\HTML5\Parser\Tokenizer;
@ -12,37 +10,38 @@ use Masterminds\HTML5\Serializer\Traverser;
/**
* This class offers convenience methods for parsing and serializing HTML5.
* It is roughly designed to mirror the \DOMDocument class that is
* provided with most versions of PHP.
* It is roughly designed to mirror the \DOMDocument native class.
*/
class HTML5
{
/**
* Global options for the parser and serializer.
*
* @var array
*/
protected $options = array(
// If the serializer should encode all entities.
'encode_entities' => false
private $defaultOptions = array(
// Whether the serializer should aggressively encode all characters as entities.
'encode_entities' => false,
// Prevents the parser from automatically assigning the HTML5 namespace to the DOM document.
'disable_html_ns' => false,
);
protected $errors = array();
public function __construct(array $options = array())
public function __construct(array $defaultOptions = array())
{
$this->options = array_merge($this->options, $options);
$this->defaultOptions = array_merge($this->defaultOptions, $defaultOptions);
}
/**
* Get the default options.
* Get the current default options.
*
* @return array The default options.
* @return array
*/
public function getOptions()
{
return $this->options;
return $this->defaultOptions;
}
/**
@ -55,14 +54,13 @@ class HTML5
*
* The rules governing parsing are set out in the HTML 5 spec.
*
* @param string|resource $file
* The path to the file to parse. If this is a resource, it is
* assumed to be an open stream whose pointer is set to the first
* byte of input.
* @param array $options
* Configuration options when parsing the HTML
* @param string|resource $file The path to the file to parse. If this is a resource, it is
* assumed to be an open stream whose pointer is set to the first
* byte of input.
* @param array $options Configuration options when parsing the HTML.
*
* @return \DOMDocument A DOM document. These object type is defined by the libxml
* library, and should have been included with your version of PHP.
* library, and should have been included with your version of PHP.
*/
public function load($file, array $options = array())
{
@ -80,12 +78,11 @@ class HTML5
* Take a string of HTML 5 (or earlier) and parse it into a
* DOMDocument.
*
* @param string $string
* A html5 document as a string.
* @param array $options
* Configuration options when parsing the HTML
* @param string $string A html5 document as a string.
* @param array $options Configuration options when parsing the HTML.
*
* @return \DOMDocument A DOM document. DOM is part of libxml, which is included with
* almost all distribtions of PHP.
* almost all distribtions of PHP.
*/
public function loadHTML($string, array $options = array())
{
@ -98,15 +95,13 @@ class HTML5
* This is here to provide backwards compatibility with the
* PHP DOM implementation. It simply calls load().
*
* @param string $file
* The path to the file to parse. If this is a resource, it is
* assumed to be an open stream whose pointer is set to the first
* byte of input.
* @param array $options
* Configuration options when parsing the HTML
* @param string $file The path to the file to parse. If this is a resource, it is
* assumed to be an open stream whose pointer is set to the first
* byte of input.
* @param array $options Configuration options when parsing the HTML.
*
* @return \DOMDocument A DOM document. These object type is defined by the libxml
* library, and should have been included with your version of PHP.
* library, and should have been included with your version of PHP.
*/
public function loadHTMLFile($file, array $options = array())
{
@ -116,11 +111,11 @@ class HTML5
/**
* Parse a HTML fragment from a string.
*
* @param string $string The HTML5 fragment as a string.
* @param array $options Configuration options when parsing the HTML
* @param string $string the HTML5 fragment as a string
* @param array $options Configuration options when parsing the HTML
*
* @return \DOMDocumentFragment A DOM fragment. The DOM is part of libxml, which is included with
* almost all distributions of PHP.
* almost all distributions of PHP.
*/
public function loadHTMLFragment($string, array $options = array())
{
@ -128,7 +123,7 @@ class HTML5
}
/**
* Return all errors encountered into parsing phase
* Return all errors encountered into parsing phase.
*
* @return array
*/
@ -138,7 +133,7 @@ class HTML5
}
/**
* Return true it some errors were encountered into parsing phase
* Return true it some errors were encountered into parsing phase.
*
* @return bool
*/
@ -148,23 +143,20 @@ class HTML5
}
/**
* Parse an input stream.
*
* Lower-level loading function. This requires an input stream instead
* of a string, file, or resource.
* Parse an input string.
*
* @param string $input
* @param array $options
* @param array $options
*
* @return \DOMDocument
*/
public function parse($input, array $options = array())
{
$this->errors = array();
$options = array_merge($this->getOptions(), $options);
$options = array_merge($this->defaultOptions, $options);
$events = new DOMTreeBuilder(false, $options);
$scanner = new Scanner($input);
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML: Tokenizer::CONFORMANT_HTML);
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML);
$parser->parse();
$this->errors = $events->getErrors();
@ -178,17 +170,17 @@ class HTML5
* Lower-level loading function. This requires an input stream instead
* of a string, file, or resource.
*
* @param string $input The input data to parse in the form of a string.
* @param array $options An array of options
* @param string $input The input data to parse in the form of a string.
* @param array $options An array of options.
*
* @return \DOMDocumentFragment
*/
public function parseFragment($input, array $options = array())
{
$options = array_merge($this->getOptions(), $options);
$options = array_merge($this->defaultOptions, $options);
$events = new DOMTreeBuilder(true, $options);
$scanner = new Scanner($input);
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML: Tokenizer::CONFORMANT_HTML);
$parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML);
$parser->parse();
$this->errors = $events->getErrors();
@ -199,15 +191,12 @@ class HTML5
/**
* Save a DOM into a given file as HTML5.
*
* @param mixed $dom
* The DOM to be serialized.
* @param string $file
* The filename to be written.
* @param array $options
* Configuration options when serializing the DOM. These include:
* - encode_entities: Text written to the output is escaped by default and not all
* entities are encoded. If this is set to true all entities will be encoded.
* Defaults to false.
* @param mixed $dom The DOM to be serialized.
* @param string|resource $file The filename to be written or resource to write to.
* @param array $options Configuration options when serializing the DOM. These include:
* - encode_entities: Text written to the output is escaped by default and not all
* entities are encoded. If this is set to true all entities will be encoded.
* Defaults to false.
*/
public function save($dom, $file, $options = array())
{
@ -216,9 +205,9 @@ class HTML5
$stream = $file;
$close = false;
} else {
$stream = fopen($file, 'w');
$stream = fopen($file, 'wb');
}
$options = array_merge($this->getOptions(), $options);
$options = array_merge($this->defaultOptions, $options);
$rules = new OutputRules($stream, $options);
$trav = new Traverser($dom, $stream, $rules, $options);
@ -232,21 +221,19 @@ class HTML5
/**
* Convert a DOM into an HTML5 string.
*
* @param mixed $dom
* The DOM to be serialized.
* @param array $options
* Configuration options when serializing the DOM. These include:
* - encode_entities: Text written to the output is escaped by default and not all
* entities are encoded. If this is set to true all entities will be encoded.
* Defaults to false.
* @param mixed $dom The DOM to be serialized.
* @param array $options Configuration options when serializing the DOM. These include:
* - encode_entities: Text written to the output is escaped by default and not all
* entities are encoded. If this is set to true all entities will be encoded.
* Defaults to false.
*
* @return string A HTML5 documented generated from the DOM.
*/
public function saveHTML($dom, $options = array())
{
$stream = fopen('php://temp', 'w');
$this->save($dom, $stream, array_merge($this->getOptions(), $options));
$stream = fopen('php://temp', 'wb');
$this->save($dom, $stream, array_merge($this->defaultOptions, $options));
return stream_get_contents($stream, - 1, 0);
return stream_get_contents($stream, -1, 0);
}
}

Some files were not shown because too many files have changed in this diff Show more