First commit
This commit is contained in:
commit
c6e2478c40
13918 changed files with 2303184 additions and 0 deletions
15
vendor/consolidation/annotated-command/.editorconfig
vendored
Normal file
15
vendor/consolidation/annotated-command/.editorconfig
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[**.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
11
vendor/consolidation/annotated-command/.github/issue_template.md
vendored
Normal file
11
vendor/consolidation/annotated-command/.github/issue_template.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
### Steps to reproduce
|
||||
What did you do?
|
||||
|
||||
### Expected behavior
|
||||
Tell us what should happen
|
||||
|
||||
### Actual behavior
|
||||
Tell us what happens instead
|
||||
|
||||
### System Configuration
|
||||
Which O.S. and PHP version are you using?
|
13
vendor/consolidation/annotated-command/.github/pull_request_template.md
vendored
Normal file
13
vendor/consolidation/annotated-command/.github/pull_request_template.md
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
### Disposition
|
||||
This pull request:
|
||||
|
||||
- [ ] Fixes a bug
|
||||
- [ ] Adds a feature
|
||||
- [ ] Breaks backwards compatibility
|
||||
- [ ] Has tests that cover changes
|
||||
|
||||
### Summary
|
||||
Short overview of what changed.
|
||||
|
||||
### Description
|
||||
Any additional information.
|
5
vendor/consolidation/annotated-command/.gitignore
vendored
Normal file
5
vendor/consolidation/annotated-command/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.DS_Store
|
||||
phpunit.xml
|
||||
vendor
|
||||
build
|
||||
.idea
|
99
vendor/consolidation/annotated-command/.travis.yml
vendored
Normal file
99
vendor/consolidation/annotated-command/.travis.yml
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
language: php
|
||||
|
||||
branches:
|
||||
# Only test the master branch and SemVer tags.
|
||||
only:
|
||||
- master
|
||||
- '/^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+.*$/'
|
||||
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
php: 7.1
|
||||
env: 'HIGHEST_LOWEST="update" STABILITY="RC"'
|
||||
-
|
||||
php: 7.0.11
|
||||
env: DO_POST_BUILD_ACTIONS=1
|
||||
-
|
||||
php: 5.6
|
||||
-
|
||||
php: 5.5
|
||||
-
|
||||
php: 5.4
|
||||
env: 'HIGHEST_LOWEST="update --prefer-lowest"'
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_script:
|
||||
# If running a highest/lowest dependencies test, get rid of composer.lock
|
||||
- |
|
||||
if [ -n "$HIGHEST_LOWEST" ] ; then
|
||||
rm composer.lock
|
||||
composer config --unset platform.php
|
||||
composer config minimum-stability ${STABILITY-stable}
|
||||
fi
|
||||
- 'composer -n ${HIGHEST_LOWEST-install} --prefer-dist'
|
||||
- composer why symfony/console
|
||||
# Print out all of the installed packages in alphabetical order, with versions
|
||||
- composer licenses
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit
|
||||
- 'vendor/bin/phpcs --standard=PSR2 -n src'
|
||||
|
||||
after_success:
|
||||
- 'travis_retry php vendor/bin/coveralls -v'
|
||||
- |
|
||||
# Only do post-build actions in one environment, and only if there is a GITHUB token.
|
||||
if [ -z "$DO_POST_BUILD_ACTIONS" ] ; then
|
||||
return
|
||||
fi
|
||||
if [ -z "$GITHUB_TOKEN" ]; then
|
||||
echo "No GITHUB_TOKEN defined; exiting."
|
||||
return
|
||||
fi
|
||||
###
|
||||
# Run composer lock update on cron jobs.
|
||||
# See: https://github.com/danielbachhuber/composer-lock-updater
|
||||
###
|
||||
if [ "$TRAVIS_EVENT_TYPE" != "cron" ] ; then
|
||||
echo "Not a cron job; exiting."
|
||||
return
|
||||
fi
|
||||
###
|
||||
# Only run on one job of a master branch build
|
||||
###
|
||||
if [ "master" != "$TRAVIS_BRANCH" ] ; then
|
||||
echo "composer.lock update only runs on the master branch."
|
||||
return
|
||||
fi
|
||||
###
|
||||
# Install composer-lock-updater
|
||||
###
|
||||
export PATH="$HOME/.composer/vendor/bin:$PATH"
|
||||
composer global require danielbachhuber/composer-lock-updater
|
||||
###
|
||||
# Optional: install Sensio Labs security checker to include security advisories in PR comments
|
||||
###
|
||||
mkdir -p $HOME/bin
|
||||
wget -O $HOME/bin/security-checker.phar http://get.sensiolabs.org/security-checker.phar
|
||||
chmod +x $HOME/bin/security-checker.phar
|
||||
export PATH="$HOME/bin:$PATH"
|
||||
###
|
||||
# Install hub for creating GitHub pull requests
|
||||
###
|
||||
wget -O hub.tgz https://github.com/github/hub/releases/download/v2.2.9/hub-linux-amd64-2.2.9.tgz
|
||||
tar -zxvf hub.tgz
|
||||
export PATH=$PATH:$PWD/hub-linux-amd64-2.2.9/bin/
|
||||
###
|
||||
# Run composer-lock-updater
|
||||
###
|
||||
clu
|
||||
|
||||
|
||||
|
||||
|
148
vendor/consolidation/annotated-command/CHANGELOG.md
vendored
Normal file
148
vendor/consolidation/annotated-command/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
# Change Log
|
||||
|
||||
### 2.8.2 - 29 Nov 2017
|
||||
|
||||
- Allow Symfony 4 components.
|
||||
|
||||
### 2.8.1 - 16 Oct 2017
|
||||
|
||||
- Add hook methods to allow Symfony command events to be added directly to the hook manager, givig better control of hook order. (#131)
|
||||
|
||||
### 2.8.0 - 13 Oct 2017
|
||||
|
||||
- Remove phpdocumentor/reflection-docblock in favor of using a bespoke parser (#130)
|
||||
|
||||
### 2.7.0 - 18 Sept 2017
|
||||
|
||||
- Add support for options with a default value of 'true' (#119)
|
||||
- BUGFIX: Improve handling of options with optional values, which previously was not working correctly. (#118)
|
||||
|
||||
### 2.6.1 - 18 Sep 2017
|
||||
|
||||
- Reverts to contents of the 2.4.13 release.
|
||||
|
||||
### 2.5.0 & 2.5.1 - 17 Sep 2017
|
||||
|
||||
- BACKED OUT. These releases accidentally introduced breaking changes.
|
||||
|
||||
### 2.4.13 - 28 Aug 2017
|
||||
|
||||
- Add a followLinks() method (#108)
|
||||
|
||||
### 2.4.12 - 24 Aug 2017
|
||||
|
||||
- BUGFIX: Allow annotated commands to directly use InputInterface and OutputInterface (#106)
|
||||
|
||||
### 2.4.11 - 27 July 2017
|
||||
|
||||
- Back out #102: do not change behavior of word wrap based on STDOUT redirection.
|
||||
|
||||
### 2.4.10 - 21 July 2017
|
||||
|
||||
- Add a method CommandProcessor::setPassExceptions() to allow applicationsto prevent the command processor from catching exceptions thrown by command methods and hooks. (#103)
|
||||
|
||||
### 2.4.9 - 20 Jul 2017
|
||||
|
||||
- Automatically disable wordwrap when the terminal is not connected to STDOUT (#102)
|
||||
|
||||
### 2.4.8 - 3 Apr 2017
|
||||
|
||||
- Allow multiple annotations with the same key. These are returned as a csv, or, alternately, can be accessed as an array via the new accessor.
|
||||
- Unprotect two methods for benefit of Drush help. (#99)
|
||||
- BUGFIX: Remove symfony/console pin (#100)
|
||||
|
||||
### 2.4.7 & 2.4.6 - 17 Mar 2017
|
||||
|
||||
- Avoid wrapping help text (#93)
|
||||
- Pin symfony/console to version < 3.2.5 (#94)
|
||||
- Add getExampleUsages() to AnnotatedCommand. (#92)
|
||||
|
||||
### 2.4.5 - 28 Feb 2017
|
||||
|
||||
- Ensure that placeholder entries are written into the commandfile cache. (#86)
|
||||
|
||||
### 2.4.4 - 27 Feb 2017
|
||||
|
||||
- BUGFIX: Avoid rewriting the command cache unless something has changed.
|
||||
- BUGFIX: Ensure that the default value of options are correctly cached.
|
||||
|
||||
### 2.4.2 - 24 Feb 2017
|
||||
|
||||
- Add SimpleCacheInterface as a documentation interface (not enforced).
|
||||
|
||||
### 2.4.1 - 20 Feb 2017
|
||||
|
||||
- Support array options: multiple options on the commandline may be passed in to options array as an array of values.
|
||||
- Add php 7.1 to the test matrix.
|
||||
|
||||
### 2.4.0 - 3 Feb 2017
|
||||
|
||||
- Automatically rebuild cached commandfile data when commandfile changes.
|
||||
- Provide path to command file in AnnotationData objects.
|
||||
- Bugfix: Add dynamic options when user runs '--help my:command' (previously, only 'help my:command' worked).
|
||||
- Bugfix: Include description of last parameter in help (was omitted if no options present)
|
||||
- Add Windows testing with Appveyor
|
||||
|
||||
|
||||
### 2.3.0 - 19 Jan 2017
|
||||
|
||||
- Add a command info cache to improve performance of applications with many commands
|
||||
- Bugfix: Allow trailing backslashes in namespaces in CommandFileDiscovery
|
||||
- Bugfix: Rename @topic to @topics
|
||||
|
||||
|
||||
### 2.2.0 - 23 November 2016
|
||||
|
||||
- Support custom events
|
||||
- Add xml and json output for replacement help command. Text / html format for replacement help command not available yet.
|
||||
|
||||
|
||||
### 2.1.0 - 14 November 2016
|
||||
|
||||
- Add support for output formatter wordwrapping
|
||||
- Fix version requirement for output-formatters in composer.json
|
||||
- Use output-formatters ~3
|
||||
- Move php_codesniffer back to require-dev (moved to require by mistake)
|
||||
|
||||
|
||||
### 2.0.0 - 30 September 2016
|
||||
|
||||
- **Breaking** Hooks with no command name now apply to all commands defined in the same class. This is a change of behavior from the 1.x branch, where hooks with no command name applied to a command with the same method name in a *different* class.
|
||||
- **Breaking** The interfaces ValidatorInterface, ProcessResultInterface and AlterResultInterface have been updated to be passed a CommandData object, which contains an Input and Output object, plus the AnnotationData.
|
||||
- **Breaking** The Symfony Command Event hook has been renamed to COMMAND_EVENT. There is a new COMMAND hook that behaves like the existing Drush command hook (i.e. the post-command event is called after the primary command method runs).
|
||||
- Add an accessor function AnnotatedCommandFactory::setIncludeAllPublicMethods() to control whether all public methods of a command class, or only those with a @command annotation will be treated as commands. Default remains to treat all public methods as commands. The parameters to AnnotatedCommandFactory::createCommandsFromClass() and AnnotatedCommandFactory::createCommandsFromClassInfo() still behave the same way, but are deprecated. If omitted, the value set by the accessor will be used.
|
||||
- @option and @usage annotations provided with @hook methods will be added to the help text of the command they hook. This should be done if a hook needs to add a new option, e.g. to control the behavior of the hook.
|
||||
- @option annotations can now be either `@option type $name description`, or just `@option name description`.
|
||||
- `@hook option` can be used to programatically add options to a command.
|
||||
- A CommandInfoAltererInterface can be added via AnnotatedCommandFactory::addCommandInfoAlterer(); it will be given the opportunity to adjust every CommandInfo object parsed from a command file prior to the creation of commands.
|
||||
- AnnotatedCommandFactory::setIncludeAllPublicMethods(false) may be used to require methods to be annotated with @commnad in order to be considered commands. This is in preference to the existing parameters of various command-creation methods of AnnotatedCommandFactory, which are now all deprecated in favor of this setter function.
|
||||
- If a --field option is given, it will also force the output format to 'string'.
|
||||
- Setter methods more consistently return $this.
|
||||
- Removed PassThroughArgsInput. This class was unnecessary.
|
||||
|
||||
|
||||
### 1.4.0 - 13 September 2016
|
||||
|
||||
- Add basic annotation hook capability, to allow hook functions to be attached to commands with arbitrary annotations.
|
||||
|
||||
|
||||
### 1.3.0 - 8 September 2016
|
||||
|
||||
- Add ComandFileDiscovery::setSearchDepth(). The search depth applies to each search location, unless there are no search locations, in which case it applies to the base directory.
|
||||
|
||||
|
||||
### 1.2.0 - 2 August 2016
|
||||
|
||||
- Support both the 2.x and 3.x versions of phpdocumentor/reflection-docblock.
|
||||
- Support php 5.4.
|
||||
- **Bug** Do not allow an @param docblock comment for the options to override the meaning of the options.
|
||||
|
||||
|
||||
### 1.1.0 - 6 July 2016
|
||||
|
||||
- Introduce AnnotatedCommandFactory::createSelectedCommandsFromClassInfo() method.
|
||||
|
||||
|
||||
### 1.0.0 - 20 May 2016
|
||||
|
||||
- First stable release.
|
31
vendor/consolidation/annotated-command/CONTRIBUTING.md
vendored
Normal file
31
vendor/consolidation/annotated-command/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Contributing to Consolidation
|
||||
|
||||
Thank you for your interest in contributing to the Consolidation effort! Consolidation aims to provide reusable, loosely-coupled components useful for building command-line tools. Consolidation is built on top of Symfony Console, but aims to separate the tool from the implementation details of Symfony.
|
||||
|
||||
Here are some of the guidelines you should follow to make the most of your efforts:
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
Consolidation adheres to the [PSR-2 Coding Style Guide](http://www.php-fig.org/psr/psr-2/) for PHP code.
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
Every pull request is run through:
|
||||
|
||||
- phpcs -n --standard=PSR2 src
|
||||
- phpunit
|
||||
- [Scrutinizer](https://scrutinizer-ci.com/g/consolidation/annotated-command/)
|
||||
|
||||
It is easy to run the unit tests and code sniffer locally; just run:
|
||||
|
||||
- composer cs
|
||||
|
||||
To run the code beautifier, which will fix many of the problems reported by phpcs:
|
||||
|
||||
- composer cbf
|
||||
|
||||
These two commands (`composer cs` and `composer cbf`) are defined in the `scripts` section of [composer.json](composer.json).
|
||||
|
||||
After submitting a pull request, please examine the Scrutinizer report. It is not required to fix all Scrutinizer issues; you may ignore recommendations that you disagree with. The spacing patches produced by Scrutinizer do not conform to PSR2 standards, and therefore should never be applied. DocBlock patches may be applied at your discression. Things that Scrutinizer identifies as a bug nearly always need to be addressed.
|
||||
|
||||
Pull requests must pass phpcs and phpunit in order to be merged; ideally, new functionality will also include new unit tests.
|
8
vendor/consolidation/annotated-command/LICENSE
vendored
Normal file
8
vendor/consolidation/annotated-command/LICENSE
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2016 Consolidation Org Developers
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
514
vendor/consolidation/annotated-command/README.md
vendored
Normal file
514
vendor/consolidation/annotated-command/README.md
vendored
Normal file
|
@ -0,0 +1,514 @@
|
|||
# Consolidation\AnnotatedCommand
|
||||
|
||||
Initialize Symfony Console commands from annotated command class methods.
|
||||
|
||||
[](https://travis-ci.org/consolidation/annotated-command)
|
||||
[](https://ci.appveyor.com/project/greg-1-anderson/annotated-command)
|
||||
[](https://scrutinizer-ci.com/g/consolidation/annotated-command/?branch=master)
|
||||
[](https://coveralls.io/github/consolidation/annotated-command?branch=master)
|
||||
[](https://packagist.org/packages/consolidation/annotated-command)
|
||||
|
||||
## Component Status
|
||||
|
||||
Currently in use in [Robo](https://github.com/consolidation/Robo) (1.x+), [Drush](https://github.com/drush-ops/drush) (9.x+) and [Terminus](https://github.com/pantheon-systems/terminus) (1.x+).
|
||||
|
||||
## Motivation
|
||||
|
||||
Symfony Console provides a set of classes that are widely used to implement command line tools. Increasingly, it is becoming popular to use annotations to describe the characteristics of the command (e.g. its arguments, options and so on) implemented by the annotated method.
|
||||
|
||||
Extant commandline tools that utilize this technique include:
|
||||
|
||||
- [Robo](https://github.com/consolidation/Robo)
|
||||
- [wp-cli](https://github.com/wp-cli/wp-cli)
|
||||
- [Pantheon Terminus](https://github.com/pantheon-systems/terminus)
|
||||
|
||||
This library provides routines to produce the Symfony\Component\Console\Command\Command from all public methods defined in the provided class.
|
||||
|
||||
**Note** If you are looking for a very fast way to write a Symfony Console-base command-line tool, you should consider using [Robo](https://github.com/consolidation/Robo), which is built on top of this library, and adds additional conveniences to get you going quickly. See [Using Robo as a Framework](https://github.com/consolidation/Robo/docs/framework.md). It is possible to use this project without Robo if desired, of course.
|
||||
|
||||
## Library Usage
|
||||
|
||||
This is a library intended to be used in some other project. Require from your composer.json file:
|
||||
```
|
||||
"require": {
|
||||
"consolidation/annotated-command": "~2"
|
||||
},
|
||||
```
|
||||
|
||||
## Example Annotated Command Class
|
||||
The public methods of the command class define its commands, and the parameters of each method define its arguments and options. The command options, if any, are declared as the last parameter of the methods. The options will be passed in as an associative array; the default options of the last parameter should list the options recognized by the command.
|
||||
|
||||
The rest of the parameters are arguments. Parameters with a default value are optional; those without a default value are required.
|
||||
```php
|
||||
class MyCommandClass
|
||||
{
|
||||
/**
|
||||
* This is the my:cat command
|
||||
*
|
||||
* This command will concatenate two parameters. If the --flip flag
|
||||
* is provided, then the result is the concatenation of two and one.
|
||||
*
|
||||
* @command my:cat
|
||||
* @param integer $one The first parameter.
|
||||
* @param integer $two The other parameter.
|
||||
* @option arr An option that takes multiple values.
|
||||
* @option flip Whether or not the second parameter should come first in the result.
|
||||
* @aliases c
|
||||
* @usage bet alpha --flip
|
||||
* Concatenate "alpha" and "bet".
|
||||
*/
|
||||
public function myCat($one, $two, $options = ['flip' => false])
|
||||
{
|
||||
if ($options['flip']) {
|
||||
return "{$two}{$one}";
|
||||
}
|
||||
return "{$one}{$two}";
|
||||
}
|
||||
}
|
||||
```
|
||||
## 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:
|
||||
|
||||
- The boolean value `false`, which indicates that the option takes no value.
|
||||
- A **string** containing the default value for options that may be provided a value, but are not required to.
|
||||
- The special value InputOption::VALUE_REQUIRED, which indicates that the user must provide a value for the option whenever it is used.
|
||||
- The special value InputOption::VALUE_OPTIONAL, which produces the following behavior:
|
||||
- If the option is given a value (e.g. `--foo=bar`), then the value will be a string.
|
||||
- If the option exists on the commandline, but has no value (e.g. `--foo`), then the value will be `true`.
|
||||
- If the option does not exist on the commandline at all, then the value will be `null`.
|
||||
- If the user explicitly sets `--foo=0`, then the value will be converted to `false`.
|
||||
- LIMITATION: If any Input object other than ArgvInput (or a subclass thereof) is used, then the value will be `null` for both the no-value case (`--foo`) and the no-option case. When using a StringInput, use `--foo=1` instead of `--foo` to avoid this problem.
|
||||
- The special value `true` produces the following behavior:
|
||||
- If the option is given a value (e.g. `--foo=bar`), then the value will be a string.
|
||||
- If the option exists on the commandline, but has no value (e.g. `--foo`), then the value will be `true`.
|
||||
- If the option does not exist on the commandline at all, then the value will also be `true`.
|
||||
- If the user explicitly sets `--foo=0`, then the value will be converted to `false`.
|
||||
- If the user adds `--no-foo` on the commandline, then the value of `foo` will be `false`.
|
||||
- An empty array, which indicates that the option may appear multiple times on the command line.
|
||||
|
||||
No other values should be used for the default value. For example, `$options = ['a' => 1]` is **incorrect**; instead, use `$options = ['a' => '1']`.
|
||||
|
||||
Default values for options may also be provided via the `@default` annotation. See hook alter, below.
|
||||
|
||||
## Hooks
|
||||
|
||||
Commandfiles may provide hooks in addition to commands. A commandfile method that contains a @hook annotation is registered as a hook instead of a command. The format of the hook annotation is:
|
||||
```
|
||||
@hook type target
|
||||
```
|
||||
The hook **type** determines when during the command lifecycle this hook will be called. The available hook types are described in detail below.
|
||||
|
||||
The hook **target** specifies which command or commands the hook will be attached to. There are several different ways to specify the hook target.
|
||||
|
||||
- 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 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:
|
||||
|
||||
- [Command Event](#command-event-hook) (Symfony)
|
||||
- @pre-command-event
|
||||
- @command-event
|
||||
- @post-command-event
|
||||
- [Option](#option-event-hook)
|
||||
- @pre-option
|
||||
- @option
|
||||
- @post-option
|
||||
- [Initialize](#initialize-hook) (Symfony)
|
||||
- @pre-init
|
||||
- @init
|
||||
- @post-init
|
||||
- [Interact](#interact-hook) (Symfony)
|
||||
- @pre-interact
|
||||
- @interact
|
||||
- @post-interact
|
||||
- [Validate](#validate-hook)
|
||||
- @pre-validate
|
||||
- @validate
|
||||
- @post-validate
|
||||
- [Command](#command-hook)
|
||||
- @pre-command
|
||||
- @command
|
||||
- @command-init
|
||||
- [Process](#process-hook)
|
||||
- @pre-process
|
||||
- @process
|
||||
- @post-process
|
||||
- [Alter](#alter-hook)
|
||||
- @pre-alter
|
||||
- @alter
|
||||
- @post-alter
|
||||
- [Status](#status-hook)
|
||||
- @status
|
||||
- [Extract](#extract-hook)
|
||||
- @extract
|
||||
|
||||
In addition to these, there are two more hooks available:
|
||||
|
||||
- [On-event](#on-event-hook)
|
||||
- @on-event
|
||||
- [Replace Command](#replace-command-hook)
|
||||
- @replace-command
|
||||
|
||||
The "pre" and "post" varieties of these hooks, where avalable, give more flexibility vis-a-vis hook ordering (and for consistency). Within one type of hook, the running order is undefined and not guaranteed. Note that many validate, process and alter hooks may run, but the first status or extract hook that successfully returns a result will halt processing of further hooks of the same type.
|
||||
|
||||
Each hook has an interface that defines its calling conventions; however, any callable may be used when registering a hook, which is convenient if versions of PHP prior to 7.0 (with no anonymous classes) need to be supported.
|
||||
|
||||
### Command Event Hook
|
||||
|
||||
The command-event hook is called via the Symfony Console command event notification callback mechanism. This happens prior to event dispatching and command / option validation. Note that Symfony does not allow the $input object to be altered in this hook; any change made here will be reset, as Symfony re-parses the object. Changes to arguments and options should be done in the initialize hook (non-interactive alterations) or the interact hook (which is naturally for interactive alterations).
|
||||
|
||||
### Option Event Hook
|
||||
|
||||
The option event hook ([OptionHookInterface](src/Hooks/OptionHookInterface.php)) is called for a specific command, whenever it is executed, or its help command is called. Any additional options for the command may be added here by calling the `addOption` method of the provided `$command` object. Note that the option hook is only necessary for calculating dynamic options. Static options may be added via the @option annotation on any hook that uses them. See the [Alter Hook](https://github.com/consolidation/annotated-command#alter-hook) documentation below for an example.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/**
|
||||
* @hook option some:command
|
||||
*/
|
||||
public function additionalOption(Command $command, AnnotationData $annotationData)
|
||||
{
|
||||
$command->addOption(
|
||||
'dynamic',
|
||||
'',
|
||||
InputOption::VALUE_NONE,
|
||||
'Option added by @hook option some:command'
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Initialize Hook
|
||||
|
||||
The initialize hook ([InitializeHookInterface](src/Hooks/InitializeHookInterface.php)) runs prior to the interact hook. It may supply command arguments and options from a configuration file or other sources. It should never do any user interaction.
|
||||
|
||||
The [consolidation/config](https://github.com/consolidation/config) project (which is used in [Robo PHP](https://github.com/consolidation/robo)) uses `@hook init` to automatically inject values from `config.yml` configuration files for options that were not provided on the command line.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* @hook init some:command
|
||||
*/
|
||||
public function initSomeCommand(InputInterface $input, AnnotationData $annotationData)
|
||||
{
|
||||
$value = $input->getOption('some-option');
|
||||
if (!$value) {
|
||||
$input->setOption('some-option', $this->generateRandomOptionValue());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* @hook interact some:command
|
||||
*/
|
||||
public function interact(InputInterface $input, OutputInterface $output, AnnotationData $annotationData)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
// If the user did not specify a password, then prompt for one.
|
||||
$password = $input->getOption('password');
|
||||
if (empty($password)) {
|
||||
$password = $io->askHidden("Enter a password:", function ($value) { return $value; });
|
||||
$input->setOption('password', $password);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Validate Hook
|
||||
|
||||
The purpose of the validate hook ([ValidatorInterface](src/Hooks/ValidatorInterface.php)) is to ensure the state of the targets of the current command are usabe in the context required by that command. Symfony has already validated the arguments and options prior to this hook. It is possible to alter the values of the arguments and options if necessary, although this is better done in the configure hook. A validation hook may take one of several actions:
|
||||
|
||||
- Do nothing. This indicates that validation succeeded.
|
||||
- Return a CommandError. Validation fails, and execution stops. The CommandError contains a status result code and a message, which is printed.
|
||||
- Throw an exception. The exception is converted into a CommandError.
|
||||
- Return false. Message is empty, and status is 1. Deprecated.
|
||||
|
||||
The validate hook may change the arguments and options of the command by modifying the Input object in the provided CommandData parameter. Any number of validation hooks may run, but if any fails, then execution of the command stops.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* @hook validate some:command
|
||||
*/
|
||||
public function validatePassword(CommandData $commandData)
|
||||
{
|
||||
$input = $commandData->input();
|
||||
$password = $input->getOption('password');
|
||||
|
||||
if (strpbrk($password, '!;$`') === false) {
|
||||
throw new \Exception("Your password MUST contain at least one of the characters ! ; ` or $, for no rational reason whatsoever.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Command Hook
|
||||
|
||||
The command hook is provided for semantic purposes. The pre-command and command hooks are equivalent to the post-validate hook, and should confirm to the interface ([ValidatorInterface](src/Hooks/ValidatorInterface.php)). All of the post-validate hooks will be called before the first pre-command hook is called. Similarly, the post-command hook is equivalent to the pre-process hook, and should implement the interface ([ProcessResultInterface](src/Hooks/ProcessResultInterface.php)).
|
||||
|
||||
The command callback itself (the method annotated @command) is called after the last command hook, and prior to the first post-command hook.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* @hook pre-command some:command
|
||||
*/
|
||||
public function preCommand(CommandData $commandData)
|
||||
{
|
||||
// Do something before some:command
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook post-command some:command
|
||||
*/
|
||||
public function postCommand($result, CommandData $commandData)
|
||||
{
|
||||
// Do something after some:command
|
||||
}
|
||||
```
|
||||
|
||||
### Process Hook
|
||||
|
||||
The process hook ([ProcessResultInterface](src/Hooks/ProcessResultInterface.php)) is specifically designed to convert a series of processing instructions into a final result. An example of this is implemented in Robo in the [CollectionProcessHook](https://github.com/consolidation/Robo/blob/master/src/Collection/CollectionProcessHook.php) class; if a Robo command returns a TaskInterface, then a Robo process hook will execute the task and return the result. This allows a pre-process hook to alter the task, e.g. by adding more operations to a task collection.
|
||||
|
||||
The process hook should not be used for other purposes.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* @hook process some:command
|
||||
*/
|
||||
public function process($result, CommandData $commandData)
|
||||
{
|
||||
if ($result instanceof MyInterimType) {
|
||||
$result = $this->convertInterimResult($result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Alter Hook
|
||||
|
||||
An alter hook ([AlterResultInterface](src/Hooks/AlterResultInterface.php)) changes the result object. Alter hooks should only operate on result objects of a type they explicitly recognize. They may return an object of the same type, or they may convert the object to some other type.
|
||||
|
||||
If something goes wrong, and the alter hooks wishes to force the command to fail, then it may either return a CommandError object, or throw an exception.
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* Demonstrate an alter hook with an option
|
||||
*
|
||||
* @hook alter some:command
|
||||
* @option $alteration Alter the result of the command in some way.
|
||||
* @usage some:command --alteration
|
||||
*/
|
||||
public function alterSomeCommand($result, CommandData $commandData)
|
||||
{
|
||||
if ($commandData->input()->getOption('alteration')) {
|
||||
$result[] = $this->getOneMoreRow();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
```
|
||||
|
||||
If an option needs to be provided with a default value, that may be done via the `@default` annotation.
|
||||
|
||||
```
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* Demonstrate an alter hook with an option that has a default value
|
||||
*
|
||||
* @hook alter some:command
|
||||
* @option $name Give the result a name.
|
||||
* @default $name George
|
||||
* @usage some:command --name=George
|
||||
*/
|
||||
public function nameSomeCommand($result, CommandData $commandData)
|
||||
{
|
||||
$result['name'] = $commandData->input()->getOption('name')
|
||||
|
||||
return $result;
|
||||
}
|
||||
```
|
||||
|
||||
### Status Hook
|
||||
|
||||
The status hook ([StatusDeterminerInterface](src/Hooks/StatusDeterminerInterface.php)) is responsible for determing whether a command succeeded (status code 0) or failed (status code > 0). The result object returned by a command may be a compound object that contains multiple bits of information about the command result. If the result object implements [ExitCodeInterface](ExitCodeInterface.php), then the `getExitCode()` method of the result object is called to determine what the status result code for the command should be. If ExitCodeInterface is not implemented, then all of the status hooks attached to this command are executed; the first one that successfully returns a result will stop further execution of status hooks, and the result it returned will be used as the status result code for this operation.
|
||||
|
||||
If no status hook returns any result, then success is presumed.
|
||||
|
||||
### Extract Hook
|
||||
|
||||
The extract hook ([ExtractOutputInterface](src/Hooks/ExtractOutputInterface.php)) is responsible for determining what the actual rendered output for the command should be. The result object returned by a command may be a compound object that contains multiple bits of information about the command result. If the result object implements [OutputDataInterface](OutputDataInterface.php), then the `getOutputData()` method of the result object is called to determine what information should be displayed to the user as a result of the command's execution. If OutputDataInterface is not implemented, then all of the extract hooks attached to this command are executed; the first one that successfully returns output data will stop further execution of extract hooks.
|
||||
|
||||
If no extract hook returns any data, then the result object itself is printed if it is a string; otherwise, no output is emitted (other than any produced by the command itself).
|
||||
|
||||
### On-Event hook
|
||||
|
||||
Commands can define their own custom events; to do so, they need only implement the CustomEventAwareInterface, and use the CustomEventAwareTrait. Event handlers for each custom event can then be defined using the on-event hook.
|
||||
|
||||
A handler using an on-event hook looks something like the following:
|
||||
```
|
||||
/**
|
||||
* @hook on-event custom-event
|
||||
*/
|
||||
public function handlerForCustomEvent(/* arbitrary parameters, as defined by custom-event */)
|
||||
{
|
||||
// do the needful, return what custom-event expects
|
||||
}
|
||||
```
|
||||
Then, to utilize this in a command:
|
||||
```
|
||||
class MyCommands implements CustomEventAwareInterface
|
||||
{
|
||||
use CustomEventAwareTrait;
|
||||
|
||||
/**
|
||||
* @command my-command
|
||||
*/
|
||||
public myCommand($options = [])
|
||||
{
|
||||
$handlers = $this->getCustomEventHandlers('custom-event');
|
||||
// iterate and call $handlers
|
||||
}
|
||||
}
|
||||
```
|
||||
It is up to the command that defines the custom event to declare what the expected parameters for the callback function should be, and what the return value is and how it should be used.
|
||||
|
||||
### Replace Command Hook
|
||||
|
||||
The replace-command ([ReplaceCommandHookInterface](src/Hooks/ReplaceCommandHookInterface.php)) hook permits you to replace a command's method with another method of your own.
|
||||
|
||||
For instance, if you'd like to replace the `foo:bar` command, you could utilize the following code:
|
||||
|
||||
```php
|
||||
<?php
|
||||
class MyReplaceCommandHook {
|
||||
|
||||
/**
|
||||
* @hook replace-command foo:bar
|
||||
*
|
||||
* Parameters must match original command method.
|
||||
*/
|
||||
public function myFooBarReplacement($value) {
|
||||
print "Hello $value!";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
If a command method returns an integer, it is used as the command exit status code. If the command method returns a string, it is printed.
|
||||
|
||||
If the [Consolidation/OutputFormatters](https://github.com/consolidation/output-formatters) project is used, then users may specify a --format option to select the formatter to use to transform the output from whatever form the command provides to a string. To make this work, the application must provide a formatter to the AnnotatedCommandFactory. See [API Usage](#api-usage) below.
|
||||
|
||||
## Logging
|
||||
|
||||
The Annotated-Command project is completely agnostic to logging. If a command wishes to log progress, then the CommandFile class should implement LoggerAwareInterface, and the Commandline tool should inject a logger for its use via the LoggerAwareTrait `setLogger()` method. Using [Robo](https://github.com/consolidation/robo) is recommended.
|
||||
|
||||
## Access to Symfony Objects
|
||||
|
||||
If you want to use annotations, but still want access to the Symfony Command, e.g. to get a reference to the helpers in order to call some legacy code, you may create an ordinary Symfony Command that extends \Consolidation\AnnotatedCommand\AnnotatedCommand, which is a \Symfony\Component\Console\Command\Command. Omit the configure method, and place your annotations on the `execute()` method.
|
||||
|
||||
It is also possible to add InputInterface and/or OutputInterface parameters to any annotated method of a command file (the parameters must go before command arguments).
|
||||
|
||||
## 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.
|
||||
|
||||
### Set up Command Factory and Instantiate Commands
|
||||
|
||||
To use annotated commands in an application, pass an instance of your command class in to AnnotatedCommandFactory::createCommandsFromClass(). The result will be a list of Commands that may be added to your application.
|
||||
```php
|
||||
$myCommandClassInstance = new MyCommandClass();
|
||||
$commandFactory = new AnnotatedCommandFactory();
|
||||
$commandFactory->setIncludeAllPublicMethods(true);
|
||||
$commandFactory->commandProcessor()->setFormatterManager(new FormatterManager());
|
||||
$commandList = $commandFactory->createCommandsFromClass($myCommandClassInstance);
|
||||
foreach ($commandList as $command) {
|
||||
$application->add($command);
|
||||
}
|
||||
```
|
||||
You may have more than one command class, if you wish. If so, simply call AnnotatedCommandFactory::createCommandsFromClass() multiple times.
|
||||
|
||||
If you do not wish every public method in your classes to be added as commands, use `AnnotatedCommandFactory::setIncludeAllPublicMethods(false)`, and only methods annotated with @command will become commands.
|
||||
|
||||
Note that the `setFormatterManager()` operation is optional; omit this if not using [Consolidation/OutputFormatters](https://github.com/consolidation/output-formatters).
|
||||
|
||||
A CommandInfoAltererInterface can be added via AnnotatedCommandFactory::addCommandInfoAlterer(); it will be given the opportunity to adjust every CommandInfo object parsed from a command file prior to the creation of commands.
|
||||
|
||||
### Command File Discovery
|
||||
|
||||
A discovery class, CommandFileDiscovery, is also provided to help find command files on the filesystem. Usage is as follows:
|
||||
```php
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$myCommandFiles = $discovery->discover($path, '\Drupal');
|
||||
foreach ($myCommandFiles as $myCommandClass) {
|
||||
$myCommandClassInstance = new $myCommandClass();
|
||||
// ... as above
|
||||
}
|
||||
```
|
||||
For a discussion on command file naming conventions and search locations, see https://github.com/consolidation/annotated-command/issues/12.
|
||||
|
||||
If different namespaces are used at different command file paths, change the call to discover as follows:
|
||||
```php
|
||||
$myCommandFiles = $discovery->discover(['\Ns1' => $path1, '\Ns2' => $path2]);
|
||||
```
|
||||
As a shortcut for the above, the method `discoverNamespaced()` will take the last directory name of each path, and append it to the base namespace provided. This matches the conventions used by Drupal modules, for example.
|
||||
|
||||
### Configuring Output Formatts (e.g. to enable wordwrap)
|
||||
|
||||
The Output Formatters project supports automatic formatting of tabular output. In order for wordwrapping to work correctly, the terminal width must be passed in to the Output Formatters handlers via `FormatterOptions::setWidth()`.
|
||||
|
||||
In the Annotated Commands project, this is done via dependency injection. If a `PrepareFormatter` object is passed to `CommandProcessor::addPrepareFormatter()`, then it will be given an opportunity to set properties on the `FormatterOptions` when it is created.
|
||||
|
||||
A `PrepareTerminalWidthOption` class is provided to use the Symfony Application class to fetch the terminal width, and provide it to the FormatterOptions. It is injected as follows:
|
||||
```php
|
||||
$terminalWidthOption = new PrepareTerminalWidthOption();
|
||||
$terminalWidthOption->setApplication($application);
|
||||
$commandFactory->commandProcessor()->addPrepareFormatter($terminalWidthOption);
|
||||
```
|
||||
To provide greater control over the width used, create your own `PrepareTerminalWidthOption` subclass, and adjust the width as needed.
|
||||
|
||||
## Other Callbacks
|
||||
|
||||
In addition to the hooks provided by the hook manager, there are additional callbacks available to alter the way the annotated command library operates.
|
||||
|
||||
### Factory Listeners
|
||||
|
||||
Factory listeners are notified every time a command file instance is used to create annotated commands.
|
||||
```
|
||||
public function AnnotatedCommandFactory::addListener(CommandCreationListenerInterface $listener);
|
||||
```
|
||||
Listeners can be used to construct command file instances as they are provided to the command factory.
|
||||
|
||||
### Option Providers
|
||||
|
||||
An option provider is given an opportunity to add options to a command as it is being constructed.
|
||||
```
|
||||
public function AnnotatedCommandFactory::addAutomaticOptionProvider(AutomaticOptionsProviderInterface $listener);
|
||||
```
|
||||
The complete CommandInfo record with all of the annotation data is available, so you can, for example, add an option `--foo` to every command whose method is annotated `@fooable`.
|
||||
|
||||
### CommandInfo Alterers
|
||||
|
||||
CommandInfo alterers can adjust information about a command immediately before it is created. Typically, these will be used to supply default values for annotations custom to the command, or take other actions based on the interfaces implemented by the commandfile instance.
|
||||
```
|
||||
public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance);
|
||||
```
|
||||
|
||||
## Comparison to Existing Solutions
|
||||
|
||||
The existing solutions used their own hand-rolled regex-based parsers to process the contents of the DocBlock comments. consolidation/annotated-command uses the [phpdocumentor/reflection-docblock](https://github.com/phpDocumentor/ReflectionDocBlock) project (which is itself a regex-based parser) to interpret DocBlock contents.
|
66
vendor/consolidation/annotated-command/appveyor.yml
vendored
Normal file
66
vendor/consolidation/annotated-command/appveyor.yml
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
build: false
|
||||
shallow_clone: true
|
||||
platform: 'x86'
|
||||
clone_folder: C:\projects\annotated-commands
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
## Cache composer bits
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\Composer\files -> composer.lock'
|
||||
|
||||
init:
|
||||
#https://github.com/composer/composer/blob/master/appveyor.yml
|
||||
#- SET ANSICON=121x90 (121x90)
|
||||
|
||||
# Inspired by https://github.com/Codeception/base/blob/master/appveyor.yml and https://github.com/phpmd/phpmd/blob/master/appveyor.yml
|
||||
install:
|
||||
- cinst -y curl
|
||||
- SET PATH=C:\Program Files\curl;%PATH%
|
||||
#which is only needed by the test suite.
|
||||
- cinst -y which
|
||||
- SET PATH=C:\Program Files\which;%PATH%
|
||||
- git clone -q https://github.com/acquia/DevDesktopCommon.git #For tar, cksum, ...
|
||||
- SET PATH=%APPVEYOR_BUILD_FOLDER%/DevDesktopCommon/bintools-win/msys/bin;%PATH%
|
||||
- SET PATH=C:\Program Files\MySql\MySQL Server 5.7\bin\;%PATH%
|
||||
#Install PHP per https://blog.wyrihaximus.net/2016/11/running-php-unit-tests-on-windows-using-appveyor-and-chocolatey/
|
||||
- ps: appveyor-retry cinst --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $Env:php_ver_target | Select-Object -first 1) -replace '[php|]','')
|
||||
- cd c:\tools\php70
|
||||
- copy php.ini-production php.ini
|
||||
|
||||
- echo extension_dir=ext >> php.ini
|
||||
- echo extension=php_openssl.dll >> php.ini
|
||||
- echo date.timezone="UTC" >> php.ini
|
||||
- echo variables_order="EGPCS" >> php.ini #May be unneeded.
|
||||
- echo mbstring.http_input=pass >> php.ini
|
||||
- echo mbstring.http_output=pass >> php.ini
|
||||
- echo sendmail_path=nul >> php.ini
|
||||
- echo extension=php_mbstring.dll >> php.ini
|
||||
- echo extension=php_curl.dll >> php.ini
|
||||
- echo extension=php_pdo_mysql.dll >> php.ini
|
||||
- echo extension=php_pdo_pgsql.dll >> php.ini
|
||||
- echo extension=php_pdo_sqlite.dll >> php.ini
|
||||
- echo extension=php_pgsql.dll >> php.ini
|
||||
- echo extension=php_gd2.dll >> php.ini
|
||||
- SET PATH=C:\tools\php70;%PATH%
|
||||
#Install Composer
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
#- appveyor DownloadFile https://getcomposer.org/composer.phar
|
||||
- php -r "readfile('http://getcomposer.org/installer');" | php
|
||||
#Install dependencies via Composer
|
||||
- php composer.phar -q install --prefer-dist -n
|
||||
- SET PATH=%APPVEYOR_BUILD_FOLDER%;%APPVEYOR_BUILD_FOLDER%/vendor/bin;%PATH%
|
||||
#Create a sandbox for testing. Don't think we need this.
|
||||
- mkdir c:\test_temp
|
||||
|
||||
test_script:
|
||||
- phpunit
|
||||
- php composer.phar cs
|
||||
|
||||
# environment variables
|
||||
environment:
|
||||
global:
|
||||
SHELL_INTERACTIVE: true
|
||||
php_ver_target: 7.0
|
||||
|
56
vendor/consolidation/annotated-command/composer.json
vendored
Normal file
56
vendor/consolidation/annotated-command/composer.json
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "consolidation/annotated-command",
|
||||
"description": "Initialize Symfony Console commands from annotated command class methods.",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Greg Anderson",
|
||||
"email": "greg.1.anderson@greenknowe.org"
|
||||
}
|
||||
],
|
||||
"autoload":{
|
||||
"psr-4":{
|
||||
"Consolidation\\AnnotatedCommand\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Consolidation\\TestUtils\\": "tests/src"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"consolidation/output-formatters": "^3.1.12",
|
||||
"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",
|
||||
"satooshi/php-coveralls": "^1.0.2 | dev-master",
|
||||
"squizlabs/php_codesniffer": "^2.7"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"platform": {
|
||||
"php": "5.6"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"cs": "phpcs --standard=PSR2 -n src",
|
||||
"cbf": "phpcbf --standard=PSR2 -n src",
|
||||
"unit": "SHELL_INTERACTIVE=true phpunit --colors=always",
|
||||
"test": [
|
||||
"@unit",
|
||||
"@cs"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
2085
vendor/consolidation/annotated-command/composer.lock
generated
vendored
Normal file
2085
vendor/consolidation/annotated-command/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
11
vendor/consolidation/annotated-command/infection.json.dist
vendored
Normal file
11
vendor/consolidation/annotated-command/infection.json.dist
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"timeout": 10,
|
||||
"source": {
|
||||
"directories": [
|
||||
"src"
|
||||
]
|
||||
},
|
||||
"logs": {
|
||||
"text": "infection-log.txt"
|
||||
}
|
||||
}
|
19
vendor/consolidation/annotated-command/phpunit.xml.dist
vendored
Normal file
19
vendor/consolidation/annotated-command/phpunit.xml.dist
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
<phpunit bootstrap="vendor/autoload.php" colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="annotation-command">
|
||||
<directory prefix="test" suffix=".php">tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<logging>
|
||||
<!--
|
||||
<log type="coverage-html" target="build/logs/coverage" lowUpperBound="35"
|
||||
highLowerBound="70"/>
|
||||
-->
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
</logging>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
452
vendor/consolidation/annotated-command/src/AnnotatedCommand.php
vendored
Normal file
452
vendor/consolidation/annotated-command/src/AnnotatedCommand.php
vendored
Normal file
|
@ -0,0 +1,452 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\AnnotatedCommand\Help\HelpDocumentAlter;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* AnnotatedCommands are created automatically by the
|
||||
* AnnotatedCommandFactory. Each command method in a
|
||||
* command file will produce one AnnotatedCommand. These
|
||||
* are then added to your Symfony Console Application object;
|
||||
* nothing else is needed.
|
||||
*
|
||||
* Optionally, though, you may extend AnnotatedCommand directly
|
||||
* to make a single command. The usage pattern is the same
|
||||
* as for any other Symfony Console command, except that you may
|
||||
* omit the 'Confiure' method, and instead place your annotations
|
||||
* on the execute() method.
|
||||
*
|
||||
* @package Consolidation\AnnotatedCommand
|
||||
*/
|
||||
class AnnotatedCommand extends Command implements HelpDocumentAlter
|
||||
{
|
||||
protected $commandCallback;
|
||||
protected $commandProcessor;
|
||||
protected $annotationData;
|
||||
protected $examples = [];
|
||||
protected $topics = [];
|
||||
protected $usesInputInterface;
|
||||
protected $usesOutputInterface;
|
||||
protected $returnType;
|
||||
|
||||
public function __construct($name = null)
|
||||
{
|
||||
$commandInfo = false;
|
||||
|
||||
// If this is a subclass of AnnotatedCommand, check to see
|
||||
// if the 'execute' method is annotated. We could do this
|
||||
// unconditionally; it is a performance optimization to skip
|
||||
// checking the annotations if $this is an instance of
|
||||
// AnnotatedCommand. Alternately, we break out a new subclass.
|
||||
// The command factory instantiates the subclass.
|
||||
if (get_class($this) != 'Consolidation\AnnotatedCommand\AnnotatedCommand') {
|
||||
$commandInfo = CommandInfo::create($this, 'execute');
|
||||
if (!isset($name)) {
|
||||
$name = $commandInfo->getName();
|
||||
}
|
||||
}
|
||||
parent::__construct($name);
|
||||
if ($commandInfo && $commandInfo->hasAnnotation('command')) {
|
||||
$this->setCommandInfo($commandInfo);
|
||||
$this->setCommandOptions($commandInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public function setCommandCallback($commandCallback)
|
||||
{
|
||||
$this->commandCallback = $commandCallback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCommandProcessor($commandProcessor)
|
||||
{
|
||||
$this->commandProcessor = $commandProcessor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function commandProcessor()
|
||||
{
|
||||
// If someone is using an AnnotatedCommand, and is NOT getting
|
||||
// it from an AnnotatedCommandFactory OR not correctly injecting
|
||||
// a command processor via setCommandProcessor() (ideally via the
|
||||
// DI container), then we'll just give each annotated command its
|
||||
// own command processor. This is not ideal; preferably, there would
|
||||
// only be one instance of the command processor in the application.
|
||||
if (!isset($this->commandProcessor)) {
|
||||
$this->commandProcessor = new CommandProcessor(new HookManager());
|
||||
}
|
||||
return $this->commandProcessor;
|
||||
}
|
||||
|
||||
public function getReturnType()
|
||||
{
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
public function setReturnType($returnType)
|
||||
{
|
||||
$this->returnType = $returnType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAnnotationData()
|
||||
{
|
||||
return $this->annotationData;
|
||||
}
|
||||
|
||||
public function setAnnotationData($annotationData)
|
||||
{
|
||||
$this->annotationData = $annotationData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTopics()
|
||||
{
|
||||
return $this->topics;
|
||||
}
|
||||
|
||||
public function setTopics($topics)
|
||||
{
|
||||
$this->topics = $topics;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCommandInfo($commandInfo)
|
||||
{
|
||||
$this->setDescription($commandInfo->getDescription());
|
||||
$this->setHelp($commandInfo->getHelp());
|
||||
$this->setAliases($commandInfo->getAliases());
|
||||
$this->setAnnotationData($commandInfo->getAnnotations());
|
||||
$this->setTopics($commandInfo->getTopics());
|
||||
foreach ($commandInfo->getExampleUsages() as $usage => $description) {
|
||||
$this->addUsageOrExample($usage, $description);
|
||||
}
|
||||
$this->setCommandArguments($commandInfo);
|
||||
$this->setReturnType($commandInfo->getReturnType());
|
||||
// Hidden commands available since Symfony 3.2
|
||||
// http://symfony.com/doc/current/console/hide_commands.html
|
||||
if (method_exists($this, 'setHidden')) {
|
||||
$this->setHidden($commandInfo->getHidden());
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExampleUsages()
|
||||
{
|
||||
return $this->examples;
|
||||
}
|
||||
|
||||
protected function addUsageOrExample($usage, $description)
|
||||
{
|
||||
$this->addUsage($usage);
|
||||
if (!empty($description)) {
|
||||
$this->examples[$usage] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected function setCommandArguments($commandInfo)
|
||||
{
|
||||
$this->setUsesInputInterface($commandInfo);
|
||||
$this->setUsesOutputInterface($commandInfo);
|
||||
$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();
|
||||
foreach ($args as $name => $defaultValue) {
|
||||
$description = $commandInfo->arguments()->getDescription($name);
|
||||
$hasDefault = $commandInfo->arguments()->hasDefault($name);
|
||||
$parameterMode = $this->getCommandArgumentMode($hasDefault, $defaultValue);
|
||||
$this->addArgument($name, $parameterMode, $description, $defaultValue);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getCommandArgumentMode($hasDefault, $defaultValue)
|
||||
{
|
||||
if (!$hasDefault) {
|
||||
return InputArgument::REQUIRED;
|
||||
}
|
||||
if (is_array($defaultValue)) {
|
||||
return InputArgument::IS_ARRAY;
|
||||
}
|
||||
return InputArgument::OPTIONAL;
|
||||
}
|
||||
|
||||
public function setCommandOptions($commandInfo, $automaticOptions = [])
|
||||
{
|
||||
$inputOptions = $commandInfo->inputOptions();
|
||||
|
||||
$this->addOptions($inputOptions + $automaticOptions, $automaticOptions);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addOptions($inputOptions, $automaticOptions = [])
|
||||
{
|
||||
foreach ($inputOptions as $name => $inputOption) {
|
||||
$description = $inputOption->getDescription();
|
||||
|
||||
if (empty($description) && isset($automaticOptions[$name])) {
|
||||
$description = $automaticOptions[$name]->getDescription();
|
||||
$inputOption = static::inputOptionSetDescription($inputOption, $description);
|
||||
}
|
||||
$this->getDefinition()->addOption($inputOption);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function inputOptionSetDescription($inputOption, $description)
|
||||
{
|
||||
// Recover the 'mode' value, because Symfony is stubborn
|
||||
$mode = 0;
|
||||
if ($inputOption->isValueRequired()) {
|
||||
$mode |= InputOption::VALUE_REQUIRED;
|
||||
}
|
||||
if ($inputOption->isValueOptional()) {
|
||||
$mode |= InputOption::VALUE_OPTIONAL;
|
||||
}
|
||||
if ($inputOption->isArray()) {
|
||||
$mode |= InputOption::VALUE_IS_ARRAY;
|
||||
}
|
||||
if (!$mode) {
|
||||
$mode = InputOption::VALUE_NONE;
|
||||
}
|
||||
|
||||
$inputOption = new InputOption(
|
||||
$inputOption->getName(),
|
||||
$inputOption->getShortcut(),
|
||||
$mode,
|
||||
$description,
|
||||
$inputOption->getDefault()
|
||||
);
|
||||
return $inputOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the hook names that may be called for this command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNames()
|
||||
{
|
||||
return HookManager::getNames($this, $this->commandCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any options to this command that are defined by hook implementations
|
||||
*/
|
||||
public function optionsHook()
|
||||
{
|
||||
$this->commandProcessor()->optionsHook(
|
||||
$this,
|
||||
$this->getNames(),
|
||||
$this->annotationData
|
||||
);
|
||||
}
|
||||
|
||||
public function optionsHookForHookAnnotations($commandInfoList)
|
||||
{
|
||||
foreach ($commandInfoList as $commandInfo) {
|
||||
$inputOptions = $commandInfo->inputOptions();
|
||||
$this->addOptions($inputOptions);
|
||||
foreach ($commandInfo->getExampleUsages() as $usage => $description) {
|
||||
if (!in_array($usage, $this->getUsages())) {
|
||||
$this->addUsageOrExample($usage, $description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->commandProcessor()->interact(
|
||||
$input,
|
||||
$output,
|
||||
$this->getNames(),
|
||||
$this->annotationData
|
||||
);
|
||||
}
|
||||
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// Allow the hook manager a chance to provide configuration values,
|
||||
// if there are any registered hooks to do that.
|
||||
$this->commandProcessor()->initializeHook($input, $this->getNames(), $this->annotationData);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// Validate, run, process, alter, handle results.
|
||||
return $this->commandProcessor()->process(
|
||||
$output,
|
||||
$this->getNames(),
|
||||
$this->commandCallback,
|
||||
$this->createCommandData($input, $output)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is available for use by a class that may
|
||||
* wish to extend this class rather than use annotations to
|
||||
* define commands. Using this technique does allow for the
|
||||
* use of annotations to define hooks.
|
||||
*/
|
||||
public function processResults(InputInterface $input, OutputInterface $output, $results)
|
||||
{
|
||||
$commandData = $this->createCommandData($input, $output);
|
||||
$commandProcessor = $this->commandProcessor();
|
||||
$names = $this->getNames();
|
||||
$results = $commandProcessor->processResults(
|
||||
$names,
|
||||
$results,
|
||||
$commandData
|
||||
);
|
||||
return $commandProcessor->handleResults(
|
||||
$output,
|
||||
$names,
|
||||
$results,
|
||||
$commandData
|
||||
);
|
||||
}
|
||||
|
||||
protected function createCommandData(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$commandData = new CommandData(
|
||||
$this->annotationData,
|
||||
$input,
|
||||
$output
|
||||
);
|
||||
|
||||
$commandData->setUseIOInterfaces(
|
||||
$this->usesInputInterface,
|
||||
$this->usesOutputInterface
|
||||
);
|
||||
|
||||
// Allow the commandData to cache the list of options with
|
||||
// special default values ('null' and 'true'), as these will
|
||||
// need special handling. @see CommandData::options().
|
||||
$commandData->cacheSpecialDefaults($this->getDefinition());
|
||||
|
||||
return $commandData;
|
||||
}
|
||||
}
|
458
vendor/consolidation/annotated-command/src/AnnotatedCommandFactory.php
vendored
Normal file
458
vendor/consolidation/annotated-command/src/AnnotatedCommandFactory.php
vendored
Normal file
|
@ -0,0 +1,458 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Cache\CacheWrapper;
|
||||
use Consolidation\AnnotatedCommand\Cache\NullCache;
|
||||
use Consolidation\AnnotatedCommand\Cache\SimpleCacheInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Options\AutomaticOptionsProviderInterface;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfoDeserializer;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfoSerializer;
|
||||
use Consolidation\OutputFormatters\Options\FormatterOptions;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* The AnnotatedCommandFactory creates commands for your application.
|
||||
* Use with a Dependency Injection Container and the CommandFactory.
|
||||
* Alternately, use the CommandFileDiscovery to find commandfiles, and
|
||||
* then use AnnotatedCommandFactory::createCommandsFromClass() to create
|
||||
* commands. See the README for more information.
|
||||
*
|
||||
* @package Consolidation\AnnotatedCommand
|
||||
*/
|
||||
class AnnotatedCommandFactory implements AutomaticOptionsProviderInterface
|
||||
{
|
||||
/** var CommandProcessor */
|
||||
protected $commandProcessor;
|
||||
|
||||
/** var CommandCreationListenerInterface[] */
|
||||
protected $listeners = [];
|
||||
|
||||
/** var AutomaticOptionsProvider[] */
|
||||
protected $automaticOptionsProviderList = [];
|
||||
|
||||
/** var boolean */
|
||||
protected $includeAllPublicMethods = true;
|
||||
|
||||
/** var CommandInfoAltererInterface */
|
||||
protected $commandInfoAlterers = [];
|
||||
|
||||
/** var SimpleCacheInterface */
|
||||
protected $dataStore;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dataStore = new NullCache();
|
||||
$this->commandProcessor = new CommandProcessor(new HookManager());
|
||||
$this->addAutomaticOptionProvider($this);
|
||||
}
|
||||
|
||||
public function setCommandProcessor(CommandProcessor $commandProcessor)
|
||||
{
|
||||
$this->commandProcessor = $commandProcessor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CommandProcessor
|
||||
*/
|
||||
public function commandProcessor()
|
||||
{
|
||||
return $this->commandProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'include all public methods flag'. If true (the default), then
|
||||
* every public method of each commandFile will be used to create commands.
|
||||
* If it is false, then only those public methods annotated with @command
|
||||
* or @name (deprecated) will be used to create commands.
|
||||
*/
|
||||
public function setIncludeAllPublicMethods($includeAllPublicMethods)
|
||||
{
|
||||
$this->includeAllPublicMethods = $includeAllPublicMethods;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIncludeAllPublicMethods()
|
||||
{
|
||||
return $this->includeAllPublicMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HookManager
|
||||
*/
|
||||
public function hookManager()
|
||||
{
|
||||
return $this->commandProcessor()->hookManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener that is notified immediately before the command
|
||||
* factory creates commands from a commandFile instance. This
|
||||
* listener can use this opportunity to do more setup for the commandFile,
|
||||
* and so on.
|
||||
*
|
||||
* @param CommandCreationListenerInterface $listener
|
||||
*/
|
||||
public function addListener(CommandCreationListenerInterface $listener)
|
||||
{
|
||||
$this->listeners[] = $listener;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener that's just a simple 'callable'.
|
||||
* @param callable $listener
|
||||
*/
|
||||
public function addListernerCallback(callable $listener)
|
||||
{
|
||||
$this->addListener(new CommandCreationListener($listener));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call all command creation listeners
|
||||
*
|
||||
* @param object $commandFileInstance
|
||||
*/
|
||||
protected function notify($commandFileInstance)
|
||||
{
|
||||
foreach ($this->listeners as $listener) {
|
||||
$listener->notifyCommandFileAdded($commandFileInstance);
|
||||
}
|
||||
}
|
||||
|
||||
public function addAutomaticOptionProvider(AutomaticOptionsProviderInterface $optionsProvider)
|
||||
{
|
||||
$this->automaticOptionsProviderList[] = $optionsProvider;
|
||||
}
|
||||
|
||||
public function addCommandInfoAlterer(CommandInfoAltererInterface $alterer)
|
||||
{
|
||||
$this->commandInfoAlterers[] = $alterer;
|
||||
}
|
||||
|
||||
/**
|
||||
* n.b. This registers all hooks from the commandfile instance as a side-effect.
|
||||
*/
|
||||
public function createCommandsFromClass($commandFileInstance, $includeAllPublicMethods = null)
|
||||
{
|
||||
// Deprecated: avoid using the $includeAllPublicMethods in favor of the setIncludeAllPublicMethods() accessor.
|
||||
if (!isset($includeAllPublicMethods)) {
|
||||
$includeAllPublicMethods = $this->getIncludeAllPublicMethods();
|
||||
}
|
||||
$this->notify($commandFileInstance);
|
||||
$commandInfoList = $this->getCommandInfoListFromClass($commandFileInstance);
|
||||
$this->registerCommandHooksFromClassInfo($commandInfoList, $commandFileInstance);
|
||||
return $this->createCommandsFromClassInfo($commandInfoList, $commandFileInstance, $includeAllPublicMethods);
|
||||
}
|
||||
|
||||
public function getCommandInfoListFromClass($commandFileInstance)
|
||||
{
|
||||
$cachedCommandInfoList = $this->getCommandInfoListFromCache($commandFileInstance);
|
||||
$commandInfoList = $this->createCommandInfoListFromClass($commandFileInstance, $cachedCommandInfoList);
|
||||
if (!empty($commandInfoList)) {
|
||||
$cachedCommandInfoList = array_merge($commandInfoList, $cachedCommandInfoList);
|
||||
$this->storeCommandInfoListInCache($commandFileInstance, $cachedCommandInfoList);
|
||||
}
|
||||
return $cachedCommandInfoList;
|
||||
}
|
||||
|
||||
protected function storeCommandInfoListInCache($commandFileInstance, $commandInfoList)
|
||||
{
|
||||
if (!$this->hasDataStore()) {
|
||||
return;
|
||||
}
|
||||
$cache_data = [];
|
||||
$serializer = new CommandInfoSerializer();
|
||||
foreach ($commandInfoList as $i => $commandInfo) {
|
||||
$cache_data[$i] = $serializer->serialize($commandInfo);
|
||||
}
|
||||
$className = get_class($commandFileInstance);
|
||||
$this->getDataStore()->set($className, $cache_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command info list from the cache
|
||||
*
|
||||
* @param mixed $commandFileInstance
|
||||
* @return array
|
||||
*/
|
||||
protected function getCommandInfoListFromCache($commandFileInstance)
|
||||
{
|
||||
$commandInfoList = [];
|
||||
$className = get_class($commandFileInstance);
|
||||
if (!$this->getDataStore()->has($className)) {
|
||||
return [];
|
||||
}
|
||||
$deserializer = new CommandInfoDeserializer();
|
||||
|
||||
$cache_data = $this->getDataStore()->get($className);
|
||||
foreach ($cache_data as $i => $data) {
|
||||
if (CommandInfoDeserializer::isValidSerializedData((array)$data)) {
|
||||
$commandInfoList[$i] = $deserializer->deserialize((array)$data);
|
||||
}
|
||||
}
|
||||
return $commandInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if this factory has a cache datastore.
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasDataStore()
|
||||
{
|
||||
return !($this->dataStore instanceof NullCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cache datastore for this factory. Any object with 'set' and
|
||||
* 'get' methods is acceptable. The key is the classname being cached,
|
||||
* and the value is a nested associative array of strings.
|
||||
*
|
||||
* TODO: Typehint this to SimpleCacheInterface
|
||||
*
|
||||
* This is not done currently to allow clients to use a generic cache
|
||||
* store that does not itself depend on the annotated-command library.
|
||||
*
|
||||
* @param Mixed $dataStore
|
||||
* @return type
|
||||
*/
|
||||
public function setDataStore($dataStore)
|
||||
{
|
||||
if (!($dataStore instanceof SimpleCacheInterface)) {
|
||||
$dataStore = new CacheWrapper($dataStore);
|
||||
}
|
||||
$this->dataStore = $dataStore;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data store attached to this factory.
|
||||
*/
|
||||
public function getDataStore()
|
||||
{
|
||||
return $this->dataStore;
|
||||
}
|
||||
|
||||
protected function createCommandInfoListFromClass($classNameOrInstance, $cachedCommandInfoList)
|
||||
{
|
||||
$commandInfoList = [];
|
||||
|
||||
// Ignore special functions, such as __construct and __call, which
|
||||
// can never be commands.
|
||||
$commandMethodNames = array_filter(
|
||||
get_class_methods($classNameOrInstance) ?: [],
|
||||
function ($m) use ($classNameOrInstance) {
|
||||
$reflectionMethod = new \ReflectionMethod($classNameOrInstance, $m);
|
||||
return !$reflectionMethod->isStatic() && !preg_match('#^_#', $m);
|
||||
}
|
||||
);
|
||||
|
||||
foreach ($commandMethodNames as $commandMethodName) {
|
||||
if (!array_key_exists($commandMethodName, $cachedCommandInfoList)) {
|
||||
$commandInfo = CommandInfo::create($classNameOrInstance, $commandMethodName);
|
||||
if (!static::isCommandOrHookMethod($commandInfo, $this->getIncludeAllPublicMethods())) {
|
||||
$commandInfo->invalidate();
|
||||
}
|
||||
$commandInfoList[$commandMethodName] = $commandInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return $commandInfoList;
|
||||
}
|
||||
|
||||
public function createCommandInfo($classNameOrInstance, $commandMethodName)
|
||||
{
|
||||
return CommandInfo::create($classNameOrInstance, $commandMethodName);
|
||||
}
|
||||
|
||||
public function createCommandsFromClassInfo($commandInfoList, $commandFileInstance, $includeAllPublicMethods = null)
|
||||
{
|
||||
// Deprecated: avoid using the $includeAllPublicMethods in favor of the setIncludeAllPublicMethods() accessor.
|
||||
if (!isset($includeAllPublicMethods)) {
|
||||
$includeAllPublicMethods = $this->getIncludeAllPublicMethods();
|
||||
}
|
||||
return $this->createSelectedCommandsFromClassInfo(
|
||||
$commandInfoList,
|
||||
$commandFileInstance,
|
||||
function ($commandInfo) use ($includeAllPublicMethods) {
|
||||
return static::isCommandMethod($commandInfo, $includeAllPublicMethods);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function createSelectedCommandsFromClassInfo($commandInfoList, $commandFileInstance, callable $commandSelector)
|
||||
{
|
||||
$commandInfoList = $this->filterCommandInfoList($commandInfoList, $commandSelector);
|
||||
return array_map(
|
||||
function ($commandInfo) use ($commandFileInstance) {
|
||||
return $this->createCommand($commandInfo, $commandFileInstance);
|
||||
},
|
||||
$commandInfoList
|
||||
);
|
||||
}
|
||||
|
||||
protected function filterCommandInfoList($commandInfoList, callable $commandSelector)
|
||||
{
|
||||
return array_filter($commandInfoList, $commandSelector);
|
||||
}
|
||||
|
||||
public static function isCommandOrHookMethod($commandInfo, $includeAllPublicMethods)
|
||||
{
|
||||
return static::isHookMethod($commandInfo) || static::isCommandMethod($commandInfo, $includeAllPublicMethods);
|
||||
}
|
||||
|
||||
public static function isHookMethod($commandInfo)
|
||||
{
|
||||
return $commandInfo->hasAnnotation('hook');
|
||||
}
|
||||
|
||||
public static function isCommandMethod($commandInfo, $includeAllPublicMethods)
|
||||
{
|
||||
// Ignore everything labeled @hook
|
||||
if (static::isHookMethod($commandInfo)) {
|
||||
return false;
|
||||
}
|
||||
// Include everything labeled @command
|
||||
if ($commandInfo->hasAnnotation('command')) {
|
||||
return true;
|
||||
}
|
||||
// Skip anything that has a missing or invalid name.
|
||||
$commandName = $commandInfo->getName();
|
||||
if (empty($commandName) || preg_match('#[^a-zA-Z0-9:_-]#', $commandName)) {
|
||||
return false;
|
||||
}
|
||||
// Skip anything named like an accessor ('get' or 'set')
|
||||
if (preg_match('#^(get[A-Z]|set[A-Z])#', $commandInfo->getMethodName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Default to the setting of 'include all public methods'.
|
||||
return $includeAllPublicMethods;
|
||||
}
|
||||
|
||||
public function registerCommandHooksFromClassInfo($commandInfoList, $commandFileInstance)
|
||||
{
|
||||
foreach ($commandInfoList as $commandInfo) {
|
||||
if (static::isHookMethod($commandInfo)) {
|
||||
$this->registerCommandHook($commandInfo, $commandFileInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a command hook given the CommandInfo for a method.
|
||||
*
|
||||
* The hook format is:
|
||||
*
|
||||
* @hook type name type
|
||||
*
|
||||
* For example, the pre-validate hook for the core:init command is:
|
||||
*
|
||||
* @hook pre-validate core:init
|
||||
*
|
||||
* If no command name is provided, then this hook will affect every
|
||||
* command that is defined in the same file.
|
||||
*
|
||||
* If no hook is provided, then we will presume that ALTER_RESULT
|
||||
* is intended.
|
||||
*
|
||||
* @param CommandInfo $commandInfo Information about the command hook method.
|
||||
* @param object $commandFileInstance An instance of the CommandFile class.
|
||||
*/
|
||||
public function registerCommandHook(CommandInfo $commandInfo, $commandFileInstance)
|
||||
{
|
||||
// Ignore if the command info has no @hook
|
||||
if (!static::isHookMethod($commandInfo)) {
|
||||
return;
|
||||
}
|
||||
$hookData = $commandInfo->getAnnotation('hook');
|
||||
$hook = $this->getNthWord($hookData, 0, HookManager::ALTER_RESULT);
|
||||
$commandName = $this->getNthWord($hookData, 1);
|
||||
|
||||
// Register the hook
|
||||
$callback = [$commandFileInstance, $commandInfo->getMethodName()];
|
||||
$this->commandProcessor()->hookManager()->add($callback, $hook, $commandName);
|
||||
|
||||
// If the hook has options, then also register the commandInfo
|
||||
// with the hook manager, so that we can add options and such to
|
||||
// the commands they hook.
|
||||
if (!$commandInfo->options()->isEmpty()) {
|
||||
$this->commandProcessor()->hookManager()->recordHookOptions($commandInfo, $commandName);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getNthWord($string, $n, $default = '', $delimiter = ' ')
|
||||
{
|
||||
$words = explode($delimiter, $string);
|
||||
if (!empty($words[$n])) {
|
||||
return $words[$n];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function createCommand(CommandInfo $commandInfo, $commandFileInstance)
|
||||
{
|
||||
$this->alterCommandInfo($commandInfo, $commandFileInstance);
|
||||
$command = new AnnotatedCommand($commandInfo->getName());
|
||||
$commandCallback = [$commandFileInstance, $commandInfo->getMethodName()];
|
||||
$command->setCommandCallback($commandCallback);
|
||||
$command->setCommandProcessor($this->commandProcessor);
|
||||
$command->setCommandInfo($commandInfo);
|
||||
$automaticOptions = $this->callAutomaticOptionsProviders($commandInfo);
|
||||
$command->setCommandOptions($commandInfo, $automaticOptions);
|
||||
// Annotation commands are never bootstrap-aware, but for completeness
|
||||
// we will notify on every created command, as some clients may wish to
|
||||
// use this notification for some other purpose.
|
||||
$this->notify($command);
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give plugins an opportunity to update the commandInfo
|
||||
*/
|
||||
public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance)
|
||||
{
|
||||
foreach ($this->commandInfoAlterers as $alterer) {
|
||||
$alterer->alterCommandInfo($commandInfo, $commandFileInstance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the options that are implied by annotations, e.g. @fields implies
|
||||
* that there should be a --fields and a --format option.
|
||||
*
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function callAutomaticOptionsProviders(CommandInfo $commandInfo)
|
||||
{
|
||||
$automaticOptions = [];
|
||||
foreach ($this->automaticOptionsProviderList as $automaticOptionsProvider) {
|
||||
$automaticOptions += $automaticOptionsProvider->automaticOptions($commandInfo);
|
||||
}
|
||||
return $automaticOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the options that are implied by annotations, e.g. @fields implies
|
||||
* that there should be a --fields and a --format option.
|
||||
*
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function automaticOptions(CommandInfo $commandInfo)
|
||||
{
|
||||
$automaticOptions = [];
|
||||
$formatManager = $this->commandProcessor()->formatterManager();
|
||||
if ($formatManager) {
|
||||
$annotationData = $commandInfo->getAnnotations()->getArrayCopy();
|
||||
$formatterOptions = new FormatterOptions($annotationData);
|
||||
$dataType = $commandInfo->getReturnType();
|
||||
$automaticOptions = $formatManager->automaticOptions($formatterOptions, $dataType);
|
||||
}
|
||||
return $automaticOptions;
|
||||
}
|
||||
}
|
27
vendor/consolidation/annotated-command/src/AnnotationData.php
vendored
Normal file
27
vendor/consolidation/annotated-command/src/AnnotationData.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CsvUtils;
|
||||
|
||||
class AnnotationData extends \ArrayObject
|
||||
{
|
||||
public function get($key, $default = '')
|
||||
{
|
||||
return $this->has($key) ? CsvUtils::toString($this[$key]) : $default;
|
||||
}
|
||||
|
||||
public function getList($key, $default = [])
|
||||
{
|
||||
return $this->has($key) ? CsvUtils::toList($this[$key]) : $default;
|
||||
}
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return isset($this[$key]);
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->getArrayCopy());
|
||||
}
|
||||
}
|
49
vendor/consolidation/annotated-command/src/Cache/CacheWrapper.php
vendored
Normal file
49
vendor/consolidation/annotated-command/src/Cache/CacheWrapper.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Cache;
|
||||
|
||||
/**
|
||||
* Make a generic cache object conform to our expected interface.
|
||||
*/
|
||||
class CacheWrapper implements SimpleCacheInterface
|
||||
{
|
||||
protected $dataStore;
|
||||
|
||||
public function __construct($dataStore)
|
||||
{
|
||||
$this->dataStore = $dataStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for an entry from the cache
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
if (method_exists($this->dataStore, 'has')) {
|
||||
return $this->dataStore->has($key);
|
||||
}
|
||||
$test = $this->dataStore->get($key);
|
||||
return !empty($test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an entry from the cache
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return (array) $this->dataStore->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an entry in the cache
|
||||
* @param string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function set($key, $data)
|
||||
{
|
||||
$this->dataStore->set($key, $data);
|
||||
}
|
||||
}
|
37
vendor/consolidation/annotated-command/src/Cache/NullCache.php
vendored
Normal file
37
vendor/consolidation/annotated-command/src/Cache/NullCache.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Cache;
|
||||
|
||||
/**
|
||||
* An empty cache that never stores or fetches any objects.
|
||||
*/
|
||||
class NullCache implements SimpleCacheInterface
|
||||
{
|
||||
/**
|
||||
* Test for an entry from the cache
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an entry from the cache
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an entry in the cache
|
||||
* @param string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function set($key, $data)
|
||||
{
|
||||
}
|
||||
}
|
35
vendor/consolidation/annotated-command/src/Cache/SimpleCacheInterface.php
vendored
Normal file
35
vendor/consolidation/annotated-command/src/Cache/SimpleCacheInterface.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Cache;
|
||||
|
||||
/**
|
||||
* Documentation interface.
|
||||
*
|
||||
* Clients that use AnnotatedCommandFactory::setDataStore()
|
||||
* are encouraged to provide a data store that implements
|
||||
* this interface.
|
||||
*
|
||||
* This is not currently required to allow clients to use a generic cache
|
||||
* store that does not itself depend on the annotated-command library.
|
||||
* This might be required in a future version.
|
||||
*/
|
||||
interface SimpleCacheInterface
|
||||
{
|
||||
/**
|
||||
* Test for an entry from the cache
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key);
|
||||
/**
|
||||
* Get an entry from the cache
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function get($key);
|
||||
/**
|
||||
* Store an entry in the cache
|
||||
* @param string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function set($key, $data);
|
||||
}
|
25
vendor/consolidation/annotated-command/src/CommandCreationListener.php
vendored
Normal file
25
vendor/consolidation/annotated-command/src/CommandCreationListener.php
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
/**
|
||||
* Command cration listeners can be added to the annotation
|
||||
* command factory. These will be notified whenever a new
|
||||
* commandfile is provided to the factory. This is useful for
|
||||
* initializing new commandfile objects.
|
||||
*
|
||||
* @see AnnotatedCommandFactory::addListener()
|
||||
*/
|
||||
class CommandCreationListener implements CommandCreationListenerInterface
|
||||
{
|
||||
protected $listener;
|
||||
|
||||
public function __construct($listener)
|
||||
{
|
||||
$this->listener = $listener;
|
||||
}
|
||||
|
||||
public function notifyCommandFileAdded($command)
|
||||
{
|
||||
call_user_func($this->listener, $command);
|
||||
}
|
||||
}
|
15
vendor/consolidation/annotated-command/src/CommandCreationListenerInterface.php
vendored
Normal file
15
vendor/consolidation/annotated-command/src/CommandCreationListenerInterface.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
/**
|
||||
* Command cration listeners can be added to the annotation
|
||||
* command factory. These will be notified whenever a new
|
||||
* commandfile is provided to the factory. This is useful for
|
||||
* initializing new commandfile objects.
|
||||
*
|
||||
* @see AnnotatedCommandFactory::addListener()
|
||||
*/
|
||||
interface CommandCreationListenerInterface
|
||||
{
|
||||
public function notifyCommandFileAdded($command);
|
||||
}
|
195
vendor/consolidation/annotated-command/src/CommandData.php
vendored
Normal file
195
vendor/consolidation/annotated-command/src/CommandData.php
vendored
Normal file
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class CommandData
|
||||
{
|
||||
/** var AnnotationData */
|
||||
protected $annotationData;
|
||||
/** var InputInterface */
|
||||
protected $input;
|
||||
/** var OutputInterface */
|
||||
protected $output;
|
||||
/** var boolean */
|
||||
protected $usesInputInterface;
|
||||
/** var boolean */
|
||||
protected $usesOutputInterface;
|
||||
/** var boolean */
|
||||
protected $includeOptionsInArgs;
|
||||
/** var array */
|
||||
protected $specialDefaults = [];
|
||||
|
||||
public function __construct(
|
||||
AnnotationData $annotationData,
|
||||
InputInterface $input,
|
||||
OutputInterface $output,
|
||||
$usesInputInterface = false,
|
||||
$usesOutputInterface = false
|
||||
) {
|
||||
$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
|
||||
*/
|
||||
public function setUseIOInterfaces($usesInputInterface, $usesOutputInterface)
|
||||
{
|
||||
$this->usesInputInterface = $usesInputInterface;
|
||||
$this->usesOutputInterface = $usesOutputInterface;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For backwards-compatibility mode only: disable addition of
|
||||
* options on the end of the arguments list.
|
||||
*/
|
||||
public function setIncludeOptionsInArgs($includeOptionsInArgs)
|
||||
{
|
||||
$this->includeOptionsInArgs = $includeOptionsInArgs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function annotationData()
|
||||
{
|
||||
return $this->annotationData;
|
||||
}
|
||||
|
||||
public function input()
|
||||
{
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function output()
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
public function arguments()
|
||||
{
|
||||
return $this->input->getArguments();
|
||||
}
|
||||
|
||||
public function options()
|
||||
{
|
||||
// We cannot tell the difference between '--foo' (an option without
|
||||
// a value) and the absence of '--foo' when the option has an optional
|
||||
// value, and the current vallue of the option is 'null' using only
|
||||
// the public methods of InputInterface. We'll try to figure out
|
||||
// which is which by other means here.
|
||||
$options = $this->getAdjustedOptions();
|
||||
|
||||
// Make two conversions here:
|
||||
// --foo=0 wil convert $value from '0' to 'false' for binary options.
|
||||
// --foo with $value of 'true' will be forced to 'false' if --no-foo exists.
|
||||
foreach ($options as $option => $value) {
|
||||
if ($this->shouldConvertOptionToFalse($options, $option, $value)) {
|
||||
$options[$option] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use 'hasParameterOption()' to attempt to disambiguate option states.
|
||||
*/
|
||||
protected function getAdjustedOptions()
|
||||
{
|
||||
$options = $this->input->getOptions();
|
||||
|
||||
// If Input isn't an ArgvInput, then return the options as-is.
|
||||
if (!$this->input instanceof ArgvInput) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
// If we have an ArgvInput, then we can determine if options
|
||||
// are missing from the command line. If the option value is
|
||||
// missing from $input, then we will keep the value `null`.
|
||||
// If it is present, but has no explicit value, then change it its
|
||||
// value to `true`.
|
||||
foreach ($options as $option => $value) {
|
||||
if (($value === null) && ($this->input->hasParameterOption("--$option"))) {
|
||||
$options[$option] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
protected function shouldConvertOptionToFalse($options, $option, $value)
|
||||
{
|
||||
// If the value is 'true' (e.g. the option is '--foo'), then convert
|
||||
// it to false if there is also an option '--no-foo'. n.b. if the
|
||||
// commandline has '--foo=bar' then $value will not be 'true', and
|
||||
// --no-foo will be ignored.
|
||||
if ($value === true) {
|
||||
// Check if the --no-* option exists. Note that none of the other
|
||||
// alteration apply in the $value == true case, so we can exit early here.
|
||||
$negation_key = 'no-' . $option;
|
||||
return array_key_exists($negation_key, $options) && $options[$negation_key];
|
||||
}
|
||||
|
||||
// If the option is '--foo=0', convert the '0' to 'false' when appropriate.
|
||||
if ($value !== '0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The '--foo=0' convertion is only applicable when the default value
|
||||
// is not in the special defaults list. i.e. you get a literal '0'
|
||||
// when your default is a string.
|
||||
return in_array($option, $this->specialDefaults);
|
||||
}
|
||||
|
||||
public function cacheSpecialDefaults($definition)
|
||||
{
|
||||
foreach ($definition->getOptions() as $option => $inputOption) {
|
||||
$defaultValue = $inputOption->getDefault();
|
||||
if (($defaultValue === null) || ($defaultValue === true)) {
|
||||
$this->specialDefaults[] = $option;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getArgsWithoutAppName()
|
||||
{
|
||||
$args = $this->arguments();
|
||||
|
||||
// When called via the Application, the first argument
|
||||
// will be the command name. The Application alters the
|
||||
// input definition to match, adding a 'command' argument
|
||||
// to the beginning.
|
||||
array_shift($args);
|
||||
|
||||
if ($this->usesOutputInterface) {
|
||||
array_unshift($args, $this->output());
|
||||
}
|
||||
|
||||
if ($this->usesInputInterface) {
|
||||
array_unshift($args, $this->input());
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
public function getArgsAndOptions()
|
||||
{
|
||||
// Get passthrough args, and add the options on the end.
|
||||
$args = $this->getArgsWithoutAppName();
|
||||
if ($this->includeOptionsInArgs) {
|
||||
$args['options'] = $this->options();
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
32
vendor/consolidation/annotated-command/src/CommandError.php
vendored
Normal file
32
vendor/consolidation/annotated-command/src/CommandError.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
/**
|
||||
* Return a CommandError as the result of a command to pass a status
|
||||
* code and error message to be displayed.
|
||||
*
|
||||
* @package Consolidation\AnnotatedCommand
|
||||
*/
|
||||
class CommandError implements ExitCodeInterface, OutputDataInterface
|
||||
{
|
||||
protected $message;
|
||||
protected $exitCode;
|
||||
|
||||
public function __construct($message = null, $exitCode = 1)
|
||||
{
|
||||
$this->message = $message;
|
||||
// Ensure the exit code is non-zero. The exit code may have
|
||||
// come from an exception, and those often default to zero if
|
||||
// a specific value is not provided.
|
||||
$this->exitCode = $exitCode == 0 ? 1 : $exitCode;
|
||||
}
|
||||
public function getExitCode()
|
||||
{
|
||||
return $this->exitCode;
|
||||
}
|
||||
|
||||
public function getOutputData()
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
}
|
406
vendor/consolidation/annotated-command/src/CommandFileDiscovery.php
vendored
Normal file
406
vendor/consolidation/annotated-command/src/CommandFileDiscovery.php
vendored
Normal file
|
@ -0,0 +1,406 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Do discovery presuming that the namespace of the command will
|
||||
* contain the last component of the path. This is the convention
|
||||
* that should be used when searching for command files that are
|
||||
* bundled with the modules of a framework. The convention used
|
||||
* is that the namespace for a module in a framework should start with
|
||||
* the framework name followed by the module name.
|
||||
*
|
||||
* For example, if base namespace is "Drupal", then a command file in
|
||||
* modules/default_content/src/CliTools/ExampleCommands.cpp
|
||||
* will be in the namespace Drupal\default_content\CliTools.
|
||||
*
|
||||
* For global locations, the middle component of the namespace is
|
||||
* omitted. For example, if the base namespace is "Drupal", then
|
||||
* a command file in __DRUPAL_ROOT__/CliTools/ExampleCommands.cpp
|
||||
* will be in the namespace Drupal\CliTools.
|
||||
*
|
||||
* To discover namespaced commands in modules:
|
||||
*
|
||||
* $commandFiles = $discovery->discoverNamespaced($moduleList, '\Drupal');
|
||||
*
|
||||
* To discover global commands:
|
||||
*
|
||||
* $commandFiles = $discovery->discover($drupalRoot, '\Drupal');
|
||||
*/
|
||||
class CommandFileDiscovery
|
||||
{
|
||||
/** @var string[] */
|
||||
protected $excludeList;
|
||||
/** @var string[] */
|
||||
protected $searchLocations;
|
||||
/** @var string */
|
||||
protected $searchPattern = '*Commands.php';
|
||||
/** @var boolean */
|
||||
protected $includeFilesAtBase = true;
|
||||
/** @var integer */
|
||||
protected $searchDepth = 2;
|
||||
/** @var bool */
|
||||
protected $followLinks = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->excludeList = ['Exclude'];
|
||||
$this->searchLocations = [
|
||||
'Command',
|
||||
'CliTools', // TODO: Maybe remove
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to search for files at the base directory
|
||||
* ($directoryList parameter to discover and discoverNamespaced
|
||||
* methods), or only in the directories listed in the search paths.
|
||||
*
|
||||
* @param boolean $includeFilesAtBase
|
||||
*/
|
||||
public function setIncludeFilesAtBase($includeFilesAtBase)
|
||||
{
|
||||
$this->includeFilesAtBase = $includeFilesAtBase;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of excludes to add to the finder, replacing
|
||||
* whatever was there before.
|
||||
*
|
||||
* @param array $excludeList The list of directory names to skip when
|
||||
* searching for command files.
|
||||
*/
|
||||
public function setExcludeList($excludeList)
|
||||
{
|
||||
$this->excludeList = $excludeList;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one more location to the exclude list.
|
||||
*
|
||||
* @param string $exclude One directory name to skip when searching
|
||||
* for command files.
|
||||
*/
|
||||
public function addExclude($exclude)
|
||||
{
|
||||
$this->excludeList[] = $exclude;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search depth. By default, fills immediately in the
|
||||
* base directory are searched, plus all of the search locations
|
||||
* to this specified depth. If the search locations is set to
|
||||
* an empty array, then the base directory is searched to this
|
||||
* depth.
|
||||
*/
|
||||
public function setSearchDepth($searchDepth)
|
||||
{
|
||||
$this->searchDepth = $searchDepth;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the discovery object should follow symlinks. By
|
||||
* default, symlinks are not followed.
|
||||
*/
|
||||
public function followLinks($followLinks = true)
|
||||
{
|
||||
$this->followLinks = $followLinks;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of search locations to examine in each directory where
|
||||
* command files may be found. This replaces whatever was there before.
|
||||
*
|
||||
* @param array $searchLocations The list of locations to search for command files.
|
||||
*/
|
||||
public function setSearchLocations($searchLocations)
|
||||
{
|
||||
$this->searchLocations = $searchLocations;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one more location to the search location list.
|
||||
*
|
||||
* @param string $location One more relative path to search
|
||||
* for command files.
|
||||
*/
|
||||
public function addSearchLocation($location)
|
||||
{
|
||||
$this->searchLocations[] = $location;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the pattern / regex used by the finder to search for
|
||||
* command files.
|
||||
*/
|
||||
public function setSearchPattern($searchPattern)
|
||||
{
|
||||
$this->searchPattern = $searchPattern;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of directories, e.g. Drupal modules like:
|
||||
*
|
||||
* core/modules/block
|
||||
* core/modules/dblog
|
||||
* modules/default_content
|
||||
*
|
||||
* Discover command files in any of these locations.
|
||||
*
|
||||
* @param string|string[] $directoryList Places to search for commands.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function discoverNamespaced($directoryList, $baseNamespace = '')
|
||||
{
|
||||
return $this->discover($this->convertToNamespacedList((array)$directoryList), $baseNamespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a simple list containing paths to directories, where
|
||||
* the last component of the path should appear in the namespace,
|
||||
* after the base namespace, this function will return an
|
||||
* associative array mapping the path's basename (e.g. the module
|
||||
* name) to the directory path.
|
||||
*
|
||||
* Module names must be unique.
|
||||
*
|
||||
* @param string[] $directoryList A list of module locations
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function convertToNamespacedList($directoryList)
|
||||
{
|
||||
$namespacedArray = [];
|
||||
foreach ((array)$directoryList as $directory) {
|
||||
$namespacedArray[basename($directory)] = $directory;
|
||||
}
|
||||
return $namespacedArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for command files in the specified locations. This is the function that
|
||||
* should be used for all locations that are NOT modules of a framework.
|
||||
*
|
||||
* @param string|string[] $directoryList Places to search for commands.
|
||||
* @return array
|
||||
*/
|
||||
public function discover($directoryList, $baseNamespace = '')
|
||||
{
|
||||
$commandFiles = [];
|
||||
foreach ((array)$directoryList as $key => $directory) {
|
||||
$itemsNamespace = $this->joinNamespace([$baseNamespace, $key]);
|
||||
$commandFiles = array_merge(
|
||||
$commandFiles,
|
||||
$this->discoverCommandFiles($directory, $itemsNamespace),
|
||||
$this->discoverCommandFiles("$directory/src", $itemsNamespace)
|
||||
);
|
||||
}
|
||||
return $commandFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for command files in specific locations within a single directory.
|
||||
*
|
||||
* In each location, we will accept only a few places where command files
|
||||
* can be found. This will reduce the need to search through many unrelated
|
||||
* files.
|
||||
*
|
||||
* The default search locations include:
|
||||
*
|
||||
* .
|
||||
* CliTools
|
||||
* src/CliTools
|
||||
*
|
||||
* The pattern we will look for is any file whose name ends in 'Commands.php'.
|
||||
* A list of paths to found files will be returned.
|
||||
*/
|
||||
protected function discoverCommandFiles($directory, $baseNamespace)
|
||||
{
|
||||
$commandFiles = [];
|
||||
// In the search location itself, we will search for command files
|
||||
// immediately inside the directory only.
|
||||
if ($this->includeFilesAtBase) {
|
||||
$commandFiles = $this->discoverCommandFilesInLocation(
|
||||
$directory,
|
||||
$this->getBaseDirectorySearchDepth(),
|
||||
$baseNamespace
|
||||
);
|
||||
}
|
||||
|
||||
// In the other search locations,
|
||||
foreach ($this->searchLocations as $location) {
|
||||
$itemsNamespace = $this->joinNamespace([$baseNamespace, $location]);
|
||||
$commandFiles = array_merge(
|
||||
$commandFiles,
|
||||
$this->discoverCommandFilesInLocation(
|
||||
"$directory/$location",
|
||||
$this->getSearchDepth(),
|
||||
$itemsNamespace
|
||||
)
|
||||
);
|
||||
}
|
||||
return $commandFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Finder search depth appropriate for our selected search depth.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getSearchDepth()
|
||||
{
|
||||
return $this->searchDepth <= 0 ? '== 0' : '<= ' . $this->searchDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Finder search depth for the base directory. If the
|
||||
* searchLocations array has been populated, then we will only search
|
||||
* for files immediately inside the base directory; no traversal into
|
||||
* deeper directories will be done, as that would conflict with the
|
||||
* specification provided by the search locations. If there is no
|
||||
* search location, then we will search to whatever depth was specified
|
||||
* by the client.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getBaseDirectorySearchDepth()
|
||||
{
|
||||
if (!empty($this->searchLocations)) {
|
||||
return '== 0';
|
||||
}
|
||||
return $this->getSearchDepth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for command files in just one particular location. Returns
|
||||
* an associative array mapping from the pathname of the file to the
|
||||
* classname that it contains. The pathname may be ignored if the search
|
||||
* location is included in the autoloader.
|
||||
*
|
||||
* @param string $directory The location to search
|
||||
* @param string $depth How deep to search (e.g. '== 0' or '< 2')
|
||||
* @param string $baseNamespace Namespace to prepend to each classname
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function discoverCommandFilesInLocation($directory, $depth, $baseNamespace)
|
||||
{
|
||||
if (!is_dir($directory)) {
|
||||
return [];
|
||||
}
|
||||
$finder = $this->createFinder($directory, $depth);
|
||||
|
||||
$commands = [];
|
||||
foreach ($finder as $file) {
|
||||
$relativePathName = $file->getRelativePathname();
|
||||
$relativeNamespaceAndClassname = str_replace(
|
||||
['/', '.php'],
|
||||
['\\', ''],
|
||||
$relativePathName
|
||||
);
|
||||
$classname = $this->joinNamespace([$baseNamespace, $relativeNamespaceAndClassname]);
|
||||
$commandFilePath = $this->joinPaths([$directory, $relativePathName]);
|
||||
$commands[$commandFilePath] = $classname;
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Finder object for use in searching a particular directory
|
||||
* location.
|
||||
*
|
||||
* @param string $directory The location to search
|
||||
* @param string $depth The depth limitation
|
||||
*
|
||||
* @return Finder
|
||||
*/
|
||||
protected function createFinder($directory, $depth)
|
||||
{
|
||||
$finder = new Finder();
|
||||
$finder->files()
|
||||
->name($this->searchPattern)
|
||||
->in($directory)
|
||||
->depth($depth);
|
||||
|
||||
foreach ($this->excludeList as $item) {
|
||||
$finder->exclude($item);
|
||||
}
|
||||
|
||||
if ($this->followLinks) {
|
||||
$finder->followLinks();
|
||||
}
|
||||
|
||||
return $finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the items of the provied array into a backslash-separated
|
||||
* namespace string. Empty and numeric items are omitted.
|
||||
*
|
||||
* @param array $namespaceParts List of components of a namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function joinNamespace(array $namespaceParts)
|
||||
{
|
||||
return $this->joinParts(
|
||||
'\\',
|
||||
$namespaceParts,
|
||||
function ($item) {
|
||||
return !is_numeric($item) && !empty($item);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the items of the provied array into a slash-separated
|
||||
* pathname. Empty items are omitted.
|
||||
*
|
||||
* @param array $pathParts List of components of a path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function joinPaths(array $pathParts)
|
||||
{
|
||||
$path = $this->joinParts(
|
||||
'/',
|
||||
$pathParts,
|
||||
function ($item) {
|
||||
return !empty($item);
|
||||
}
|
||||
);
|
||||
return str_replace(DIRECTORY_SEPARATOR, '/', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper around implode and array_filter.
|
||||
*
|
||||
* @param string $delimiter
|
||||
* @param array $parts
|
||||
* @param callable $filterFunction
|
||||
*/
|
||||
protected function joinParts($delimiter, $parts, $filterFunction)
|
||||
{
|
||||
$parts = array_map(
|
||||
function ($item) use ($delimiter) {
|
||||
return rtrim($item, $delimiter);
|
||||
},
|
||||
$parts
|
||||
);
|
||||
return implode(
|
||||
$delimiter,
|
||||
array_filter($parts, $filterFunction)
|
||||
);
|
||||
}
|
||||
}
|
9
vendor/consolidation/annotated-command/src/CommandInfoAltererInterface.php
vendored
Normal file
9
vendor/consolidation/annotated-command/src/CommandInfoAltererInterface.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
|
||||
interface CommandInfoAltererInterface
|
||||
{
|
||||
public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance);
|
||||
}
|
363
vendor/consolidation/annotated-command/src/CommandProcessor.php
vendored
Normal file
363
vendor/consolidation/annotated-command/src/CommandProcessor.php
vendored
Normal file
|
@ -0,0 +1,363 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\ReplaceCommandHookDispatcher;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Process a command, including hooks and other callbacks.
|
||||
* There should only be one command processor per application.
|
||||
* Provide your command processor to the AnnotatedCommandFactory
|
||||
* via AnnotatedCommandFactory::setCommandProcessor().
|
||||
*/
|
||||
class CommandProcessor implements LoggerAwareInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/** var HookManager */
|
||||
protected $hookManager;
|
||||
/** var FormatterManager */
|
||||
protected $formatterManager;
|
||||
/** var callable */
|
||||
protected $displayErrorFunction;
|
||||
/** var PrepareFormatterOptions[] */
|
||||
protected $prepareOptionsList = [];
|
||||
/** var boolean */
|
||||
protected $passExceptions;
|
||||
|
||||
public function __construct(HookManager $hookManager)
|
||||
{
|
||||
$this->hookManager = $hookManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hook manager
|
||||
* @return HookManager
|
||||
*/
|
||||
public function hookManager()
|
||||
{
|
||||
return $this->hookManager;
|
||||
}
|
||||
|
||||
public function addPrepareFormatter(PrepareFormatter $preparer)
|
||||
{
|
||||
$this->prepareOptionsList[] = $preparer;
|
||||
}
|
||||
|
||||
public function setFormatterManager(FormatterManager $formatterManager)
|
||||
{
|
||||
$this->formatterManager = $formatterManager;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDisplayErrorFunction(callable $fn)
|
||||
{
|
||||
$this->displayErrorFunction = $fn;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mode to make the annotated command library re-throw
|
||||
* any exception that it catches while processing a command.
|
||||
*
|
||||
* The default behavior in the current (2.x) branch is to catch
|
||||
* the exception and replace it with a CommandError object that
|
||||
* may be processed by the normal output processing passthrough.
|
||||
*
|
||||
* In the 3.x branch, exceptions will never be caught; they will
|
||||
* be passed through, as if setPassExceptions(true) were called.
|
||||
* This is the recommended behavior.
|
||||
*/
|
||||
public function setPassExceptions($passExceptions)
|
||||
{
|
||||
$this->passExceptions = $passExceptions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function commandErrorForException(\Exception $e)
|
||||
{
|
||||
if ($this->passExceptions) {
|
||||
throw $e;
|
||||
}
|
||||
return new CommandError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the formatter manager
|
||||
* @return FormatterManager
|
||||
*/
|
||||
public function formatterManager()
|
||||
{
|
||||
return $this->formatterManager;
|
||||
}
|
||||
|
||||
public function initializeHook(
|
||||
InputInterface $input,
|
||||
$names,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$initializeDispatcher = new InitializeHookDispatcher($this->hookManager(), $names);
|
||||
return $initializeDispatcher->initialize($input, $annotationData);
|
||||
}
|
||||
|
||||
public function optionsHook(
|
||||
AnnotatedCommand $command,
|
||||
$names,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$optionsDispatcher = new OptionsHookDispatcher($this->hookManager(), $names);
|
||||
$optionsDispatcher->getOptions($command, $annotationData);
|
||||
}
|
||||
|
||||
public function interact(
|
||||
InputInterface $input,
|
||||
OutputInterface $output,
|
||||
$names,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$interactDispatcher = new InteractHookDispatcher($this->hookManager(), $names);
|
||||
return $interactDispatcher->interact($input, $output, $annotationData);
|
||||
}
|
||||
|
||||
public function process(
|
||||
OutputInterface $output,
|
||||
$names,
|
||||
$commandCallback,
|
||||
CommandData $commandData
|
||||
) {
|
||||
$result = [];
|
||||
try {
|
||||
$result = $this->validateRunAndAlter(
|
||||
$names,
|
||||
$commandCallback,
|
||||
$commandData
|
||||
);
|
||||
return $this->handleResults($output, $names, $result, $commandData);
|
||||
} catch (\Exception $e) {
|
||||
$result = $this->commandErrorForException($e);
|
||||
return $this->handleResults($output, $names, $result, $commandData);
|
||||
}
|
||||
}
|
||||
|
||||
public function validateRunAndAlter(
|
||||
$names,
|
||||
$commandCallback,
|
||||
CommandData $commandData
|
||||
) {
|
||||
// Validators return any object to signal a validation error;
|
||||
// if the return an array, it replaces the arguments.
|
||||
$validateDispatcher = new ValidateHookDispatcher($this->hookManager(), $names);
|
||||
$validated = $validateDispatcher->validate($commandData);
|
||||
if (is_object($validated)) {
|
||||
return $validated;
|
||||
}
|
||||
|
||||
$replaceDispatcher = new ReplaceCommandHookDispatcher($this->hookManager(), $names);
|
||||
if ($this->logger) {
|
||||
$replaceDispatcher->setLogger($this->logger);
|
||||
}
|
||||
if ($replaceDispatcher->hasReplaceCommandHook()) {
|
||||
$commandCallback = $replaceDispatcher->getReplacementCommand($commandData);
|
||||
}
|
||||
|
||||
// Run the command, alter the results, and then handle output and status
|
||||
$result = $this->runCommandCallback($commandCallback, $commandData);
|
||||
return $this->processResults($names, $result, $commandData);
|
||||
}
|
||||
|
||||
public function processResults($names, $result, CommandData $commandData)
|
||||
{
|
||||
$processDispatcher = new ProcessResultHookDispatcher($this->hookManager(), $names);
|
||||
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);
|
||||
$status = $statusCodeDispatcher->determineStatusCode($result);
|
||||
// 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);
|
||||
$output = $this->chooseOutputStream($output, $status);
|
||||
if ($status != 0) {
|
||||
return $this->writeErrorMessage($output, $status, $structuredOutput, $result);
|
||||
}
|
||||
if ($this->dataCanBeFormatted($structuredOutput) && isset($this->formatterManager)) {
|
||||
return $this->writeUsingFormatter($output, $structuredOutput, $commandData);
|
||||
}
|
||||
return $this->writeCommandOutput($output, $structuredOutput);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
$formatterOptions = $this->createFormatterOptions($commandData);
|
||||
$format = $this->getFormat($formatterOptions);
|
||||
$this->formatterManager->write(
|
||||
$output,
|
||||
$format,
|
||||
$structuredOutput,
|
||||
$formatterOptions
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FormatterOptions object for use in writing the formatted output.
|
||||
* @param CommandData $commandData
|
||||
* @return FormatterOptions
|
||||
*/
|
||||
protected function createFormatterOptions($commandData)
|
||||
{
|
||||
$options = $commandData->input()->getOptions();
|
||||
$formatterOptions = new FormatterOptions($commandData->annotationData()->getArrayCopy(), $options);
|
||||
foreach ($this->prepareOptionsList as $preparer) {
|
||||
$preparer->prepare($commandData, $formatterOptions);
|
||||
}
|
||||
return $formatterOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
) {
|
||||
// If there is no formatter, we will print strings,
|
||||
// but can do no more than that.
|
||||
if (is_string($structuredOutput)) {
|
||||
$output->writeln($structuredOutput);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a status code was set, then return it; otherwise,
|
||||
* presume success.
|
||||
*/
|
||||
protected function interpretStatusCode($status)
|
||||
{
|
||||
if (isset($status)) {
|
||||
return $status;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
20
vendor/consolidation/annotated-command/src/Events/CustomEventAwareInterface.php
vendored
Normal file
20
vendor/consolidation/annotated-command/src/Events/CustomEventAwareInterface.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Events;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
|
||||
interface CustomEventAwareInterface
|
||||
{
|
||||
/**
|
||||
* Set a reference to the hook manager for later use
|
||||
* @param HookManager $hookManager
|
||||
*/
|
||||
public function setHookManager(HookManager $hookManager);
|
||||
|
||||
/**
|
||||
* Get all of the defined event handlers of the specified name.
|
||||
* @param string $eventName
|
||||
* @return Callable[]
|
||||
*/
|
||||
public function getCustomEventHandlers($eventName);
|
||||
}
|
29
vendor/consolidation/annotated-command/src/Events/CustomEventAwareTrait.php
vendored
Normal file
29
vendor/consolidation/annotated-command/src/Events/CustomEventAwareTrait.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Events;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
|
||||
trait CustomEventAwareTrait
|
||||
{
|
||||
/** var HookManager */
|
||||
protected $hookManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHookManager(HookManager $hookManager)
|
||||
{
|
||||
$this->hookManager = $hookManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCustomEventHandlers($eventName)
|
||||
{
|
||||
if (!$this->hookManager) {
|
||||
return [];
|
||||
}
|
||||
return $this->hookManager->getHook($eventName, HookManager::ON_EVENT);
|
||||
}
|
||||
}
|
12
vendor/consolidation/annotated-command/src/ExitCodeInterface.php
vendored
Normal file
12
vendor/consolidation/annotated-command/src/ExitCodeInterface.php
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
/**
|
||||
* If an annotated command method encounters an error, then it
|
||||
* should either throw an exception, or return a result object
|
||||
* that implements ExitCodeInterface.
|
||||
*/
|
||||
interface ExitCodeInterface
|
||||
{
|
||||
public function getExitCode();
|
||||
}
|
48
vendor/consolidation/annotated-command/src/Help/HelpCommand.php
vendored
Normal file
48
vendor/consolidation/annotated-command/src/Help/HelpCommand.php
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?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;
|
||||
|
||||
class HelpCommand
|
||||
{
|
||||
/** var Application */
|
||||
protected $application;
|
||||
|
||||
/**
|
||||
* Create a help document from a Symfony Console command
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
public function getApplication()
|
||||
{
|
||||
return $this->application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the help command
|
||||
*
|
||||
* @command my-help
|
||||
* @return \Consolidation\AnnotatedCommand\Help\HelpDocument
|
||||
*/
|
||||
public function help($commandName = 'help')
|
||||
{
|
||||
$command = $this->getApplication()->find($commandName);
|
||||
|
||||
$helpDocument = $this->getHelpDocument($command);
|
||||
return $helpDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a help document.
|
||||
*/
|
||||
protected function getHelpDocument($command)
|
||||
{
|
||||
return new HelpDocument($command);
|
||||
}
|
||||
}
|
65
vendor/consolidation/annotated-command/src/Help/HelpDocument.php
vendored
Normal file
65
vendor/consolidation/annotated-command/src/Help/HelpDocument.php
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Help;
|
||||
|
||||
use Consolidation\OutputFormatters\StructuredData\Xml\DomDataInterface;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Descriptor\XmlDescriptor;
|
||||
|
||||
class HelpDocument implements DomDataInterface
|
||||
{
|
||||
/** var Command */
|
||||
protected $command;
|
||||
|
||||
/** var \DOMDocument */
|
||||
protected $dom;
|
||||
|
||||
/**
|
||||
* Create a help document from a Symfony Console command
|
||||
*/
|
||||
public function __construct(Command $command)
|
||||
{
|
||||
$dom = $this->generateBaseHelpDom($command);
|
||||
$dom = $this->alterHelpDocument($command, $dom);
|
||||
|
||||
$this->command = $command;
|
||||
$this->dom = $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data into a \DomDocument.
|
||||
*
|
||||
* @return \DomDocument
|
||||
*/
|
||||
public function getDomData()
|
||||
{
|
||||
return $this->dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the base help DOM prior to alteration by the Command object.
|
||||
* @param Command $command
|
||||
* @return \DomDocument
|
||||
*/
|
||||
protected function generateBaseHelpDom(Command $command)
|
||||
{
|
||||
// Use Symfony to generate xml text. If other formats are
|
||||
// requested, convert from xml to the desired form.
|
||||
$descriptor = new XmlDescriptor();
|
||||
return $descriptor->getCommandDocument($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the DOM document per the command object
|
||||
* @param Command $command
|
||||
* @param \DomDocument $dom
|
||||
* @return \DomDocument
|
||||
*/
|
||||
protected function alterHelpDocument(Command $command, \DomDocument $dom)
|
||||
{
|
||||
if ($command instanceof HelpDocumentAlter) {
|
||||
$dom = $command->helpAlter($dom);
|
||||
}
|
||||
return $dom;
|
||||
}
|
||||
}
|
7
vendor/consolidation/annotated-command/src/Help/HelpDocumentAlter.php
vendored
Normal file
7
vendor/consolidation/annotated-command/src/Help/HelpDocumentAlter.php
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Help;
|
||||
|
||||
interface HelpDocumentAlter
|
||||
{
|
||||
public function helpAlter(\DomDocument $dom);
|
||||
}
|
12
vendor/consolidation/annotated-command/src/Hooks/AlterResultInterface.php
vendored
Normal file
12
vendor/consolidation/annotated-command/src/Hooks/AlterResultInterface.php
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
/**
|
||||
* Alter the result of a command after it has been processed.
|
||||
* An alter result interface isa process result interface.
|
||||
*
|
||||
* @see HookManager::addAlterResult()
|
||||
*/
|
||||
interface AlterResultInterface extends ProcessResultInterface
|
||||
{
|
||||
}
|
37
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/CommandEventHookDispatcher.php
vendored
Normal file
37
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/CommandEventHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class CommandEventHookDispatcher extends HookDispatcher
|
||||
{
|
||||
/**
|
||||
* @param ConsoleCommandEvent $event
|
||||
*/
|
||||
public function callCommandEventHooks(ConsoleCommandEvent $event)
|
||||
{
|
||||
$hooks = [
|
||||
HookManager::PRE_COMMAND_EVENT,
|
||||
HookManager::COMMAND_EVENT,
|
||||
HookManager::POST_COMMAND_EVENT
|
||||
];
|
||||
$commandEventHooks = $this->getHooks($hooks);
|
||||
foreach ($commandEventHooks as $commandEvent) {
|
||||
if ($commandEvent instanceof EventDispatcherInterface) {
|
||||
$commandEvent->dispatch(ConsoleEvents::COMMAND, $event);
|
||||
}
|
||||
if (is_callable($commandEvent)) {
|
||||
$commandEvent($event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ExtracterHookDispatcher.php
vendored
Normal file
47
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ExtracterHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\ExtractOutputInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\OutputDataInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class ExtracterHookDispatcher extends HookDispatcher implements ExtractOutputInterface
|
||||
{
|
||||
/**
|
||||
* Convert the result object to printable output in
|
||||
* structured form.
|
||||
*/
|
||||
public function extractOutput($result)
|
||||
{
|
||||
if ($result instanceof OutputDataInterface) {
|
||||
return $result->getOutputData();
|
||||
}
|
||||
|
||||
$hooks = [
|
||||
HookManager::EXTRACT_OUTPUT,
|
||||
];
|
||||
$extractors = $this->getHooks($hooks);
|
||||
foreach ($extractors as $extractor) {
|
||||
$structuredOutput = $this->callExtractor($extractor, $result);
|
||||
if (isset($structuredOutput)) {
|
||||
return $structuredOutput;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function callExtractor($extractor, $result)
|
||||
{
|
||||
if ($extractor instanceof ExtractOutputInterface) {
|
||||
return $extractor->extractOutput($result);
|
||||
}
|
||||
if (is_callable($extractor)) {
|
||||
return $extractor($result);
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/HookDispatcher.php
vendored
Normal file
27
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/HookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class HookDispatcher
|
||||
{
|
||||
/** var HookManager */
|
||||
protected $hookManager;
|
||||
protected $names;
|
||||
|
||||
public function __construct(HookManager $hookManager, $names)
|
||||
{
|
||||
$this->hookManager = $hookManager;
|
||||
$this->names = $names;
|
||||
}
|
||||
|
||||
public function getHooks($hooks, $annotationData = null)
|
||||
{
|
||||
return $this->hookManager->getHooks($this->names, $hooks, $annotationData);
|
||||
}
|
||||
}
|
40
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php
vendored
Normal file
40
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\InitializeHookInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class InitializeHookDispatcher extends HookDispatcher implements InitializeHookInterface
|
||||
{
|
||||
public function initialize(
|
||||
InputInterface $input,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$hooks = [
|
||||
HookManager::PRE_INITIALIZE,
|
||||
HookManager::INITIALIZE,
|
||||
HookManager::POST_INITIALIZE
|
||||
];
|
||||
$providers = $this->getHooks($hooks, $annotationData);
|
||||
foreach ($providers as $provider) {
|
||||
$this->callInitializeHook($provider, $input, $annotationData);
|
||||
}
|
||||
}
|
||||
|
||||
protected function callInitializeHook($provider, $input, AnnotationData $annotationData)
|
||||
{
|
||||
if ($provider instanceof InitializeHookInterface) {
|
||||
return $provider->initialize($input, $annotationData);
|
||||
}
|
||||
if (is_callable($provider)) {
|
||||
return $provider($input, $annotationData);
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InteractHookDispatcher.php
vendored
Normal file
41
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InteractHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\InteractorInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class InteractHookDispatcher extends HookDispatcher
|
||||
{
|
||||
public function interact(
|
||||
InputInterface $input,
|
||||
OutputInterface $output,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$hooks = [
|
||||
HookManager::PRE_INTERACT,
|
||||
HookManager::INTERACT,
|
||||
HookManager::POST_INTERACT
|
||||
];
|
||||
$interactors = $this->getHooks($hooks, $annotationData);
|
||||
foreach ($interactors as $interactor) {
|
||||
$this->callInteractor($interactor, $input, $output, $annotationData);
|
||||
}
|
||||
}
|
||||
|
||||
protected function callInteractor($interactor, $input, $output, AnnotationData $annotationData)
|
||||
{
|
||||
if ($interactor instanceof InteractorInterface) {
|
||||
return $interactor->interact($input, $output, $annotationData);
|
||||
}
|
||||
if (is_callable($interactor)) {
|
||||
return $interactor($input, $output, $annotationData);
|
||||
}
|
||||
}
|
||||
}
|
44
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/OptionsHookDispatcher.php
vendored
Normal file
44
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/OptionsHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Consolidation\AnnotatedCommand\AnnotatedCommand;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\OptionHookInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class OptionsHookDispatcher extends HookDispatcher implements OptionHookInterface
|
||||
{
|
||||
public function getOptions(
|
||||
Command $command,
|
||||
AnnotationData $annotationData
|
||||
) {
|
||||
$hooks = [
|
||||
HookManager::PRE_OPTION_HOOK,
|
||||
HookManager::OPTION_HOOK,
|
||||
HookManager::POST_OPTION_HOOK
|
||||
];
|
||||
$optionHooks = $this->getHooks($hooks, $annotationData);
|
||||
foreach ($optionHooks as $optionHook) {
|
||||
$this->callOptionHook($optionHook, $command, $annotationData);
|
||||
}
|
||||
$commandInfoList = $this->hookManager->getHookOptionsForCommand($command);
|
||||
if ($command instanceof AnnotatedCommand) {
|
||||
$command->optionsHookForHookAnnotations($commandInfoList);
|
||||
}
|
||||
}
|
||||
|
||||
protected function callOptionHook($optionHook, $command, AnnotationData $annotationData)
|
||||
{
|
||||
if ($optionHook instanceof OptionHookInterface) {
|
||||
return $optionHook->getOptions($command, $annotationData);
|
||||
}
|
||||
if (is_callable($optionHook)) {
|
||||
return $optionHook($command, $annotationData);
|
||||
}
|
||||
}
|
||||
}
|
53
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ProcessResultHookDispatcher.php
vendored
Normal file
53
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ProcessResultHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ProcessResultInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class ProcessResultHookDispatcher extends HookDispatcher implements ProcessResultInterface
|
||||
{
|
||||
/**
|
||||
* Process result and decide what to do with it.
|
||||
* Allow client to add transformation / interpretation
|
||||
* callbacks.
|
||||
*/
|
||||
public function process($result, CommandData $commandData)
|
||||
{
|
||||
$hooks = [
|
||||
HookManager::PRE_PROCESS_RESULT,
|
||||
HookManager::PROCESS_RESULT,
|
||||
HookManager::POST_PROCESS_RESULT,
|
||||
HookManager::PRE_ALTER_RESULT,
|
||||
HookManager::ALTER_RESULT,
|
||||
HookManager::POST_ALTER_RESULT,
|
||||
HookManager::POST_COMMAND_HOOK,
|
||||
];
|
||||
$processors = $this->getHooks($hooks, $commandData->annotationData());
|
||||
foreach ($processors as $processor) {
|
||||
$result = $this->callProcessor($processor, $result, $commandData);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function callProcessor($processor, $result, CommandData $commandData)
|
||||
{
|
||||
$processed = null;
|
||||
if ($processor instanceof ProcessResultInterface) {
|
||||
$processed = $processor->process($result, $commandData);
|
||||
}
|
||||
if (is_callable($processor)) {
|
||||
$processed = $processor($result, $commandData);
|
||||
}
|
||||
if (isset($processed)) {
|
||||
return $processed;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
66
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ReplaceCommandHookDispatcher.php
vendored
Normal file
66
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ReplaceCommandHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Call hooks.
|
||||
*/
|
||||
class ReplaceCommandHookDispatcher extends HookDispatcher implements LoggerAwareInterface
|
||||
{
|
||||
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function hasReplaceCommandHook()
|
||||
{
|
||||
return (bool) count($this->getReplaceCommandHooks());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \callable[]
|
||||
*/
|
||||
public function getReplaceCommandHooks()
|
||||
{
|
||||
$hooks = [
|
||||
HookManager::REPLACE_COMMAND_HOOK,
|
||||
];
|
||||
$replaceCommandHooks = $this->getHooks($hooks);
|
||||
|
||||
return $replaceCommandHooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Consolidation\AnnotatedCommand\CommandData $commandData
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getReplacementCommand(CommandData $commandData)
|
||||
{
|
||||
$replaceCommandHooks = $this->getReplaceCommandHooks();
|
||||
|
||||
// We only take the first hook implementation of "replace-command" as the replacement. Commands shouldn't have
|
||||
// more than one replacement.
|
||||
$replacementCommand = reset($replaceCommandHooks);
|
||||
|
||||
if ($this->logger && count($replaceCommandHooks) > 1) {
|
||||
$command_name = $commandData->annotationData()->get('command', 'unknown');
|
||||
$message = "Multiple implementations of the \"replace - command\" hook exist for the \"$command_name\" command.\n";
|
||||
foreach ($replaceCommandHooks as $replaceCommandHook) {
|
||||
$class = get_class($replaceCommandHook[0]);
|
||||
$method = $replaceCommandHook[1];
|
||||
$hook_name = "$class->$method";
|
||||
$message .= " - $hook_name\n";
|
||||
}
|
||||
$this->logger->warning($message);
|
||||
}
|
||||
|
||||
return $replacementCommand;
|
||||
}
|
||||
}
|
51
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/StatusDeterminerHookDispatcher.php
vendored
Normal file
51
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/StatusDeterminerHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\ExitCodeInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\StatusDeterminerInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class StatusDeterminerHookDispatcher extends HookDispatcher implements StatusDeterminerInterface
|
||||
{
|
||||
/**
|
||||
* Call all status determiners, and see if any of them
|
||||
* know how to convert to a status code.
|
||||
*/
|
||||
public function determineStatusCode($result)
|
||||
{
|
||||
// If the result (post-processing) is an object that
|
||||
// implements ExitCodeInterface, then we will ask it
|
||||
// to give us the status code.
|
||||
if ($result instanceof ExitCodeInterface) {
|
||||
return $result->getExitCode();
|
||||
}
|
||||
|
||||
$hooks = [
|
||||
HookManager::STATUS_DETERMINER,
|
||||
];
|
||||
// If the result does not implement ExitCodeInterface,
|
||||
// then we'll see if there is a determiner that can
|
||||
// extract a status code from the result.
|
||||
$determiners = $this->getHooks($hooks);
|
||||
foreach ($determiners as $determiner) {
|
||||
$status = $this->callDeterminer($determiner, $result);
|
||||
if (isset($status)) {
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function callDeterminer($determiner, $result)
|
||||
{
|
||||
if ($determiner instanceof StatusDeterminerInterface) {
|
||||
return $determiner->determineStatusCode($result);
|
||||
}
|
||||
if (is_callable($determiner)) {
|
||||
return $determiner($result);
|
||||
}
|
||||
}
|
||||
}
|
46
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ValidateHookDispatcher.php
vendored
Normal file
46
vendor/consolidation/annotated-command/src/Hooks/Dispatchers/ValidateHookDispatcher.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Consolidation\AnnotatedCommand\Hooks\Dispatchers;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\CommandError;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* Call hooks
|
||||
*/
|
||||
class ValidateHookDispatcher extends HookDispatcher implements ValidatorInterface
|
||||
{
|
||||
public function validate(CommandData $commandData)
|
||||
{
|
||||
$hooks = [
|
||||
HookManager::PRE_ARGUMENT_VALIDATOR,
|
||||
HookManager::ARGUMENT_VALIDATOR,
|
||||
HookManager::POST_ARGUMENT_VALIDATOR,
|
||||
HookManager::PRE_COMMAND_HOOK,
|
||||
HookManager::COMMAND_HOOK,
|
||||
];
|
||||
$validators = $this->getHooks($hooks, $commandData->annotationData());
|
||||
foreach ($validators as $validator) {
|
||||
$validated = $this->callValidator($validator, $commandData);
|
||||
if ($validated === false) {
|
||||
return new CommandError();
|
||||
}
|
||||
if (is_object($validated)) {
|
||||
return $validated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function callValidator($validator, CommandData $commandData)
|
||||
{
|
||||
if ($validator instanceof ValidatorInterface) {
|
||||
return $validator->validate($commandData);
|
||||
}
|
||||
if (is_callable($validator)) {
|
||||
return $validator($commandData);
|
||||
}
|
||||
}
|
||||
}
|
14
vendor/consolidation/annotated-command/src/Hooks/ExtractOutputInterface.php
vendored
Normal file
14
vendor/consolidation/annotated-command/src/Hooks/ExtractOutputInterface.php
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
/**
|
||||
* Extract Output hooks are used to select the particular
|
||||
* data elements of the result that should be printed as
|
||||
* the command output -- perhaps after being formatted.
|
||||
*
|
||||
* @see HookManager::addOutputExtractor()
|
||||
*/
|
||||
interface ExtractOutputInterface
|
||||
{
|
||||
public function extractOutput($result);
|
||||
}
|
434
vendor/consolidation/annotated-command/src/Hooks/HookManager.php
vendored
Normal file
434
vendor/consolidation/annotated-command/src/Hooks/HookManager.php
vendored
Normal file
|
@ -0,0 +1,434 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
use Consolidation\AnnotatedCommand\ExitCodeInterface;
|
||||
use Consolidation\AnnotatedCommand\OutputDataInterface;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\CommandError;
|
||||
use Consolidation\AnnotatedCommand\Hooks\Dispatchers\CommandEventHookDispatcher;
|
||||
|
||||
/**
|
||||
* Manage named callback hooks
|
||||
*/
|
||||
class HookManager implements EventSubscriberInterface
|
||||
{
|
||||
protected $hooks = [];
|
||||
/** var CommandInfo[] */
|
||||
protected $hookOptions = [];
|
||||
|
||||
const REPLACE_COMMAND_HOOK = 'replace-command';
|
||||
const PRE_COMMAND_EVENT = 'pre-command-event';
|
||||
const COMMAND_EVENT = 'command-event';
|
||||
const POST_COMMAND_EVENT = 'post-command-event';
|
||||
const PRE_OPTION_HOOK = 'pre-option';
|
||||
const OPTION_HOOK = 'option';
|
||||
const POST_OPTION_HOOK = 'post-option';
|
||||
const PRE_INITIALIZE = 'pre-init';
|
||||
const INITIALIZE = 'init';
|
||||
const POST_INITIALIZE = 'post-init';
|
||||
const PRE_INTERACT = 'pre-interact';
|
||||
const INTERACT = 'interact';
|
||||
const POST_INTERACT = 'post-interact';
|
||||
const PRE_ARGUMENT_VALIDATOR = 'pre-validate';
|
||||
const ARGUMENT_VALIDATOR = 'validate';
|
||||
const POST_ARGUMENT_VALIDATOR = 'post-validate';
|
||||
const PRE_COMMAND_HOOK = 'pre-command';
|
||||
const COMMAND_HOOK = 'command';
|
||||
const POST_COMMAND_HOOK = 'post-command';
|
||||
const PRE_PROCESS_RESULT = 'pre-process';
|
||||
const PROCESS_RESULT = 'process';
|
||||
const POST_PROCESS_RESULT = 'post-process';
|
||||
const PRE_ALTER_RESULT = 'pre-alter';
|
||||
const ALTER_RESULT = 'alter';
|
||||
const POST_ALTER_RESULT = 'post-alter';
|
||||
const STATUS_DETERMINER = 'status';
|
||||
const EXTRACT_OUTPUT = 'extract';
|
||||
const ON_EVENT = 'on-event';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function getAllHooks()
|
||||
{
|
||||
return $this->hooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hook
|
||||
*
|
||||
* @param mixed $callback The callback function to call
|
||||
* @param string $hook The name of the hook to add
|
||||
* @param string $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function add(callable $callback, $hook, $name = '*')
|
||||
{
|
||||
if (empty($name)) {
|
||||
$name = static::getClassNameFromCallback($callback);
|
||||
}
|
||||
$this->hooks[$name][$hook][] = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function recordHookOptions($commandInfo, $name)
|
||||
{
|
||||
$this->hookOptions[$name][] = $commandInfo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function getNames($command, $callback)
|
||||
{
|
||||
return array_filter(
|
||||
array_merge(
|
||||
static::getNamesUsingCommands($command),
|
||||
[static::getClassNameFromCallback($callback)]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected static function getNamesUsingCommands($command)
|
||||
{
|
||||
return array_merge(
|
||||
[$command->getName()],
|
||||
$command->getAliases()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a command hook does not specify any particular command
|
||||
* name that it should be attached to, then it will be applied
|
||||
* to every command that is defined in the same class as the hook.
|
||||
* This is controlled by using the namespace + class name of
|
||||
* the implementing class of the callback hook.
|
||||
*/
|
||||
protected static function getClassNameFromCallback($callback)
|
||||
{
|
||||
if (!is_array($callback)) {
|
||||
return '';
|
||||
}
|
||||
$reflectionClass = new \ReflectionClass($callback[0]);
|
||||
return $reflectionClass->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a replace command hook
|
||||
*
|
||||
* @param type ReplaceCommandHookInterface $provider
|
||||
* @param type string $command_name The name of the command to replace
|
||||
*/
|
||||
public function addReplaceCommandHook(ReplaceCommandHookInterface $replaceCommandHook, $name)
|
||||
{
|
||||
$this->hooks[$name][self::REPLACE_COMMAND_HOOK][] = $replaceCommandHook;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addPreCommandEventDispatcher(EventDispatcherInterface $eventDispatcher, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::PRE_COMMAND_EVENT][] = $eventDispatcher;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCommandEventDispatcher(EventDispatcherInterface $eventDispatcher, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::COMMAND_EVENT][] = $eventDispatcher;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addPostCommandEventDispatcher(EventDispatcherInterface $eventDispatcher, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::POST_COMMAND_EVENT][] = $eventDispatcher;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCommandEvent(EventSubscriberInterface $eventSubscriber)
|
||||
{
|
||||
// Wrap the event subscriber in a dispatcher and add it
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber($eventSubscriber);
|
||||
return $this->addCommandEventDispatcher($dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an configuration provider hook
|
||||
*
|
||||
* @param type InitializeHookInterface $provider
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addInitializeHook(InitializeHookInterface $initializeHook, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::INITIALIZE][] = $initializeHook;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an option hook
|
||||
*
|
||||
* @param type ValidatorInterface $validator
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addOptionHook(OptionHookInterface $interactor, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::INTERACT][] = $interactor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an interact hook
|
||||
*
|
||||
* @param type ValidatorInterface $validator
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addInteractor(InteractorInterface $interactor, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::INTERACT][] = $interactor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pre-validator hook
|
||||
*
|
||||
* @param type ValidatorInterface $validator
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addPreValidator(ValidatorInterface $validator, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::PRE_ARGUMENT_VALIDATOR][] = $validator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a validator hook
|
||||
*
|
||||
* @param type ValidatorInterface $validator
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addValidator(ValidatorInterface $validator, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::ARGUMENT_VALIDATOR][] = $validator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pre-command hook. This is the same as a validator hook, except
|
||||
* that it will run after all of the post-validator hooks.
|
||||
*
|
||||
* @param type ValidatorInterface $preCommand
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addPreCommandHook(ValidatorInterface $preCommand, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::PRE_COMMAND_HOOK][] = $preCommand;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a post-command hook. This is the same as a pre-process hook,
|
||||
* except that it will run before the first pre-process hook.
|
||||
*
|
||||
* @param type ProcessResultInterface $postCommand
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addPostCommandHook(ProcessResultInterface $postCommand, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::POST_COMMAND_HOOK][] = $postCommand;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a result processor.
|
||||
*
|
||||
* @param type ProcessResultInterface $resultProcessor
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addResultProcessor(ProcessResultInterface $resultProcessor, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::PROCESS_RESULT][] = $resultProcessor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a result alterer. After a result is processed
|
||||
* by a result processor, an alter hook may be used
|
||||
* to convert the result from one form to another.
|
||||
*
|
||||
* @param type AlterResultInterface $resultAlterer
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addAlterResult(AlterResultInterface $resultAlterer, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::ALTER_RESULT][] = $resultAlterer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a status determiner. Usually, a command should return
|
||||
* an integer on error, or a result object on success (which
|
||||
* implies a status code of zero). If a result contains the
|
||||
* status code in some other field, then a status determiner
|
||||
* can be used to call the appropriate accessor method to
|
||||
* determine the status code. This is usually not necessary,
|
||||
* though; a command that fails may return a CommandError
|
||||
* object, which contains a status code and a result message
|
||||
* to display.
|
||||
* @see CommandError::getExitCode()
|
||||
*
|
||||
* @param type StatusDeterminerInterface $statusDeterminer
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addStatusDeterminer(StatusDeterminerInterface $statusDeterminer, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::STATUS_DETERMINER][] = $statusDeterminer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an output extractor. If a command returns an object
|
||||
* object, by default it is passed directly to the output
|
||||
* formatter (if in use) for rendering. If the result object
|
||||
* contains more information than just the data to render, though,
|
||||
* then an output extractor can be used to call the appopriate
|
||||
* accessor method of the result object to get the data to
|
||||
* rendered. This is usually not necessary, though; it is preferable
|
||||
* to have complex result objects implement the OutputDataInterface.
|
||||
* @see OutputDataInterface::getOutputData()
|
||||
*
|
||||
* @param type ExtractOutputInterface $outputExtractor
|
||||
* @param type $name The name of the command to hook
|
||||
* ('*' for all)
|
||||
*/
|
||||
public function addOutputExtractor(ExtractOutputInterface $outputExtractor, $name = '*')
|
||||
{
|
||||
$this->hooks[$name][self::EXTRACT_OUTPUT][] = $outputExtractor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHookOptionsForCommand($command)
|
||||
{
|
||||
$names = $this->addWildcardHooksToNames($command->getNames(), $command->getAnnotationData());
|
||||
return $this->getHookOptions($names);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CommandInfo[]
|
||||
*/
|
||||
public function getHookOptions($names)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($names as $name) {
|
||||
if (isset($this->hookOptions[$name])) {
|
||||
$result = array_merge($result, $this->hookOptions[$name]);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of hooks with the provided name(s). Include the
|
||||
* pre- and post- hooks, and also include the global hooks ('*')
|
||||
* in addition to the named hooks provided.
|
||||
*
|
||||
* @param string|array $names The name of the function being hooked.
|
||||
* @param string[] $hooks A list of hooks (e.g. [HookManager::ALTER_RESULT])
|
||||
*
|
||||
* @return callable[]
|
||||
*/
|
||||
public function getHooks($names, $hooks, $annotationData = null)
|
||||
{
|
||||
return $this->get($this->addWildcardHooksToNames($names, $annotationData), $hooks);
|
||||
}
|
||||
|
||||
protected function addWildcardHooksToNames($names, $annotationData = null)
|
||||
{
|
||||
$names = array_merge(
|
||||
(array)$names,
|
||||
($annotationData == null) ? [] : array_map(function ($item) {
|
||||
return "@$item";
|
||||
}, $annotationData->keys())
|
||||
);
|
||||
$names[] = '*';
|
||||
return array_unique($names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of hooks with the provided name(s).
|
||||
*
|
||||
* @param string|array $names The name of the function being hooked.
|
||||
* @param string[] $hooks The list of hook names (e.g. [HookManager::ALTER_RESULT])
|
||||
*
|
||||
* @return callable[]
|
||||
*/
|
||||
public function get($names, $hooks)
|
||||
{
|
||||
$result = [];
|
||||
foreach ((array)$hooks as $hook) {
|
||||
foreach ((array)$names as $name) {
|
||||
$result = array_merge($result, $this->getHook($name, $hook));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single named hook.
|
||||
*
|
||||
* @param string $name The name of the hooked method
|
||||
* @param string $hook The specific hook name (e.g. alter)
|
||||
*
|
||||
* @return callable[]
|
||||
*/
|
||||
public function getHook($name, $hook)
|
||||
{
|
||||
if (isset($this->hooks[$name][$hook])) {
|
||||
return $this->hooks[$name][$hook];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the command event hooks.
|
||||
*
|
||||
* TODO: This should be moved to CommandEventHookDispatcher, which
|
||||
* should become the class that implements EventSubscriberInterface.
|
||||
* This change would break all clients, though, so postpone until next
|
||||
* major release.
|
||||
*
|
||||
* @param ConsoleCommandEvent $event
|
||||
*/
|
||||
public function callCommandEventHooks(ConsoleCommandEvent $event)
|
||||
{
|
||||
/* @var Command $command */
|
||||
$command = $event->getCommand();
|
||||
$dispatcher = new CommandEventHookDispatcher($this, [$command->getName()]);
|
||||
$dispatcher->callCommandEventHooks($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @{@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [ConsoleEvents::COMMAND => 'callCommandEventHooks'];
|
||||
}
|
||||
}
|
15
vendor/consolidation/annotated-command/src/Hooks/InitializeHookInterface.php
vendored
Normal file
15
vendor/consolidation/annotated-command/src/Hooks/InitializeHookInterface.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
/**
|
||||
* Non-interactively (e.g. via configuration files) apply configuration values to the Input object.
|
||||
*
|
||||
* @see HookManager::addInitializeHook()
|
||||
*/
|
||||
interface InitializeHookInterface
|
||||
{
|
||||
public function initialize(InputInterface $input, AnnotationData $annotationData);
|
||||
}
|
18
vendor/consolidation/annotated-command/src/Hooks/InteractorInterface.php
vendored
Normal file
18
vendor/consolidation/annotated-command/src/Hooks/InteractorInterface.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Interactively supply values for missing required arguments for
|
||||
* the current command. Note that this hook is not called if
|
||||
* the --no-interaction flag is set.
|
||||
*
|
||||
* @see HookManager::addInteractor()
|
||||
*/
|
||||
interface InteractorInterface
|
||||
{
|
||||
public function interact(InputInterface $input, OutputInterface $output, AnnotationData $annotationData);
|
||||
}
|
16
vendor/consolidation/annotated-command/src/Hooks/OptionHookInterface.php
vendored
Normal file
16
vendor/consolidation/annotated-command/src/Hooks/OptionHookInterface.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/**
|
||||
* Add options to a command.
|
||||
*
|
||||
* @see HookManager::addOptionHook()
|
||||
* @see AnnotatedCommandFactory::addListener()
|
||||
*/
|
||||
interface OptionHookInterface
|
||||
{
|
||||
public function getOptions(Command $command, AnnotationData $annotationData);
|
||||
}
|
27
vendor/consolidation/annotated-command/src/Hooks/ProcessResultInterface.php
vendored
Normal file
27
vendor/consolidation/annotated-command/src/Hooks/ProcessResultInterface.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* A result processor takes a result object, processes it, and
|
||||
* returns another result object. For example, if a result object
|
||||
* represents a 'task', then a task-runner hook could run the
|
||||
* task and return the result from that execution.
|
||||
*
|
||||
* @see HookManager::addResultProcessor()
|
||||
*/
|
||||
interface ProcessResultInterface
|
||||
{
|
||||
/**
|
||||
* After a command has executed, if the result is something
|
||||
* that needs to be processed, e.g. a collection of tasks to
|
||||
* run, then execute it and return the new result.
|
||||
*
|
||||
* @param mixed $result Result to (potentially) be processed
|
||||
* @param CommandData $commandData Reference to commandline arguments and options
|
||||
*
|
||||
* @return mixed $result
|
||||
*/
|
||||
public function process($result, CommandData $commandData);
|
||||
}
|
18
vendor/consolidation/annotated-command/src/Hooks/StatusDeterminerInterface.php
vendored
Normal file
18
vendor/consolidation/annotated-command/src/Hooks/StatusDeterminerInterface.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
/**
|
||||
* A StatusDeterminer maps from a result to a status exit code.
|
||||
*
|
||||
* @see HookManager::addStatusDeterminer()
|
||||
*/
|
||||
interface StatusDeterminerInterface
|
||||
{
|
||||
/**
|
||||
* Convert a result object into a status code, if
|
||||
* possible. Return null if the result object is unknown.
|
||||
*
|
||||
* @return null|integer
|
||||
*/
|
||||
public function determineStatusCode($result);
|
||||
}
|
14
vendor/consolidation/annotated-command/src/Hooks/ValidatorInterface.php
vendored
Normal file
14
vendor/consolidation/annotated-command/src/Hooks/ValidatorInterface.php
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Hooks;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* Validate the arguments for the current command.
|
||||
*
|
||||
* @see HookManager::addValidator()
|
||||
*/
|
||||
interface ValidatorInterface
|
||||
{
|
||||
public function validate(CommandData $commandData);
|
||||
}
|
92
vendor/consolidation/annotated-command/src/Options/AlterOptionsCommandEvent.php
vendored
Normal file
92
vendor/consolidation/annotated-command/src/Options/AlterOptionsCommandEvent.php
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Options;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotatedCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* AlterOptionsCommandEvent is a subscriber to the Command Event
|
||||
* that looks up any additional options (e.g. from an OPTION_HOOK)
|
||||
* that should be added to the command. Options need to be added
|
||||
* in two circumstances:
|
||||
*
|
||||
* 1. When 'help' for the command is called, so that the additional
|
||||
* command options may be listed in the command description.
|
||||
*
|
||||
* 2. When the command itself is called, so that option validation
|
||||
* may be done.
|
||||
*
|
||||
* We defer the addition of options until these times so that we
|
||||
* do not invoke the option hooks for every command on every run
|
||||
* of the program, and so that we do not need to defer the addition
|
||||
* of all of the application hooks until after all of the application
|
||||
* commands have been added. (Hooks may appear in the same command files
|
||||
* as command implementations; applications may support command file
|
||||
* plug-ins, and hooks may add options to commands defined in other
|
||||
* commandfiles.)
|
||||
*/
|
||||
class AlterOptionsCommandEvent implements EventSubscriberInterface
|
||||
{
|
||||
/** var Application */
|
||||
protected $application;
|
||||
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConsoleCommandEvent $event
|
||||
*/
|
||||
public function alterCommandOptions(ConsoleCommandEvent $event)
|
||||
{
|
||||
/* @var Command $command */
|
||||
$command = $event->getCommand();
|
||||
$input = $event->getInput();
|
||||
if ($command->getName() == 'help') {
|
||||
// Symfony 3.x prepares $input for us; Symfony 2.x, on the other
|
||||
// hand, passes it in prior to binding with the command definition,
|
||||
// so we have to go to a little extra work. It may be inadvisable
|
||||
// to do these steps for commands other than 'help'.
|
||||
if (!$input->hasArgument('command_name')) {
|
||||
$command->ignoreValidationErrors();
|
||||
$command->mergeApplicationDefinition();
|
||||
$input->bind($command->getDefinition());
|
||||
}
|
||||
|
||||
// Symfony Console helpfully swaps 'command_name' and 'command'
|
||||
// depending on whether the user entered `help foo` or `--help foo`.
|
||||
// One of these is always `help`, and the other is the command we
|
||||
// are actually interested in.
|
||||
$nameOfCommandToDescribe = $event->getInput()->getArgument('command_name');
|
||||
if ($nameOfCommandToDescribe == 'help') {
|
||||
$nameOfCommandToDescribe = $event->getInput()->getArgument('command');
|
||||
}
|
||||
$commandToDescribe = $this->application->find($nameOfCommandToDescribe);
|
||||
$this->findAndAddHookOptions($commandToDescribe);
|
||||
} else {
|
||||
$this->findAndAddHookOptions($command);
|
||||
}
|
||||
}
|
||||
|
||||
public function findAndAddHookOptions($command)
|
||||
{
|
||||
if (!$command instanceof AnnotatedCommand) {
|
||||
return;
|
||||
}
|
||||
$command->optionsHook();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @{@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [ConsoleEvents::COMMAND => 'alterCommandOptions'];
|
||||
}
|
||||
}
|
21
vendor/consolidation/annotated-command/src/Options/AutomaticOptionsProviderInterface.php
vendored
Normal file
21
vendor/consolidation/annotated-command/src/Options/AutomaticOptionsProviderInterface.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Options;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* Option providers can add options to commands based on the annotations
|
||||
* present in a command. For example, a command that specifies @fields
|
||||
* will automatically be given --format and --fields options.
|
||||
*
|
||||
* @see AnnotatedCommandFactory::addListener()
|
||||
* @see HookManager::addOptionHook()
|
||||
*/
|
||||
interface AutomaticOptionsProviderInterface
|
||||
{
|
||||
/**
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function automaticOptions(CommandInfo $commandInfo);
|
||||
}
|
10
vendor/consolidation/annotated-command/src/Options/PrepareFormatter.php
vendored
Normal file
10
vendor/consolidation/annotated-command/src/Options/PrepareFormatter.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Options;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\OutputFormatters\Options\FormatterOptions;
|
||||
|
||||
interface PrepareFormatter
|
||||
{
|
||||
public function prepare(CommandData $commandData, FormatterOptions $options);
|
||||
}
|
106
vendor/consolidation/annotated-command/src/Options/PrepareTerminalWidthOption.php
vendored
Normal file
106
vendor/consolidation/annotated-command/src/Options/PrepareTerminalWidthOption.php
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Options;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\OutputFormatters\Options\FormatterOptions;
|
||||
|
||||
class PrepareTerminalWidthOption implements PrepareFormatter
|
||||
{
|
||||
/** var Application */
|
||||
protected $application;
|
||||
|
||||
protected $terminal;
|
||||
|
||||
/** var int */
|
||||
protected $defaultWidth;
|
||||
|
||||
/** var int */
|
||||
protected $maxWidth = PHP_INT_MAX;
|
||||
|
||||
/** var int */
|
||||
protected $minWidth = 0;
|
||||
|
||||
/* var boolean */
|
||||
protected $shouldWrap = true;
|
||||
|
||||
public function __construct($defaultWidth = 0)
|
||||
{
|
||||
$this->defaultWidth = $defaultWidth;
|
||||
}
|
||||
|
||||
public function setApplication(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
public function setTerminal($terminal)
|
||||
{
|
||||
$this->terminal = $terminal;
|
||||
}
|
||||
|
||||
public function getTerminal()
|
||||
{
|
||||
if (!$this->terminal && class_exists('\Symfony\Component\Console\Terminal')) {
|
||||
$this->terminal = new \Symfony\Component\Console\Terminal();
|
||||
}
|
||||
return $this->terminal;
|
||||
}
|
||||
|
||||
public function enableWrap($shouldWrap)
|
||||
{
|
||||
$this->shouldWrap = $shouldWrap;
|
||||
}
|
||||
|
||||
public function prepare(CommandData $commandData, FormatterOptions $options)
|
||||
{
|
||||
$width = $this->getTerminalWidth();
|
||||
if (!$width) {
|
||||
$width = $this->defaultWidth;
|
||||
}
|
||||
|
||||
// Enforce minimum and maximum widths
|
||||
$width = min($width, $this->getMaxWidth($commandData));
|
||||
$width = max($width, $this->getMinWidth($commandData));
|
||||
|
||||
$options->setWidth($width);
|
||||
}
|
||||
|
||||
protected function getTerminalWidth()
|
||||
{
|
||||
// Don't wrap if wrapping has been disabled.
|
||||
if (!$this->shouldWrap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$terminal = $this->getTerminal();
|
||||
if ($terminal) {
|
||||
return $terminal->getWidth();
|
||||
}
|
||||
|
||||
return $this->getTerminalWidthViaApplication();
|
||||
}
|
||||
|
||||
protected function getTerminalWidthViaApplication()
|
||||
{
|
||||
if (!$this->application) {
|
||||
return 0;
|
||||
}
|
||||
$dimensions = $this->application->getTerminalDimensions();
|
||||
if ($dimensions[0] == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $dimensions[0];
|
||||
}
|
||||
|
||||
protected function getMaxWidth(CommandData $commandData)
|
||||
{
|
||||
return $this->maxWidth;
|
||||
}
|
||||
|
||||
protected function getMinWidth(CommandData $commandData)
|
||||
{
|
||||
return $this->minWidth;
|
||||
}
|
||||
}
|
13
vendor/consolidation/annotated-command/src/OutputDataInterface.php
vendored
Normal file
13
vendor/consolidation/annotated-command/src/OutputDataInterface.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
/**
|
||||
* If an annotated command method returns an object that
|
||||
* implements OutputDataInterface, then the getOutputData()
|
||||
* method is used to fetch the output to print from the
|
||||
* result object.
|
||||
*/
|
||||
interface OutputDataInterface
|
||||
{
|
||||
public function getOutputData();
|
||||
}
|
764
vendor/consolidation/annotated-command/src/Parser/CommandInfo.php
vendored
Normal file
764
vendor/consolidation/annotated-command/src/Parser/CommandInfo.php
vendored
Normal file
|
@ -0,0 +1,764 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParser;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParserFactory;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
|
||||
/**
|
||||
* Given a class and method name, parse the annotations in the
|
||||
* DocBlock comment, and provide accessor methods for all of
|
||||
* the elements that are needed to create a Symfony Console Command.
|
||||
*
|
||||
* Note that the name of this class is now somewhat of a misnomer,
|
||||
* as we now use it to hold annotation data for hooks as well as commands.
|
||||
* It would probably be better to rename this to MethodInfo at some point.
|
||||
*/
|
||||
class CommandInfo
|
||||
{
|
||||
/**
|
||||
* Serialization schema version. Incremented every time the serialization schema changes.
|
||||
*/
|
||||
const SERIALIZATION_SCHEMA_VERSION = 3;
|
||||
|
||||
/**
|
||||
* @var \ReflectionMethod
|
||||
*/
|
||||
protected $reflection;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @var string
|
||||
*/
|
||||
protected $docBlockIsParsed = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $help = '';
|
||||
|
||||
/**
|
||||
* @var DefaultsWithDescriptions
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var DefaultsWithDescriptions
|
||||
*/
|
||||
protected $arguments;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $exampleUsage = [];
|
||||
|
||||
/**
|
||||
* @var AnnotationData
|
||||
*/
|
||||
protected $otherAnnotations;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* @var InputOption[]
|
||||
*/
|
||||
protected $inputOptions;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $methodName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $returnType;
|
||||
|
||||
/**
|
||||
* Create a new CommandInfo class for a particular method of a class.
|
||||
*
|
||||
* @param string|mixed $classNameOrInstance The name of a class, or an
|
||||
* instance of it, or an array of cached data.
|
||||
* @param string $methodName The name of the method to get info about.
|
||||
* @param array $cache Cached data
|
||||
* @deprecated Use CommandInfo::create() or CommandInfo::deserialize()
|
||||
* instead. In the future, this constructor will be protected.
|
||||
*/
|
||||
public function __construct($classNameOrInstance, $methodName, $cache = [])
|
||||
{
|
||||
$this->reflection = new \ReflectionMethod($classNameOrInstance, $methodName);
|
||||
$this->methodName = $methodName;
|
||||
$this->arguments = new DefaultsWithDescriptions();
|
||||
$this->options = new DefaultsWithDescriptions();
|
||||
|
||||
// If the cache came from a newer version, ignore it and
|
||||
// regenerate the cached information.
|
||||
if (!empty($cache) && CommandInfoDeserializer::isValidSerializedData($cache) && !$this->cachedFileIsModified($cache)) {
|
||||
$deserializer = new CommandInfoDeserializer();
|
||||
$deserializer->constructFromCache($this, $cache);
|
||||
$this->docBlockIsParsed = true;
|
||||
} else {
|
||||
$this->constructFromClassAndMethod($classNameOrInstance, $methodName);
|
||||
}
|
||||
}
|
||||
|
||||
public static function create($classNameOrInstance, $methodName)
|
||||
{
|
||||
return new self($classNameOrInstance, $methodName);
|
||||
}
|
||||
|
||||
public static function deserialize($cache)
|
||||
{
|
||||
$cache = (array)$cache;
|
||||
return new self($cache['class'], $cache['method_name'], $cache);
|
||||
}
|
||||
|
||||
public function cachedFileIsModified($cache)
|
||||
{
|
||||
$path = $this->reflection->getFileName();
|
||||
return filemtime($path) != $cache['mtime'];
|
||||
}
|
||||
|
||||
protected function constructFromClassAndMethod($classNameOrInstance, $methodName)
|
||||
{
|
||||
$this->otherAnnotations = new AnnotationData();
|
||||
// Set up a default name for the command from the method name.
|
||||
// This can be overridden via @command or @name annotations.
|
||||
$this->name = $this->convertName($methodName);
|
||||
$this->options = new DefaultsWithDescriptions($this->determineOptionsFromParameters(), false);
|
||||
$this->arguments = $this->determineAgumentClassifications();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover the method name provided to the constructor.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethodName()
|
||||
{
|
||||
return $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary name for this command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the primary name for this command.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not this method represents a valid command
|
||||
* or hook.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return !empty($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* If higher-level code decides that this CommandInfo is not interesting
|
||||
* or useful (if it is not a command method or a hook method), then
|
||||
* we will mark it as invalid to prevent it from being created as a command.
|
||||
* We still cache a placeholder record for invalid methods, so that we
|
||||
* do not need to re-parse the method again later simply to determine that
|
||||
* it is invalid.
|
||||
*/
|
||||
public function invalidate()
|
||||
{
|
||||
$this->name = '';
|
||||
}
|
||||
|
||||
public function getReturnType()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
public function setReturnType($returnType)
|
||||
{
|
||||
$this->returnType = $returnType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any annotations included in the docblock comment for the
|
||||
* implementation method of this command that are not already
|
||||
* handled by the primary methods of this class.
|
||||
*
|
||||
* @return AnnotationData
|
||||
*/
|
||||
public function getRawAnnotations()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->otherAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the annotation data.
|
||||
*/
|
||||
public function replaceRawAnnotations($annotationData)
|
||||
{
|
||||
$this->otherAnnotations = new AnnotationData((array) $annotationData);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any annotations included in the docblock comment,
|
||||
* also including default values such as @command. We add
|
||||
* in the default @command annotation late, and only in a
|
||||
* copy of the annotation data because we use the existance
|
||||
* of a @command to indicate that this CommandInfo is
|
||||
* a command, and not a hook or anything else.
|
||||
*
|
||||
* @return AnnotationData
|
||||
*/
|
||||
public function getAnnotations()
|
||||
{
|
||||
// Also provide the path to the commandfile that these annotations
|
||||
// were pulled from and the classname of that file.
|
||||
$path = $this->reflection->getFileName();
|
||||
$className = $this->reflection->getDeclaringClass()->getName();
|
||||
return new AnnotationData(
|
||||
$this->getRawAnnotations()->getArrayCopy() +
|
||||
[
|
||||
'command' => $this->getName(),
|
||||
'_path' => $path,
|
||||
'_classname' => $className,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific named annotation for this command as a list.
|
||||
*
|
||||
* @param string $name The name of the annotation.
|
||||
* @return array|null
|
||||
*/
|
||||
public function getAnnotationList($name)
|
||||
{
|
||||
// hasAnnotation parses the docblock
|
||||
if (!$this->hasAnnotation($name)) {
|
||||
return null;
|
||||
}
|
||||
return $this->otherAnnotations->getList($name);
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific named annotation for this command as a string.
|
||||
*
|
||||
* @param string $name The name of the annotation.
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAnnotation($name)
|
||||
{
|
||||
// hasAnnotation parses the docblock
|
||||
if (!$this->hasAnnotation($name)) {
|
||||
return null;
|
||||
}
|
||||
return $this->otherAnnotations->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the specified annotation exists for this command.
|
||||
*
|
||||
* @param string $annotation The name of the annotation.
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasAnnotation($annotation)
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return isset($this->otherAnnotations[$annotation]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save any tag that we do not explicitly recognize in the
|
||||
* 'otherAnnotations' map.
|
||||
*/
|
||||
public function addAnnotation($name, $content)
|
||||
{
|
||||
// Convert to an array and merge if there are multiple
|
||||
// instances of the same annotation defined.
|
||||
if (isset($this->otherAnnotations[$name])) {
|
||||
$content = array_merge((array) $this->otherAnnotations[$name], (array)$content);
|
||||
}
|
||||
$this->otherAnnotations[$name] = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an annotation that was previoudly set.
|
||||
*/
|
||||
public function removeAnnotation($name)
|
||||
{
|
||||
unset($this->otherAnnotations[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the synopsis of the command (~first line).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command description.
|
||||
*
|
||||
* @param string $description The description to set.
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = str_replace("\n", ' ', $description);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the help text of the command (the description)
|
||||
*/
|
||||
public function getHelp()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->help;
|
||||
}
|
||||
/**
|
||||
* Set the help text for this command.
|
||||
*
|
||||
* @param string $help The help text.
|
||||
*/
|
||||
public function setHelp($help)
|
||||
{
|
||||
$this->help = $help;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of aliases for this command.
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAliases()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set aliases that can be used in place of the command's primary name.
|
||||
*
|
||||
* @param string|string[] $aliases
|
||||
*/
|
||||
public function setAliases($aliases)
|
||||
{
|
||||
if (is_string($aliases)) {
|
||||
$aliases = explode(',', static::convertListToCommaSeparated($aliases));
|
||||
}
|
||||
$this->aliases = array_filter($aliases);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hidden status for the command.
|
||||
* @return bool
|
||||
*/
|
||||
public function getHidden()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->hasAnnotation('hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hidden status. List command omits hidden commands.
|
||||
*
|
||||
* @param bool $hidden
|
||||
*/
|
||||
public function setHidden($hidden)
|
||||
{
|
||||
$this->hidden = $hidden;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the examples for this command. This is @usage instead of
|
||||
* @example because the later is defined by the phpdoc standard to
|
||||
* be example method calls.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getExampleUsages()
|
||||
{
|
||||
$this->parseDocBlock();
|
||||
return $this->exampleUsage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an example usage for this command.
|
||||
*
|
||||
* @param string $usage An example of the command, including the command
|
||||
* name and all of its example arguments and options.
|
||||
* @param string $description An explanation of what the example does.
|
||||
*/
|
||||
public function setExampleUsage($usage, $description)
|
||||
{
|
||||
$this->exampleUsage[$usage] = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite all example usages
|
||||
*/
|
||||
public function replaceExampleUsages($usages)
|
||||
{
|
||||
$this->exampleUsage = $usages;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the topics for this command.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTopics()
|
||||
{
|
||||
if (!$this->hasAnnotation('topics')) {
|
||||
return [];
|
||||
}
|
||||
$topics = $this->getAnnotation('topics');
|
||||
return explode(',', trim($topics));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of refleaction parameters.
|
||||
*
|
||||
* @return ReflectionParameter[]
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->reflection->getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Descriptions of commandline arguements for this command.
|
||||
*
|
||||
* @return DefaultsWithDescriptions
|
||||
*/
|
||||
public function arguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Descriptions of commandline options for this command.
|
||||
*
|
||||
* @return DefaultsWithDescriptions
|
||||
*/
|
||||
public function options()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inputOptions for the options associated with this CommandInfo
|
||||
* object, e.g. via @option annotations, or from
|
||||
* $options = ['someoption' => 'defaultvalue'] in the command method
|
||||
* parameter list.
|
||||
*
|
||||
* @return InputOption[]
|
||||
*/
|
||||
public function inputOptions()
|
||||
{
|
||||
if (!isset($this->inputOptions)) {
|
||||
$this->inputOptions = $this->createInputOptions();
|
||||
}
|
||||
return $this->inputOptions;
|
||||
}
|
||||
|
||||
protected function addImplicitNoOptions()
|
||||
{
|
||||
$opts = $this->options()->getValues();
|
||||
foreach ($opts as $name => $defaultValue) {
|
||||
if ($defaultValue === true) {
|
||||
$key = 'no-' . $name;
|
||||
if (!array_key_exists($key, $opts)) {
|
||||
$description = "Negate --$name option.";
|
||||
$this->options()->add($key, $description, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function createInputOptions()
|
||||
{
|
||||
$explicitOptions = [];
|
||||
$this->addImplicitNoOptions();
|
||||
|
||||
$opts = $this->options()->getValues();
|
||||
foreach ($opts as $name => $defaultValue) {
|
||||
$description = $this->options()->getDescription($name);
|
||||
|
||||
$fullName = $name;
|
||||
$shortcut = '';
|
||||
if (strpos($name, '|')) {
|
||||
list($fullName, $shortcut) = explode('|', $name, 2);
|
||||
}
|
||||
|
||||
// Treat the following two cases identically:
|
||||
// - 'foo' => InputOption::VALUE_OPTIONAL
|
||||
// - 'foo' => null
|
||||
// The first form is preferred, but we will convert the value
|
||||
// to 'null' for storage as the option default value.
|
||||
if ($defaultValue === InputOption::VALUE_OPTIONAL) {
|
||||
$defaultValue = null;
|
||||
}
|
||||
|
||||
if ($defaultValue === false) {
|
||||
$explicitOptions[$fullName] = new InputOption($fullName, $shortcut, InputOption::VALUE_NONE, $description);
|
||||
} elseif ($defaultValue === InputOption::VALUE_REQUIRED) {
|
||||
$explicitOptions[$fullName] = new InputOption($fullName, $shortcut, InputOption::VALUE_REQUIRED, $description);
|
||||
} elseif (is_array($defaultValue)) {
|
||||
$optionality = count($defaultValue) ? InputOption::VALUE_OPTIONAL : InputOption::VALUE_REQUIRED;
|
||||
$explicitOptions[$fullName] = new InputOption(
|
||||
$fullName,
|
||||
$shortcut,
|
||||
InputOption::VALUE_IS_ARRAY | $optionality,
|
||||
$description,
|
||||
count($defaultValue) ? $defaultValue : null
|
||||
);
|
||||
} else {
|
||||
$explicitOptions[$fullName] = new InputOption($fullName, $shortcut, InputOption::VALUE_OPTIONAL, $description, $defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
return $explicitOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* An option might have a name such as 'silent|s'. In this
|
||||
* instance, we will allow the @option or @default tag to
|
||||
* reference the option only by name (e.g. 'silent' or 's'
|
||||
* instead of 'silent|s').
|
||||
*
|
||||
* @param string $optionName
|
||||
* @return string
|
||||
*/
|
||||
public function findMatchingOption($optionName)
|
||||
{
|
||||
// Exit fast if there's an exact match
|
||||
if ($this->options->exists($optionName)) {
|
||||
return $optionName;
|
||||
}
|
||||
$existingOptionName = $this->findExistingOption($optionName);
|
||||
if (isset($existingOptionName)) {
|
||||
return $existingOptionName;
|
||||
}
|
||||
return $this->findOptionAmongAlternatives($optionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $optionName
|
||||
* @return string
|
||||
*/
|
||||
protected function findOptionAmongAlternatives($optionName)
|
||||
{
|
||||
// Check the other direction: if the annotation contains @silent|s
|
||||
// and the options array has 'silent|s'.
|
||||
$checkMatching = explode('|', $optionName);
|
||||
if (count($checkMatching) > 1) {
|
||||
foreach ($checkMatching as $checkName) {
|
||||
if ($this->options->exists($checkName)) {
|
||||
$this->options->rename($checkName, $optionName);
|
||||
return $optionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $optionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $optionName
|
||||
* @return string|null
|
||||
*/
|
||||
protected function findExistingOption($optionName)
|
||||
{
|
||||
// Check to see if we can find the option name in an existing option,
|
||||
// e.g. if the options array has 'silent|s' => false, and the annotation
|
||||
// is @silent.
|
||||
foreach ($this->options()->getValues() as $name => $default) {
|
||||
if (in_array($optionName, explode('|', $name))) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the parameters of the method for this command, and
|
||||
* build a list of commandline arguements for them.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function determineAgumentClassifications()
|
||||
{
|
||||
$result = new DefaultsWithDescriptions();
|
||||
$params = $this->reflection->getParameters();
|
||||
$optionsFromParameters = $this->determineOptionsFromParameters();
|
||||
if ($this->lastParameterIsOptionsArray()) {
|
||||
array_pop($params);
|
||||
}
|
||||
foreach ($params as $param) {
|
||||
$this->addParameterToResult($result, $param);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the provided parameter, and determine whether it
|
||||
* is a parameter that will be filled in with a positional
|
||||
* commandline argument.
|
||||
*/
|
||||
protected function addParameterToResult($result, $param)
|
||||
{
|
||||
// Commandline arguments must be strings, so ignore any
|
||||
// parameter that is typehinted to any non-primative class.
|
||||
if ($param->getClass() != null) {
|
||||
return;
|
||||
}
|
||||
$result->add($param->name);
|
||||
if ($param->isDefaultValueAvailable()) {
|
||||
$defaultValue = $param->getDefaultValue();
|
||||
if (!$this->isAssoc($defaultValue)) {
|
||||
$result->setDefaultValue($param->name, $defaultValue);
|
||||
}
|
||||
} elseif ($param->isArray()) {
|
||||
$result->setDefaultValue($param->name, []);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the parameters of the method for this command, and determine
|
||||
* the disposition of the options from them.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function determineOptionsFromParameters()
|
||||
{
|
||||
$params = $this->reflection->getParameters();
|
||||
if (empty($params)) {
|
||||
return [];
|
||||
}
|
||||
$param = end($params);
|
||||
if (!$param->isDefaultValueAvailable()) {
|
||||
return [];
|
||||
}
|
||||
if (!$this->isAssoc($param->getDefaultValue())) {
|
||||
return [];
|
||||
}
|
||||
return $param->getDefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the last argument contains $options.
|
||||
*
|
||||
* Two forms indicate options:
|
||||
* - $options = []
|
||||
* - $options = ['flag' => 'default-value']
|
||||
*
|
||||
* Any other form, including `array $foo`, is not options.
|
||||
*/
|
||||
protected function lastParameterIsOptionsArray()
|
||||
{
|
||||
$params = $this->reflection->getParameters();
|
||||
if (empty($params)) {
|
||||
return [];
|
||||
}
|
||||
$param = end($params);
|
||||
if (!$param->isDefaultValueAvailable()) {
|
||||
return [];
|
||||
}
|
||||
return is_array($param->getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper; determine if an array is associative or not. An array
|
||||
* is not associative if its keys are numeric, and numbered sequentially
|
||||
* from zero. All other arrays are considered to be associative.
|
||||
*
|
||||
* @param array $arr The array
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isAssoc($arr)
|
||||
{
|
||||
if (!is_array($arr)) {
|
||||
return false;
|
||||
}
|
||||
return array_keys($arr) !== range(0, count($arr) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from a method name to the corresponding command name. A
|
||||
* method 'fooBar' will become 'foo:bar', and 'fooBarBazBoz' will
|
||||
* become 'foo:bar-baz-boz'.
|
||||
*
|
||||
* @param string $camel method name.
|
||||
* @return string
|
||||
*/
|
||||
protected function convertName($camel)
|
||||
{
|
||||
$splitter="-";
|
||||
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
|
||||
$camel = preg_replace("/$splitter/", ':', $camel, 1);
|
||||
return strtolower($camel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the docBlock comment for this command, and set the
|
||||
* fields of this class with the data thereby obtained.
|
||||
*/
|
||||
protected function parseDocBlock()
|
||||
{
|
||||
if (!$this->docBlockIsParsed) {
|
||||
// The parse function will insert data from the provided method
|
||||
// into this object, using our accessors.
|
||||
CommandDocBlockParserFactory::parse($this, $this->reflection);
|
||||
$this->docBlockIsParsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list that might be 'a b c' or 'a, b, c' or 'a,b,c',
|
||||
* convert the data into the last of these forms.
|
||||
*/
|
||||
protected static function convertListToCommaSeparated($text)
|
||||
{
|
||||
return preg_replace('#[ \t\n\r,]+#', ',', $text);
|
||||
}
|
||||
}
|
87
vendor/consolidation/annotated-command/src/Parser/CommandInfoDeserializer.php
vendored
Normal file
87
vendor/consolidation/annotated-command/src/Parser/CommandInfoDeserializer.php
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParser;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParserFactory;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
|
||||
/**
|
||||
* Deserialize a CommandInfo object
|
||||
*/
|
||||
class CommandInfoDeserializer
|
||||
{
|
||||
// TODO: in a future version, move CommandInfo::deserialize here
|
||||
public function deserialize($data)
|
||||
{
|
||||
return CommandInfo::deserialize((array)$data);
|
||||
}
|
||||
|
||||
protected static function cachedMethodExists($cache)
|
||||
{
|
||||
return method_exists($cache['class'], $cache['method_name']);
|
||||
}
|
||||
|
||||
public static function isValidSerializedData($cache)
|
||||
{
|
||||
return
|
||||
isset($cache['schema']) &&
|
||||
isset($cache['method_name']) &&
|
||||
isset($cache['mtime']) &&
|
||||
($cache['schema'] > 0) &&
|
||||
($cache['schema'] <= CommandInfo::SERIALIZATION_SCHEMA_VERSION) &&
|
||||
self::cachedMethodExists($cache);
|
||||
}
|
||||
|
||||
public function constructFromCache(CommandInfo $commandInfo, $info_array)
|
||||
{
|
||||
$info_array += $this->defaultSerializationData();
|
||||
|
||||
$commandInfo
|
||||
->setName($info_array['name'])
|
||||
->replaceRawAnnotations($info_array['annotations'])
|
||||
->setAliases($info_array['aliases'])
|
||||
->setHelp($info_array['help'])
|
||||
->setDescription($info_array['description'])
|
||||
->replaceExampleUsages($info_array['example_usages'])
|
||||
->setReturnType($info_array['return_type'])
|
||||
;
|
||||
|
||||
$this->constructDefaultsWithDescriptions($commandInfo->arguments(), (array)$info_array['arguments']);
|
||||
$this->constructDefaultsWithDescriptions($commandInfo->options(), (array)$info_array['options']);
|
||||
}
|
||||
|
||||
protected function constructDefaultsWithDescriptions(DefaultsWithDescriptions $defaults, $data)
|
||||
{
|
||||
foreach ($data as $key => $info) {
|
||||
$info = (array)$info;
|
||||
$defaults->add($key, $info['description']);
|
||||
if (array_key_exists('default', $info)) {
|
||||
$defaults->setDefaultValue($key, $info['default']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default data. Everything should be provided during serialization;
|
||||
* this is just as a fallback for unusual circumstances.
|
||||
* @return array
|
||||
*/
|
||||
protected function defaultSerializationData()
|
||||
{
|
||||
return [
|
||||
'name' => '',
|
||||
'description' => '',
|
||||
'help' => '',
|
||||
'aliases' => [],
|
||||
'annotations' => [],
|
||||
'example_usages' => [],
|
||||
'return_type' => [],
|
||||
'parameters' => [],
|
||||
'arguments' => [],
|
||||
'options' => [],
|
||||
'mtime' => 0,
|
||||
];
|
||||
}
|
||||
}
|
59
vendor/consolidation/annotated-command/src/Parser/CommandInfoSerializer.php
vendored
Normal file
59
vendor/consolidation/annotated-command/src/Parser/CommandInfoSerializer.php
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParser;
|
||||
use Consolidation\AnnotatedCommand\Parser\Internal\CommandDocBlockParserFactory;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
|
||||
/**
|
||||
* Serialize a CommandInfo object
|
||||
*/
|
||||
class CommandInfoSerializer
|
||||
{
|
||||
public function serialize(CommandInfo $commandInfo)
|
||||
{
|
||||
$allAnnotations = $commandInfo->getAnnotations();
|
||||
$path = $allAnnotations['_path'];
|
||||
$className = $allAnnotations['_classname'];
|
||||
|
||||
// Include the minimum information for command info (including placeholder records)
|
||||
$info = [
|
||||
'schema' => CommandInfo::SERIALIZATION_SCHEMA_VERSION,
|
||||
'class' => $className,
|
||||
'method_name' => $commandInfo->getMethodName(),
|
||||
'mtime' => filemtime($path),
|
||||
];
|
||||
|
||||
// If this is a valid method / hook, then add more information.
|
||||
if ($commandInfo->valid()) {
|
||||
$info += [
|
||||
'name' => $commandInfo->getName(),
|
||||
'description' => $commandInfo->getDescription(),
|
||||
'help' => $commandInfo->getHelp(),
|
||||
'aliases' => $commandInfo->getAliases(),
|
||||
'annotations' => $commandInfo->getRawAnnotations()->getArrayCopy(),
|
||||
'example_usages' => $commandInfo->getExampleUsages(),
|
||||
'return_type' => $commandInfo->getReturnType(),
|
||||
];
|
||||
$info['arguments'] = $this->serializeDefaultsWithDescriptions($commandInfo->arguments());
|
||||
$info['options'] = $this->serializeDefaultsWithDescriptions($commandInfo->options());
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
protected function serializeDefaultsWithDescriptions(DefaultsWithDescriptions $defaults)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($defaults->getValues() as $key => $val) {
|
||||
$result[$key] = [
|
||||
'description' => $defaults->getDescription($key),
|
||||
];
|
||||
if ($defaults->hasDefault($key)) {
|
||||
$result[$key]['default'] = $val;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
162
vendor/consolidation/annotated-command/src/Parser/DefaultsWithDescriptions.php
vendored
Normal file
162
vendor/consolidation/annotated-command/src/Parser/DefaultsWithDescriptions.php
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser;
|
||||
|
||||
/**
|
||||
* An associative array that maps from key to default value;
|
||||
* each entry can also have a description.
|
||||
*/
|
||||
class DefaultsWithDescriptions
|
||||
{
|
||||
/**
|
||||
* @var array Associative array of key : default mappings
|
||||
*/
|
||||
protected $values;
|
||||
|
||||
/**
|
||||
* @var array Associative array used like a set to indicate default value
|
||||
* exists for the key.
|
||||
*/
|
||||
protected $hasDefault;
|
||||
|
||||
/**
|
||||
* @var array Associative array of key : description mappings
|
||||
*/
|
||||
protected $descriptions;
|
||||
|
||||
/**
|
||||
* @var mixed Default value that the default value of items in
|
||||
* the collection should take when not specified in the 'add' method.
|
||||
*/
|
||||
protected $defaultDefault;
|
||||
|
||||
public function __construct($values = [], $defaultDefault = null)
|
||||
{
|
||||
$this->values = $values;
|
||||
$this->hasDefault = array_filter($this->values, function ($value) {
|
||||
return isset($value);
|
||||
});
|
||||
$this->descriptions = [];
|
||||
$this->defaultDefault = $defaultDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return just the key : default values mapping
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValues()
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this set of options is empty
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return empty($this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see whether the speicifed key exists in the collection.
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
return array_key_exists($key, $this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of one entry.
|
||||
*
|
||||
* @param string $key The key of the item.
|
||||
* @return string
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->values)) {
|
||||
return $this->values[$key];
|
||||
}
|
||||
return $this->defaultDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of one entry.
|
||||
*
|
||||
* @param string $key The key of the item.
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->descriptions)) {
|
||||
return $this->descriptions[$key];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add another argument to this command.
|
||||
*
|
||||
* @param string $key Name of the argument.
|
||||
* @param string $description Help text for the argument.
|
||||
* @param mixed $defaultValue The default value for the argument.
|
||||
*/
|
||||
public function add($key, $description = '', $defaultValue = null)
|
||||
{
|
||||
if (!$this->exists($key) || isset($defaultValue)) {
|
||||
$this->values[$key] = isset($defaultValue) ? $defaultValue : $this->defaultDefault;
|
||||
}
|
||||
unset($this->descriptions[$key]);
|
||||
if (!empty($description)) {
|
||||
$this->descriptions[$key] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the default value of an entry.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $defaultValue
|
||||
*/
|
||||
public function setDefaultValue($key, $defaultValue)
|
||||
{
|
||||
$this->values[$key] = $defaultValue;
|
||||
$this->hasDefault[$key] = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the named argument definitively has a default value.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return array_key_exists($key, $this->hasDefault);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry
|
||||
*
|
||||
* @param string $key The entry to remove
|
||||
*/
|
||||
public function clear($key)
|
||||
{
|
||||
unset($this->values[$key]);
|
||||
unset($this->descriptions[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename an existing option to something else.
|
||||
*/
|
||||
public function rename($oldName, $newName)
|
||||
{
|
||||
$this->add($newName, $this->getDescription($oldName), $this->get($oldName));
|
||||
$this->clear($oldName);
|
||||
}
|
||||
}
|
322
vendor/consolidation/annotated-command/src/Parser/Internal/BespokeDocBlockParser.php
vendored
Normal file
322
vendor/consolidation/annotated-command/src/Parser/Internal/BespokeDocBlockParser.php
vendored
Normal file
|
@ -0,0 +1,322 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\AnnotatedCommand\Parser\DefaultsWithDescriptions;
|
||||
|
||||
/**
|
||||
* Given a class and method name, parse the annotations in the
|
||||
* DocBlock comment, and provide accessor methods for all of
|
||||
* the elements that are needed to create an annotated Command.
|
||||
*/
|
||||
class BespokeDocBlockParser
|
||||
{
|
||||
protected $fqcnCache;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $tagProcessors = [
|
||||
'command' => 'processCommandTag',
|
||||
'name' => 'processCommandTag',
|
||||
'arg' => 'processArgumentTag',
|
||||
'param' => 'processArgumentTag',
|
||||
'return' => 'processReturnTag',
|
||||
'option' => 'processOptionTag',
|
||||
'default' => 'processDefaultTag',
|
||||
'aliases' => 'processAliases',
|
||||
'usage' => 'processUsageTag',
|
||||
'description' => 'processAlternateDescriptionTag',
|
||||
'desc' => 'processAlternateDescriptionTag',
|
||||
];
|
||||
|
||||
public function __construct(CommandInfo $commandInfo, \ReflectionMethod $reflection, $fqcnCache = null)
|
||||
{
|
||||
$this->commandInfo = $commandInfo;
|
||||
$this->reflection = $reflection;
|
||||
$this->fqcnCache = $fqcnCache ?: new FullyQualifiedClassCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the docBlock comment for this command, and set the
|
||||
* fields of this class with the data thereby obtained.
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
$doc = $this->reflection->getDocComment();
|
||||
$this->parseDocBlock($doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save any tag that we do not explicitly recognize in the
|
||||
* 'otherAnnotations' map.
|
||||
*/
|
||||
protected function processGenericTag($tag)
|
||||
{
|
||||
$this->commandInfo->addAnnotation($tag->getTag(), $tag->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the command from a @command or @name annotation.
|
||||
*/
|
||||
protected function processCommandTag($tag)
|
||||
{
|
||||
if (!$tag->hasWordAndDescription($matches)) {
|
||||
throw new \Exception('Could not determine command name from tag ' . (string)$tag);
|
||||
}
|
||||
$commandName = $matches['word'];
|
||||
$this->commandInfo->setName($commandName);
|
||||
// We also store the name in the 'other annotations' so that is is
|
||||
// possible to determine if the method had a @command annotation.
|
||||
$this->commandInfo->addAnnotation($tag->getTag(), $commandName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The @description and @desc annotations may be used in
|
||||
* place of the synopsis (which we call 'description').
|
||||
* This is discouraged.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function processAlternateDescriptionTag($tag)
|
||||
{
|
||||
$this->commandInfo->setDescription($tag->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data from a @arg annotation in our argument descriptions.
|
||||
*/
|
||||
protected function processArgumentTag($tag)
|
||||
{
|
||||
if (!$tag->hasVariable($matches)) {
|
||||
throw new \Exception('Could not determine argument name from tag ' . (string)$tag);
|
||||
}
|
||||
if ($matches['variable'] == $this->optionParamName()) {
|
||||
return;
|
||||
}
|
||||
$this->addOptionOrArgumentTag($tag, $this->commandInfo->arguments(), $matches['variable'], $matches['description']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data from an @option annotation in our option descriptions.
|
||||
*/
|
||||
protected function processOptionTag($tag)
|
||||
{
|
||||
if (!$tag->hasVariable($matches)) {
|
||||
throw new \Exception('Could not determine option name from tag ' . (string)$tag);
|
||||
}
|
||||
$this->addOptionOrArgumentTag($tag, $this->commandInfo->options(), $matches['variable'], $matches['description']);
|
||||
}
|
||||
|
||||
protected function addOptionOrArgumentTag($tag, DefaultsWithDescriptions $set, $name, $description)
|
||||
{
|
||||
$variableName = $this->commandInfo->findMatchingOption($name);
|
||||
$description = static::removeLineBreaks($description);
|
||||
$set->add($variableName, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data from a @default annotation in our argument or option store,
|
||||
* as appropriate.
|
||||
*/
|
||||
protected function processDefaultTag($tag)
|
||||
{
|
||||
if (!$tag->hasVariable($matches)) {
|
||||
throw new \Exception('Could not determine parameter name for default value from tag ' . (string)$tag);
|
||||
}
|
||||
$variableName = $matches['variable'];
|
||||
$defaultValue = $this->interpretDefaultValue($matches['description']);
|
||||
if ($this->commandInfo->arguments()->exists($variableName)) {
|
||||
$this->commandInfo->arguments()->setDefaultValue($variableName, $defaultValue);
|
||||
return;
|
||||
}
|
||||
$variableName = $this->commandInfo->findMatchingOption($variableName);
|
||||
if ($this->commandInfo->options()->exists($variableName)) {
|
||||
$this->commandInfo->options()->setDefaultValue($variableName, $defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data from a @usage annotation in our example usage list.
|
||||
*/
|
||||
protected function processUsageTag($tag)
|
||||
{
|
||||
$lines = explode("\n", $tag->getContent());
|
||||
$usage = trim(array_shift($lines));
|
||||
$description = static::removeLineBreaks(implode("\n", array_map(function ($line) {
|
||||
return trim($line);
|
||||
}, $lines)));
|
||||
|
||||
$this->commandInfo->setExampleUsage($usage, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the comma-separated list of aliases
|
||||
*/
|
||||
protected function processAliases($tag)
|
||||
{
|
||||
$this->commandInfo->setAliases((string)$tag->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data from a @return annotation in our argument descriptions.
|
||||
*/
|
||||
protected function processReturnTag($tag)
|
||||
{
|
||||
// The return type might be a variable -- '$this'. It will
|
||||
// usually be a type, like RowsOfFields, or \Namespace\RowsOfFields.
|
||||
if (!$tag->hasVariableAndDescription($matches)) {
|
||||
throw new \Exception('Could not determine return type from tag ' . (string)$tag);
|
||||
}
|
||||
// Look at namespace and `use` statments to make returnType a fqdn
|
||||
$returnType = $matches['variable'];
|
||||
$returnType = $this->findFullyQualifiedClass($returnType);
|
||||
$this->commandInfo->setReturnType($returnType);
|
||||
}
|
||||
|
||||
protected function findFullyQualifiedClass($className)
|
||||
{
|
||||
if (strpos($className, '\\') !== false) {
|
||||
return $className;
|
||||
}
|
||||
|
||||
return $this->fqcnCache->qualify($this->reflection->getFileName(), $className);
|
||||
}
|
||||
|
||||
private function parseDocBlock($doc)
|
||||
{
|
||||
// Remove the leading /** and the trailing */
|
||||
$doc = preg_replace('#^\s*/\*+\s*#', '', $doc);
|
||||
$doc = preg_replace('#\s*\*+/\s*#', '', $doc);
|
||||
|
||||
// Nothing left? Exit.
|
||||
if (empty($doc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tagFactory = new TagFactory();
|
||||
$lines = [];
|
||||
|
||||
foreach (explode("\n", $doc) as $row) {
|
||||
// Remove trailing whitespace and leading space + '*'s
|
||||
$row = rtrim($row);
|
||||
$row = preg_replace('#^[ \t]*\**#', '', $row);
|
||||
|
||||
if (!$tagFactory->parseLine($row)) {
|
||||
$lines[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
$this->processDescriptionAndHelp($lines);
|
||||
$this->processAllTags($tagFactory->getTags());
|
||||
}
|
||||
|
||||
protected function processDescriptionAndHelp($lines)
|
||||
{
|
||||
// Trim all of the lines individually.
|
||||
$lines =
|
||||
array_map(
|
||||
function ($line) {
|
||||
return trim($line);
|
||||
},
|
||||
$lines
|
||||
);
|
||||
|
||||
// Everything up to the first blank line goes in the description.
|
||||
$description = array_shift($lines);
|
||||
while ($this->nextLineIsNotEmpty($lines)) {
|
||||
$description .= ' ' . array_shift($lines);
|
||||
}
|
||||
|
||||
// Everything else goes in the help.
|
||||
$help = trim(implode("\n", $lines));
|
||||
|
||||
$this->commandInfo->setDescription($description);
|
||||
$this->commandInfo->setHelp($help);
|
||||
}
|
||||
|
||||
protected function nextLineIsNotEmpty($lines)
|
||||
{
|
||||
if (empty($lines)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nextLine = trim($lines[0]);
|
||||
return !empty($nextLine);
|
||||
}
|
||||
|
||||
protected function processAllTags($tags)
|
||||
{
|
||||
// Iterate over all of the tags, and process them as necessary.
|
||||
foreach ($tags as $tag) {
|
||||
$processFn = [$this, 'processGenericTag'];
|
||||
if (array_key_exists($tag->getTag(), $this->tagProcessors)) {
|
||||
$processFn = [$this, $this->tagProcessors[$tag->getTag()]];
|
||||
}
|
||||
$processFn($tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected function lastParameterName()
|
||||
{
|
||||
$params = $this->commandInfo->getParameters();
|
||||
$param = end($params);
|
||||
if (!$param) {
|
||||
return '';
|
||||
}
|
||||
return $param->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the last parameter if it holds the options.
|
||||
*/
|
||||
public function optionParamName()
|
||||
{
|
||||
// Remember the name of the last parameter, if it holds the options.
|
||||
// We will use this information to ignore @param annotations for the options.
|
||||
if (!isset($this->optionParamName)) {
|
||||
$this->optionParamName = '';
|
||||
$options = $this->commandInfo->options();
|
||||
if (!$options->isEmpty()) {
|
||||
$this->optionParamName = $this->lastParameterName();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->optionParamName;
|
||||
}
|
||||
|
||||
protected function interpretDefaultValue($defaultValue)
|
||||
{
|
||||
$defaults = [
|
||||
'null' => null,
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
"''" => '',
|
||||
'[]' => [],
|
||||
];
|
||||
foreach ($defaults as $defaultName => $defaultTypedValue) {
|
||||
if ($defaultValue == $defaultName) {
|
||||
return $defaultTypedValue;
|
||||
}
|
||||
}
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list that might be 'a b c' or 'a, b, c' or 'a,b,c',
|
||||
* convert the data into the last of these forms.
|
||||
*/
|
||||
protected static function convertListToCommaSeparated($text)
|
||||
{
|
||||
return preg_replace('#[ \t\n\r,]+#', ',', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a multiline description and convert it into a single
|
||||
* long unbroken line.
|
||||
*/
|
||||
protected static function removeLineBreaks($text)
|
||||
{
|
||||
return trim(preg_replace('#[ \t\n\r]+#', ' ', $text));
|
||||
}
|
||||
}
|
20
vendor/consolidation/annotated-command/src/Parser/Internal/CommandDocBlockParserFactory.php
vendored
Normal file
20
vendor/consolidation/annotated-command/src/Parser/Internal/CommandDocBlockParserFactory.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
|
||||
/**
|
||||
* Create an appropriate CommandDocBlockParser.
|
||||
*/
|
||||
class CommandDocBlockParserFactory
|
||||
{
|
||||
public static function parse(CommandInfo $commandInfo, \ReflectionMethod $reflection)
|
||||
{
|
||||
return static::create($commandInfo, $reflection)->parse();
|
||||
}
|
||||
|
||||
private static function create(CommandInfo $commandInfo, \ReflectionMethod $reflection)
|
||||
{
|
||||
return new BespokeDocBlockParser($commandInfo, $reflection);
|
||||
}
|
||||
}
|
49
vendor/consolidation/annotated-command/src/Parser/Internal/CsvUtils.php
vendored
Normal file
49
vendor/consolidation/annotated-command/src/Parser/Internal/CsvUtils.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
/**
|
||||
* Methods to convert to / from a csv string.
|
||||
*/
|
||||
class CsvUtils
|
||||
{
|
||||
/**
|
||||
* Ensure that the provided data is a string.
|
||||
*
|
||||
* @param string|array $data The data to convert to a string.
|
||||
* @return string
|
||||
*/
|
||||
public static function toString($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
return static::csvEscape($data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to a csv.
|
||||
*/
|
||||
public static function csvEscape(array $data, $delimiter = ',')
|
||||
{
|
||||
$buffer = fopen('php://temp', 'r+');
|
||||
fputcsv($buffer, $data, $delimiter);
|
||||
rewind($buffer);
|
||||
$csv = fgets($buffer);
|
||||
fclose($buffer);
|
||||
return rtrim($csv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific named annotation for this command.
|
||||
*
|
||||
* @param string|array $data The data to convert to an array.
|
||||
* @return array
|
||||
*/
|
||||
public static function toList($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
return str_getcsv($data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
155
vendor/consolidation/annotated-command/src/Parser/Internal/DocblockTag.php
vendored
Normal file
155
vendor/consolidation/annotated-command/src/Parser/Internal/DocblockTag.php
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
/**
|
||||
* Hold the tag definition for one tag in a DocBlock.
|
||||
*
|
||||
* The tag can be sliced into the following forms:
|
||||
* - "@tag content"
|
||||
* - "@tag word description"
|
||||
* - "@tag $variable description"
|
||||
* - "@tag word $variable description"
|
||||
*/
|
||||
class DocblockTag
|
||||
{
|
||||
/** @var string Name of the tag */
|
||||
protected $tag;
|
||||
|
||||
/** @var string|null Contents of the tag. */
|
||||
protected $content;
|
||||
|
||||
const TAG_REGEX = '@(?P<tag>[^\s$]+)[\s]*';
|
||||
const VARIABLE_REGEX = '\\$(?P<variable>[^\s$]+)[\s]*';
|
||||
const VARIABLE_OR_WORD_REGEX = '\\$?(?P<variable>[^\s$]+)[\s]*';
|
||||
const TYPE_REGEX = '(?P<type>[^\s$]+)[\s]*';
|
||||
const WORD_REGEX = '(?P<word>[^\s$]+)[\s]*';
|
||||
const DESCRIPTION_REGEX = '(?P<description>.*)';
|
||||
const IS_TAG_REGEX = '/^[*\s]*@/';
|
||||
|
||||
/**
|
||||
* Check if the provided string begins with a tag
|
||||
* @param string $subject
|
||||
* @return bool
|
||||
*/
|
||||
public static function isTag($subject)
|
||||
{
|
||||
return preg_match(self::IS_TAG_REGEX, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a regular expression to separate the tag from the content.
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string[] &$matches Sets $matches['tag'] and $matches['description']
|
||||
* @return bool
|
||||
*/
|
||||
public static function splitTagAndContent($subject, &$matches)
|
||||
{
|
||||
$regex = '/' . self::TAG_REGEX . self::DESCRIPTION_REGEX . '/s';
|
||||
return preg_match($regex, $subject, $matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* DockblockTag constructor
|
||||
*/
|
||||
public function __construct($tag, $content = null)
|
||||
{
|
||||
$this->tag = $tag;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add more content onto a tag during parsing.
|
||||
*/
|
||||
public function appendContent($line)
|
||||
{
|
||||
$this->content .= "\n$line";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tag - e.g. "@foo description" returns 'foo'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content portion of the tag - e.g. "@foo bar baz boz" returns
|
||||
* "bar baz boz"
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert tag back into a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return '@' . $this->getTag() . ' ' . $this->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if tag is one of:
|
||||
* - "@tag variable description"
|
||||
* - "@tag $variable description"
|
||||
* - "@tag type $variable description"
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string[] &$matches Sets $matches['variable'] and
|
||||
* $matches['description']; might set $matches['type'].
|
||||
* @return bool
|
||||
*/
|
||||
public function hasVariable(&$matches)
|
||||
{
|
||||
return
|
||||
$this->hasTypeVariableAndDescription($matches) ||
|
||||
$this->hasVariableAndDescription($matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if tag is "@tag $variable description"
|
||||
* @param string $subject
|
||||
* @param string[] &$matches Sets $matches['variable'] and
|
||||
* $matches['description']
|
||||
* @return bool
|
||||
*/
|
||||
public function hasVariableAndDescription(&$matches)
|
||||
{
|
||||
$regex = '/^\s*' . self::VARIABLE_OR_WORD_REGEX . self::DESCRIPTION_REGEX . '/s';
|
||||
return preg_match($regex, $this->getContent(), $matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if tag is "@tag type $variable description"
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string[] &$matches Sets $matches['variable'],
|
||||
* $matches['description'] and $matches['type'].
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTypeVariableAndDescription(&$matches)
|
||||
{
|
||||
$regex = '/^\s*' . self::TYPE_REGEX . self::VARIABLE_REGEX . self::DESCRIPTION_REGEX . '/s';
|
||||
return preg_match($regex, $this->getContent(), $matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if tag is "@tag word description"
|
||||
* @param string $subject
|
||||
* @param string[] &$matches Sets $matches['word'] and
|
||||
* $matches['description']
|
||||
* @return bool
|
||||
*/
|
||||
public function hasWordAndDescription(&$matches)
|
||||
{
|
||||
$regex = '/^\s*' . self::WORD_REGEX . self::DESCRIPTION_REGEX . '/s';
|
||||
return preg_match($regex, $this->getContent(), $matches);
|
||||
}
|
||||
}
|
106
vendor/consolidation/annotated-command/src/Parser/Internal/FullyQualifiedClassCache.php
vendored
Normal file
106
vendor/consolidation/annotated-command/src/Parser/Internal/FullyQualifiedClassCache.php
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
class FullyQualifiedClassCache
|
||||
{
|
||||
protected $classCache = [];
|
||||
protected $namespaceCache = [];
|
||||
|
||||
public function qualify($filename, $className)
|
||||
{
|
||||
$this->primeCache($filename, $className);
|
||||
return $this->cached($filename, $className);
|
||||
}
|
||||
|
||||
protected function cached($filename, $className)
|
||||
{
|
||||
return isset($this->classCache[$filename][$className]) ? $this->classCache[$filename][$className] : $className;
|
||||
}
|
||||
|
||||
protected function primeCache($filename, $className)
|
||||
{
|
||||
// If the cache has already been primed, do no further work
|
||||
if (isset($this->namespaceCache[$filename])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$handle = fopen($filename, "r");
|
||||
if (!$handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$namespaceName = $this->primeNamespaceCache($filename, $handle);
|
||||
$this->primeUseCache($filename, $handle);
|
||||
|
||||
// If there is no 'use' statement for the className, then
|
||||
// generate an effective classname from the namespace
|
||||
if (!isset($this->classCache[$filename][$className])) {
|
||||
$this->classCache[$filename][$className] = $namespaceName . '\\' . $className;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
protected function primeNamespaceCache($filename, $handle)
|
||||
{
|
||||
$namespaceName = $this->readNamespace($handle);
|
||||
if (!$namespaceName) {
|
||||
return false;
|
||||
}
|
||||
$this->namespaceCache[$filename] = $namespaceName;
|
||||
return $namespaceName;
|
||||
}
|
||||
|
||||
protected function primeUseCache($filename, $handle)
|
||||
{
|
||||
$usedClasses = $this->readUseStatements($handle);
|
||||
if (empty($usedClasses)) {
|
||||
return false;
|
||||
}
|
||||
$this->classCache[$filename] = $usedClasses;
|
||||
}
|
||||
|
||||
protected function readNamespace($handle)
|
||||
{
|
||||
$namespaceRegex = '#^\s*namespace\s+#';
|
||||
$line = $this->readNextRelevantLine($handle);
|
||||
if (!$line || !preg_match($namespaceRegex, $line)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$namespaceName = preg_replace($namespaceRegex, '', $line);
|
||||
$namespaceName = rtrim($namespaceName, ';');
|
||||
return $namespaceName;
|
||||
}
|
||||
|
||||
protected function readUseStatements($handle)
|
||||
{
|
||||
$useRegex = '#^\s*use\s+#';
|
||||
$result = [];
|
||||
while (true) {
|
||||
$line = $this->readNextRelevantLine($handle);
|
||||
if (!$line || !preg_match($useRegex, $line)) {
|
||||
return $result;
|
||||
}
|
||||
$usedClass = preg_replace($useRegex, '', $line);
|
||||
$usedClass = rtrim($usedClass, ';');
|
||||
$unqualifiedClass = preg_replace('#.*\\\\#', '', $usedClass);
|
||||
// If this is an aliased class, 'use \Foo\Bar as Baz', then adjust
|
||||
if (strpos($usedClass, ' as ')) {
|
||||
$unqualifiedClass = preg_replace('#.*\sas\s+#', '', $usedClass);
|
||||
$usedClass = preg_replace('#\s+as\s+#', '', $usedClass);
|
||||
}
|
||||
$result[$unqualifiedClass] = $usedClass;
|
||||
}
|
||||
}
|
||||
|
||||
protected function readNextRelevantLine($handle)
|
||||
{
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
if (preg_match('#^\s*\w#', $line)) {
|
||||
return trim($line);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
67
vendor/consolidation/annotated-command/src/Parser/Internal/TagFactory.php
vendored
Normal file
67
vendor/consolidation/annotated-command/src/Parser/Internal/TagFactory.php
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand\Parser\Internal;
|
||||
|
||||
/**
|
||||
* Hold some state. Collect tags.
|
||||
*/
|
||||
class TagFactory
|
||||
{
|
||||
/** @var DocblockTag|null Current tag */
|
||||
protected $current;
|
||||
|
||||
/** @var DocblockTag[] All tag */
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* DocblockTag constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->current = null;
|
||||
$this->tags = [];
|
||||
}
|
||||
|
||||
public function parseLine($line)
|
||||
{
|
||||
if (DocblockTag::isTag($line)) {
|
||||
return $this->createTag($line);
|
||||
}
|
||||
if (empty($line)) {
|
||||
return $this->storeCurrentTag();
|
||||
}
|
||||
return $this->accumulateContent($line);
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
$this->storeCurrentTag();
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
protected function createTag($line)
|
||||
{
|
||||
DocblockTag::splitTagAndContent($line, $matches);
|
||||
$this->storeCurrentTag();
|
||||
$this->current = new DocblockTag($matches['tag'], $matches['description']);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function storeCurrentTag()
|
||||
{
|
||||
if (!$this->current) {
|
||||
return false;
|
||||
}
|
||||
$this->tags[] = $this->current;
|
||||
$this->current = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function accumulateContent($line)
|
||||
{
|
||||
if (!$this->current) {
|
||||
return false;
|
||||
}
|
||||
$this->current->appendContent($line);
|
||||
return true;
|
||||
}
|
||||
}
|
59
vendor/consolidation/annotated-command/tests/FullyQualifiedClassCacheTests.php
vendored
Normal file
59
vendor/consolidation/annotated-command/tests/FullyQualifiedClassCacheTests.php
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\TestUtils\ExampleCommandInfoAlterer;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use \Consolidation\AnnotatedCommand\Parser\Internal\FullyQualifiedClassCache;
|
||||
|
||||
class FullyQualifiedClassCacheTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
function testFqcn()
|
||||
{
|
||||
$reflectionMethod = new \ReflectionMethod('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTableTwo');
|
||||
$filename = $reflectionMethod->getFileName();
|
||||
|
||||
$fqcnCache = new FullyQualifiedClassCache();
|
||||
|
||||
$handle = fopen($filename, "r");
|
||||
$this->assertTrue($handle !== false);
|
||||
|
||||
$namespaceName = $this->callProtected($fqcnCache, 'readNamespace', [$handle]);
|
||||
|
||||
$this->assertEquals('Consolidation\TestUtils\alpha', $namespaceName);
|
||||
|
||||
$usedClasses = $this->callProtected($fqcnCache, 'readUseStatements', [$handle]);
|
||||
|
||||
$this->assertTrue(isset($usedClasses['RowsOfFields']));
|
||||
$this->assertEquals('Consolidation\OutputFormatters\StructuredData\RowsOfFields', $usedClasses['RowsOfFields']);
|
||||
|
||||
fclose($handle);
|
||||
|
||||
$fqcn = $fqcnCache->qualify($filename, 'RowsOfFields');
|
||||
$this->assertEquals('Consolidation\OutputFormatters\StructuredData\RowsOfFields', $fqcn);
|
||||
|
||||
$fqcn = $fqcnCache->qualify($filename, 'ClassWithoutUse');
|
||||
$this->assertEquals('Consolidation\TestUtils\alpha\ClassWithoutUse', $fqcn);
|
||||
|
||||
$fqcn = $fqcnCache->qualify($filename, 'ExampleAliasedClass');
|
||||
$this->assertEquals('Consolidation\TestUtils\ExampleCommandFile', $fqcn);
|
||||
}
|
||||
|
||||
function callProtected($object, $method, $args = [])
|
||||
{
|
||||
$r = new \ReflectionMethod($object, $method);
|
||||
$r->setAccessible(true);
|
||||
return $r->invokeArgs($object, $args);
|
||||
}
|
||||
}
|
26
vendor/consolidation/annotated-command/tests/src/ApplicationWithTerminalWidth.php
vendored
Normal file
26
vendor/consolidation/annotated-command/tests/src/ApplicationWithTerminalWidth.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
class ApplicationWithTerminalWidth extends Application
|
||||
{
|
||||
protected $width = 0;
|
||||
protected $height = 0;
|
||||
|
||||
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
|
||||
{
|
||||
parent::__construct($name, $version);
|
||||
}
|
||||
|
||||
public function setWidthAndHeight($width, $height)
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
public function getTerminalDimensions()
|
||||
{
|
||||
return [ $this->width, $this->height ];
|
||||
}
|
||||
}
|
63
vendor/consolidation/annotated-command/tests/src/ExampleAnnotatedCommand.php
vendored
Normal file
63
vendor/consolidation/annotated-command/tests/src/ExampleAnnotatedCommand.php
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotatedCommand;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Test file used in the Annotation Factory tests. It is also
|
||||
* discovered in the testCommandDiscovery() test.
|
||||
*
|
||||
* The testCommandDiscovery test search base is the 'src' directory;
|
||||
* any command files located immediately inside the search base are
|
||||
* eligible for discovery, and will be included in the search results.
|
||||
*/
|
||||
class ExampleAnnotatedCommand extends AnnotatedCommand
|
||||
{
|
||||
/**
|
||||
* Do the main function of the my:cat command.
|
||||
*/
|
||||
public function myCat($one, $two = '', $multiple = [], $flip = false)
|
||||
{
|
||||
if ($flip) {
|
||||
return "{$two}{$one}" . implode('', array_reverse($multiple));
|
||||
}
|
||||
return "{$one}{$two}" . implode('', $multiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the my:cat command implemented as an AnnotatedCommand subclass.
|
||||
*
|
||||
* 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
|
||||
* @arg string $one The first parameter.
|
||||
* @arg string $two The other parameter.
|
||||
* @default $two ''
|
||||
* @option array $multiple An array of values
|
||||
* @default $multiple []
|
||||
* @option boolean $flip Whether or not the second parameter should come first in the result.
|
||||
* @aliases c
|
||||
* @usage bet alpha --flip
|
||||
* Concatenate "alpha" and "bet".
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$one = $input->getArgument('one');
|
||||
$two = $input->getArgument('two');
|
||||
$multiple = $input->getOption('multiple');
|
||||
$flip = $input->getOption('flip');
|
||||
|
||||
$result = $this->myCat($one, $two, $multiple, $flip);
|
||||
|
||||
// We could also just use $output->writeln($result) here,
|
||||
// but calling processResults enables the use of output
|
||||
// formatters. Note also that if you use processResults, you
|
||||
// should correctly inject the command processor into your
|
||||
// annotated command via AnnotatedCommand::setCommandProcessor().
|
||||
return $this->processResults($input, $output, $result);
|
||||
}
|
||||
}
|
521
vendor/consolidation/annotated-command/tests/src/ExampleCommandFile.php
vendored
Normal file
521
vendor/consolidation/annotated-command/tests/src/ExampleCommandFile.php
vendored
Normal file
|
@ -0,0 +1,521 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandError;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Test file used in the Annotation Factory tests. It is also
|
||||
* discovered in the testCommandDiscovery() test.
|
||||
*
|
||||
* The testCommandDiscovery test search base is the 'src' directory;
|
||||
* any command files located immediately inside the search base are
|
||||
* eligible for discovery, and will be included in the search results.
|
||||
*/
|
||||
class ExampleCommandFile
|
||||
{
|
||||
protected $state;
|
||||
protected $output;
|
||||
|
||||
public function __construct($state = '')
|
||||
{
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
public function setOutput($output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import config from a config directory.
|
||||
*
|
||||
* @command config:import
|
||||
* @param $label A config directory label (i.e. a key in \$config_directories array in settings.php).
|
||||
* @interact-config-label
|
||||
* @option preview Format for displaying proposed changes. Recognized values: list, diff.
|
||||
* @option source An arbitrary directory that holds the configuration files. An alternative to label argument
|
||||
* @option partial Allows for partial config imports from the source directory. Only updates and new configs will be processed with this flag (missing configs will not be deleted).
|
||||
* @aliases cim,config-import
|
||||
*/
|
||||
public function import($label = null, $options = ['preview' => 'list', 'source' => InputOption::VALUE_REQUIRED, 'partial' => false])
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the fibonacci sequence between two numbers.
|
||||
*
|
||||
* Graphic output will look like
|
||||
* +----+---+-------------+
|
||||
* | | | |
|
||||
* | |-+-| |
|
||||
* |----+-+-+ |
|
||||
* | | |
|
||||
* | | |
|
||||
* | | |
|
||||
* +--------+-------------+
|
||||
*
|
||||
* @param int $start Number to start from
|
||||
* @param int $steps Number of steps to perform
|
||||
* @param array $opts
|
||||
* @option $graphic Display the sequence graphically using cube
|
||||
* representation
|
||||
*/
|
||||
public function fibonacci($start, $steps, $opts = ['graphic' => false])
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Code sniffer.
|
||||
*
|
||||
* Run the PHP Codesniffer on a file or directory.
|
||||
*
|
||||
* @param string $file
|
||||
* A file or directory to analyze.
|
||||
* @option $autofix Whether to run the automatic fixer or not.
|
||||
* @option $strict Show warnings as well as errors.
|
||||
* Default is to show only errors.
|
||||
*/
|
||||
public function sniff(
|
||||
$file = 'src',
|
||||
array $options = [
|
||||
'autofix' => false,
|
||||
'strict' => false,
|
||||
]
|
||||
) {
|
||||
return var_export($options, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the my:cat command
|
||||
*
|
||||
* This command will concatenate two parameters. If the --flip flag
|
||||
* is provided, then the result is the concatenation of two and one.
|
||||
*
|
||||
* @param string $one The first parameter.
|
||||
* @param string $two The other parameter.
|
||||
* @option boolean $flip Whether or not the second parameter should come first in the result.
|
||||
* @aliases c
|
||||
* @usage bet alpha --flip
|
||||
* Concatenate "alpha" and "bet".
|
||||
* @arbitrary This annotation is here merely as a marker used in testing.
|
||||
*/
|
||||
public function myCat($one, $two = '', array $options = ['flip' => false])
|
||||
{
|
||||
if ($options['flip']) {
|
||||
return "{$two}{$one}";
|
||||
}
|
||||
return "{$one}{$two}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @command my:repeat
|
||||
*/
|
||||
public function myRepeat($one, $two = '', array $options = ['repeat' => 1])
|
||||
{
|
||||
return str_repeat("{$one}{$two}", $options['repeat']);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the my:join command
|
||||
*
|
||||
* This command will join its parameters together. It can also reverse and repeat its arguments.
|
||||
*
|
||||
* @command my:join
|
||||
* @usage a b
|
||||
* Join a and b to produce "a,b"
|
||||
* @usage
|
||||
* Example with no parameters or options
|
||||
*/
|
||||
public function myJoin(array $args, array $options = ['flip' => false, 'repeat' => 1])
|
||||
{
|
||||
if ($options['flip']) {
|
||||
$args = array_reverse($args);
|
||||
}
|
||||
$result = implode('', $args);
|
||||
return str_repeat($result, $options['repeat']);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a command with no options
|
||||
*
|
||||
* This command will concatenate two parameters.
|
||||
*
|
||||
* @param $one The first parameter.
|
||||
* @param $two The other parameter.
|
||||
* @aliases nope
|
||||
* @usage alpha bet
|
||||
* Concatenate "alpha" and "bet".
|
||||
*/
|
||||
public function commandWithNoOptions($one, $two = 'default')
|
||||
{
|
||||
return "{$one}{$two}";
|
||||
}
|
||||
|
||||
/**
|
||||
* This command work with app's input and output
|
||||
*
|
||||
* @command command:with-io-parameters
|
||||
*/
|
||||
public function commandWithIOParameters(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
return $input->getFirstArgument();
|
||||
}
|
||||
|
||||
/**
|
||||
* This command has no arguments--only options
|
||||
*
|
||||
* Return a result only if not silent.
|
||||
*
|
||||
* @option silent Supress output.
|
||||
*/
|
||||
public function commandWithNoArguments(array $opts = ['silent|s' => false])
|
||||
{
|
||||
if (!$opts['silent']) {
|
||||
return "Hello, world";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut on annotation
|
||||
*
|
||||
* This command defines the option shortcut on the annotation instead of in the options array.
|
||||
*
|
||||
* @param $opts The options
|
||||
* @option silent|s Supress output.
|
||||
*/
|
||||
public function shortcutOnAnnotation(array $opts = ['silent' => false])
|
||||
{
|
||||
if (!$opts['silent']) {
|
||||
return "Hello, world";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the test:arithmatic command
|
||||
*
|
||||
* This command will add one and two. If the --negate flag
|
||||
* is provided, then the result is negated.
|
||||
*
|
||||
* @command test:arithmatic
|
||||
* @param integer $one The first number to add.
|
||||
* @param integer $two The other number to add.
|
||||
* @option negate Whether or not the result should be negated.
|
||||
* @aliases arithmatic
|
||||
* @usage 2 2 --negate
|
||||
* Add two plus two and then negate.
|
||||
* @custom
|
||||
* @dup one
|
||||
* @dup two
|
||||
*/
|
||||
public function testArithmatic($one, $two = 2, array $options = ['negate' => false, 'unused' => 'bob'])
|
||||
{
|
||||
$result = $one + $two;
|
||||
if ($options['negate']) {
|
||||
$result = -$result;
|
||||
}
|
||||
|
||||
// Integer return codes are exit codes (errors), so
|
||||
// return a the result as a string so that it will be printed.
|
||||
return "$result";
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the test:state command
|
||||
*
|
||||
* This command tests to see if the state of the Commandfile instance
|
||||
*/
|
||||
public function testState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the test:passthrough command
|
||||
*
|
||||
* This command takes a variable number of parameters as
|
||||
* an array and returns them as a csv.
|
||||
*/
|
||||
public function testPassthrough(array $params)
|
||||
{
|
||||
return implode(',', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* This command wraps its parameter in []; its alter hook
|
||||
* then wraps the result in <>.
|
||||
*/
|
||||
public function testHook($parameter)
|
||||
{
|
||||
return "[$parameter]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the results of test:hook in <>.
|
||||
*
|
||||
* @hook alter test:hook
|
||||
*/
|
||||
public function hookTestHook($result)
|
||||
{
|
||||
return "<$result>";
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is very similar to the preceding test, except
|
||||
* it uses an annotation hook instead of a named-function hook.
|
||||
*
|
||||
* @hookme
|
||||
* @before >
|
||||
* @after <
|
||||
*/
|
||||
public function testAnnotationHook($parameter)
|
||||
{
|
||||
return "($parameter)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the results of test:hook in whatever the @before and @after
|
||||
* annotations contain.
|
||||
*
|
||||
* @hook alter @hookme
|
||||
*/
|
||||
public function hookTestAnnotatedHook($result, CommandData $commandData)
|
||||
{
|
||||
$before = $commandData->annotationData()->get('before', '-');
|
||||
$after = $commandData->annotationData()->get('after', '-');
|
||||
return "$before$result$after";
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the results of the hook with its command name.
|
||||
*
|
||||
* @hook alter @addmycommandname
|
||||
*/
|
||||
public function hookAddCommandName($result, CommandData $commandData)
|
||||
{
|
||||
$annotationData = $commandData->annotationData();
|
||||
return "$result from " . $annotationData['command'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Here is a hook with an explicit command annotation that we will alter
|
||||
* with the preceeding hook
|
||||
*
|
||||
* @command alter-me
|
||||
* @addmycommandname
|
||||
*/
|
||||
public function alterMe()
|
||||
{
|
||||
return "splendiferous";
|
||||
}
|
||||
|
||||
/**
|
||||
* Here is another hook that has no command annotation that should be
|
||||
* altered with the default value for the command name
|
||||
*
|
||||
* @addmycommandname
|
||||
*/
|
||||
public function alterMeToo()
|
||||
{
|
||||
return "fantabulous";
|
||||
}
|
||||
|
||||
/**
|
||||
* @command test:replace-command
|
||||
*/
|
||||
public function testReplaceCommand($value)
|
||||
{
|
||||
$this->output->writeln($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook replace-command test:replace-command
|
||||
*/
|
||||
public function hookTestReplaceCommandHook($value)
|
||||
{
|
||||
$this->output->writeln("bar");
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook pre-command test:post-command
|
||||
*/
|
||||
public function hookTestPreCommandHook(CommandData $commandData)
|
||||
{
|
||||
// Use 'writeln' to detect order that hooks are called
|
||||
$this->output->writeln("foo");
|
||||
}
|
||||
|
||||
/**
|
||||
* @command test:post-command
|
||||
*/
|
||||
public function testPostCommand($value)
|
||||
{
|
||||
$this->output->writeln($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook post-command test:post-command
|
||||
*/
|
||||
public function hookTestPostCommandHook($result, CommandData $commandData)
|
||||
{
|
||||
// Use 'writeln' to detect order that hooks are called
|
||||
$this->output->writeln("baz");
|
||||
}
|
||||
|
||||
public function testHello($who)
|
||||
{
|
||||
return "Hello, $who.";
|
||||
}
|
||||
|
||||
public function testException($what)
|
||||
{
|
||||
throw new \Exception($what);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook init test:hello
|
||||
*/
|
||||
public function initializeTestHello($input, AnnotationData $annotationData)
|
||||
{
|
||||
$who = $input->getArgument('who');
|
||||
if (!$who) {
|
||||
$input->setArgument('who', 'Huey');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook command-event test:hello
|
||||
*/
|
||||
public function commandEventTestHello(ConsoleCommandEvent $event)
|
||||
{
|
||||
// Note that Symfony Console will not allow us to alter the
|
||||
// input from this hook, so we'll just print something to
|
||||
// show that this hook was executed.
|
||||
$input = $event->getInput();
|
||||
$who = $input->getArgument('who');
|
||||
$this->output->writeln("Here comes $who!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook interact test:hello
|
||||
*/
|
||||
public function interactTestHello($input, $output)
|
||||
{
|
||||
$who = $input->getArgument('who');
|
||||
if (!$who) {
|
||||
$input->setArgument('who', 'Goofey');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook validate test:hello
|
||||
*/
|
||||
public function validateTestHello($commandData)
|
||||
{
|
||||
$args = $commandData->arguments();
|
||||
if ($args['who'] == 'Donald Duck') {
|
||||
return new CommandError("I won't say hello to Donald Duck.");
|
||||
}
|
||||
if ($args['who'] == 'Drumph') {
|
||||
throw new \Exception('Irrational value error.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default values in arguments
|
||||
*
|
||||
* @param string|null $one
|
||||
* @param string|null $two
|
||||
* @return string
|
||||
*/
|
||||
public function defaults($one = null, $two = null)
|
||||
{
|
||||
if ($one && $two) {
|
||||
return "$one and $two";
|
||||
}
|
||||
if ($one) {
|
||||
return "only $one";
|
||||
}
|
||||
return "nothing provided";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultOptionOne(array $options = ['foo' => '1'])
|
||||
{
|
||||
return "Foo is " . $options['foo'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultOptionTwo(array $options = ['foo' => '2'])
|
||||
{
|
||||
return "Foo is " . $options['foo'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultOptionNone(array $options = ['foo' => InputOption::VALUE_REQUIRED])
|
||||
{
|
||||
return "Foo is " . $options['foo'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultOptionalValue(array $options = ['foo' => InputOption::VALUE_OPTIONAL])
|
||||
{
|
||||
return "Foo is " . var_export($options['foo'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultOptionDefaultsToTrue(array $options = ['foo' => true])
|
||||
{
|
||||
return "Foo is " . var_export($options['foo'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the test:required-array-option command
|
||||
*
|
||||
* This command will print all the valused of passed option
|
||||
*
|
||||
* @param array $opts
|
||||
* @return string
|
||||
*/
|
||||
public function testRequiredArrayOption(array $opts = ['arr|a' => []])
|
||||
{
|
||||
return implode(' ', $opts['arr']);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the test:array-option command
|
||||
*
|
||||
* This command will print all the valused of passed option
|
||||
*
|
||||
* @param array $opts
|
||||
* @return string
|
||||
*/
|
||||
public function testArrayOption(array $opts = ['arr|a' => ['1', '2', '3']])
|
||||
{
|
||||
return implode(' ', $opts['arr']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @command global-options-only
|
||||
*/
|
||||
public function globalOptionsOnly($arg, array $options = [])
|
||||
{
|
||||
return "Arg is $arg, options[help] is " . var_export($options['help'], true) . "\n";
|
||||
}
|
||||
}
|
15
vendor/consolidation/annotated-command/tests/src/ExampleCommandInfoAlterer.php
vendored
Normal file
15
vendor/consolidation/annotated-command/tests/src/ExampleCommandInfoAlterer.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\AnnotatedCommand\CommandInfoAltererInterface;
|
||||
|
||||
class ExampleCommandInfoAlterer implements CommandInfoAltererInterface
|
||||
{
|
||||
public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance)
|
||||
{
|
||||
if ($commandInfo->hasAnnotation('arbitrary')) {
|
||||
$commandInfo->addAnnotation('dynamic', "This annotation was dynamically added by ExampleCommandInfoAlterer");
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/consolidation/annotated-command/tests/src/ExampleHookAllCommandFile.php
vendored
Normal file
41
vendor/consolidation/annotated-command/tests/src/ExampleHookAllCommandFile.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Consolidation\AnnotatedCommand\CommandError;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ExampleHookAllCommandFile
|
||||
{
|
||||
public function doCat($one, $two = '', $options = ['flip' => false])
|
||||
{
|
||||
if ($options['flip']) {
|
||||
return "{$two}{$one}";
|
||||
}
|
||||
return "{$one}{$two}";
|
||||
}
|
||||
|
||||
public function doRepeat($one, $two = '', $options = ['repeat' => 1])
|
||||
{
|
||||
return str_repeat("{$one}{$two}", $options['repeat']);
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook function does not specify which command or annotation
|
||||
* it is hooking; that makes it apply to every command in the same class.
|
||||
*
|
||||
* @hook alter
|
||||
*/
|
||||
public function alterAllCommands($result)
|
||||
{
|
||||
if (is_string($result)) {
|
||||
$result = "*** $result ***";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
50
vendor/consolidation/annotated-command/tests/src/InMemoryCacheStore.php
vendored
Normal file
50
vendor/consolidation/annotated-command/tests/src/InMemoryCacheStore.php
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Cache\SimpleCacheInterface;
|
||||
|
||||
/**
|
||||
* A simple in-memory cache for testing
|
||||
*/
|
||||
class InMemoryCacheStore implements SimpleCacheInterface
|
||||
{
|
||||
protected $cache;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cache = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for an entry from the cache
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return array_key_exists($key, $this->cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an entry from the cache
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (!$this->has($key)) {
|
||||
return [];
|
||||
}
|
||||
return $this->cache[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an entry in the cache
|
||||
* @param string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function set($key, $data)
|
||||
{
|
||||
$this->cache[$key] = $data;
|
||||
}
|
||||
}
|
22
vendor/consolidation/annotated-command/tests/src/TestTerminal.php
vendored
Normal file
22
vendor/consolidation/annotated-command/tests/src/TestTerminal.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
class TestTerminal
|
||||
{
|
||||
protected $width = 0;
|
||||
|
||||
public function __construct($width)
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
public function setWidth($width)
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
}
|
325
vendor/consolidation/annotated-command/tests/src/alpha/AlphaCommandFile.php
vendored
Normal file
325
vendor/consolidation/annotated-command/tests/src/alpha/AlphaCommandFile.php
vendored
Normal file
|
@ -0,0 +1,325 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils\alpha;
|
||||
|
||||
use Consolidation\AnnotatedCommand\CommandError;
|
||||
use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
|
||||
use Consolidation\OutputFormatters\StructuredData\AssociativeList;
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface;
|
||||
use Consolidation\AnnotatedCommand\Events\CustomEventAwareTrait;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
use Consolidation\TestUtils\ExampleCommandFile as ExampleAliasedClass;
|
||||
|
||||
/**
|
||||
* Test file used in the testCommandDiscovery() test.
|
||||
*
|
||||
* This commandfile is found by the test. The test search base is the
|
||||
* 'src' directory, and 'alpha' is one of the search directories available
|
||||
* for searching.
|
||||
*/
|
||||
class AlphaCommandFile implements CustomEventAwareInterface
|
||||
{
|
||||
use CustomEventAwareTrait;
|
||||
|
||||
/**
|
||||
* @command always:fail
|
||||
*/
|
||||
public function alwaysFail()
|
||||
{
|
||||
return new CommandError('This command always fails.', 13);
|
||||
}
|
||||
|
||||
public static function ignoredStaticMethod()
|
||||
{
|
||||
return 'This method is static; it should not generate a command.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @command simulated:status
|
||||
*/
|
||||
public function simulatedStatus()
|
||||
{
|
||||
return ['status-code' => 42];
|
||||
}
|
||||
|
||||
/**
|
||||
* @command example:output
|
||||
*/
|
||||
public function exampleOutput()
|
||||
{
|
||||
return 'Hello, World.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @command example:cat
|
||||
*/
|
||||
public function exampleCat($one, $two = '', $options = ['flip' => false])
|
||||
{
|
||||
if ($options['flip']) {
|
||||
return "{$two}{$one}";
|
||||
}
|
||||
return "{$one}{$two}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @command example:echo
|
||||
*/
|
||||
public function exampleEcho(array $args)
|
||||
{
|
||||
return ['item-list' => $args];
|
||||
}
|
||||
|
||||
/**
|
||||
* @command example:message
|
||||
*/
|
||||
public function exampleMessage()
|
||||
{
|
||||
return ['message' => 'Shipwrecked; send bananas.'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test command with formatters
|
||||
*
|
||||
* @command example:table
|
||||
* @param $unused An unused argument
|
||||
* @field-labels
|
||||
* first: I
|
||||
* second: II
|
||||
* third: III
|
||||
* @usage example:table --format=yml
|
||||
* Show the example table in yml format.
|
||||
* @usage example:table --fields=first,third
|
||||
* Show only the first and third fields in the table.
|
||||
* @usage example:table --fields=II,III
|
||||
* Note that either the field ID or the visible field label may be used.
|
||||
* @aliases extab
|
||||
* @topics docs-tables
|
||||
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields Fully-qualified class name
|
||||
*/
|
||||
public function exampleTable($unused = '', $options = ['format' => 'table', 'fields' => ''])
|
||||
{
|
||||
$outputData = [
|
||||
[ 'first' => 'One', 'second' => 'Two', 'third' => 'Three' ],
|
||||
[ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei' ],
|
||||
[ 'first' => 'Ichi', 'second' => 'Ni', 'third' => 'San' ],
|
||||
[ 'first' => 'Uno', 'second' => 'Dos', 'third' => 'Tres' ],
|
||||
];
|
||||
return new RowsOfFields($outputData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test command with formatters using a short classname in @return
|
||||
*
|
||||
* @command example:table2
|
||||
* @param $unused An unused argument
|
||||
* @field-labels
|
||||
* first: I
|
||||
* second: II
|
||||
* third: III
|
||||
* @usage example:table --format=yml
|
||||
* Show the example table in yml format.
|
||||
* @usage example:table --fields=first,third
|
||||
* Show only the first and third fields in the table.
|
||||
* @usage example:table --fields=II,III
|
||||
* Note that either the field ID or the visible field label may be used.
|
||||
* @aliases extab
|
||||
* @topics docs-tables
|
||||
* @return RowsOfFields Short class names are converted to fqcns
|
||||
*/
|
||||
public function exampleTableTwo($unused = '', $options = ['format' => 'table', 'fields' => ''])
|
||||
{
|
||||
$outputData = [
|
||||
[ 'first' => 'One', 'second' => 'Two', 'third' => 'Three' ],
|
||||
[ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei' ],
|
||||
[ 'first' => 'Ichi', 'second' => 'Ni', 'third' => 'San' ],
|
||||
[ 'first' => 'Uno', 'second' => 'Dos', 'third' => 'Tres' ],
|
||||
];
|
||||
return new RowsOfFields($outputData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test word wrapping
|
||||
*
|
||||
* @command example:wrap
|
||||
* @field-labels
|
||||
* first: First
|
||||
* second: Second
|
||||
*
|
||||
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
|
||||
*/
|
||||
public function exampleWrap()
|
||||
{
|
||||
$data = [
|
||||
[
|
||||
'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
|
||||
'second' => 'This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.',
|
||||
]
|
||||
];
|
||||
return new RowsOfFields($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook option example:table
|
||||
*/
|
||||
public function additionalOptionForExampleTable(Command $command, AnnotationData $annotationData)
|
||||
{
|
||||
$command->addOption(
|
||||
'dynamic',
|
||||
'',
|
||||
InputOption::VALUE_NONE,
|
||||
'Option added by @hook option example:table'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Demonstrate an alter hook with an option
|
||||
*
|
||||
* @hook alter example:table
|
||||
* @option french Add a row with French numbers.
|
||||
* @usage example:table --french
|
||||
*/
|
||||
public function alterFormatters($result, CommandData $commandData)
|
||||
{
|
||||
if ($commandData->input()->getOption('french')) {
|
||||
$result[] = [ 'first' => 'Un', 'second' => 'Deux', 'third' => 'Trois' ];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test command with formatters using an associative list
|
||||
*
|
||||
* @command example:list
|
||||
* @field-labels
|
||||
* sftp_command: SFTP Command
|
||||
* sftp_username: SFTP Username
|
||||
* sftp_host: SFTP Host
|
||||
* sftp_password: SFTP Password
|
||||
* sftp_url: SFTP URL
|
||||
* git_command: Git Command
|
||||
* git_username: Git Username
|
||||
* git_host: Git Host
|
||||
* git_port: Git Port
|
||||
* git_url: Git URL
|
||||
* mysql_command: MySQL Command
|
||||
* mysql_username: MySQL Username
|
||||
* mysql_host: MySQL Host
|
||||
* mysql_password: MySQL Password
|
||||
* mysql_url: MySQL URL
|
||||
* mysql_port: MySQL Port
|
||||
* mysql_database: MySQL Database
|
||||
* redis_command: Redis Command
|
||||
* redis_port: Redis Port
|
||||
* redis_url: Redis URL
|
||||
* redis_password: Redis Password
|
||||
* @default-fields *_command
|
||||
* @return \Consolidation\OutputFormatters\StructuredData\AssociativeList
|
||||
*/
|
||||
public function exampleAssociativeList()
|
||||
{
|
||||
$outputData = [
|
||||
'sftp_command' => 'sftp -o Port=2222 dev@appserver.dev.drush.in',
|
||||
'sftp_username' => 'dev',
|
||||
'sftp_host' => 'appserver.dev.drush.in',
|
||||
'sftp_password' => 'Use your account password',
|
||||
'sftp_url' => 'sftp://dev@appserver.dev.drush.in:2222',
|
||||
'git_command' => 'git clone ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git wp-update',
|
||||
'git_username' => 'codeserver.dev',
|
||||
'git_host' => 'codeserver.dev.drush.in',
|
||||
'git_port' => 2222,
|
||||
'git_url' => 'ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git',
|
||||
'mysql_command' => 'mysql -u pantheon -p4b33cb -h dbserver.dev.drush.in -P 16191 pantheon',
|
||||
'mysql_username' => 'pantheon',
|
||||
'mysql_host' => 'dbserver.dev.drush.in',
|
||||
'mysql_password' => '4b33cb',
|
||||
'mysql_url' => 'mysql://pantheon:4b33cb@dbserver.dev.drush.in:16191/pantheon',
|
||||
'mysql_port' => 16191,
|
||||
'mysql_database' => 'pantheon',
|
||||
];
|
||||
return new AssociativeList($outputData);
|
||||
}
|
||||
|
||||
/**
|
||||
* This command has no annotations; this means that it will not be
|
||||
* found when createCommandsFromClass() is called with
|
||||
* '$includeAllPublicMethods' set to false.
|
||||
*/
|
||||
public function withoutAnnotations()
|
||||
{
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* @command command:with-one-optional-argument
|
||||
*
|
||||
* This command has just one optional argument.
|
||||
*
|
||||
* Return a result only if not silent.
|
||||
*
|
||||
* @option silent Supress output.
|
||||
*/
|
||||
public function commandWithOneOptionalArgument($who = 'world', $opts = ['silent|s' => false])
|
||||
{
|
||||
if (!$opts['silent']) {
|
||||
return "Hello, $who";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be a command, because it is annotated like one.
|
||||
*
|
||||
* @command get:serious
|
||||
*/
|
||||
public function getSerious()
|
||||
{
|
||||
return 'very serious';
|
||||
}
|
||||
|
||||
/**
|
||||
* This should not be a command, because it looks like an accessor and
|
||||
* has no @command annotation.
|
||||
*/
|
||||
public function getLost()
|
||||
{
|
||||
return 'very lost';
|
||||
}
|
||||
|
||||
/**
|
||||
* This command uses a custom event 'my-event' to collect data. Note that
|
||||
* the event handlers will not be found unless the hook manager is
|
||||
* injected into this command handler object via `setHookManager()`
|
||||
* (defined in CustomEventAwareTrait).
|
||||
*
|
||||
* @command use:event
|
||||
*/
|
||||
public function useEvent()
|
||||
{
|
||||
$myEventHandlers = $this->getCustomEventHandlers('my-event');
|
||||
$result = [];
|
||||
foreach ($myEventHandlers as $handler) {
|
||||
$result[] = $handler();
|
||||
}
|
||||
sort($result);
|
||||
return implode(',', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook on-event my-event
|
||||
*/
|
||||
public function hookOne()
|
||||
{
|
||||
return 'one';
|
||||
}
|
||||
|
||||
/**
|
||||
* @hook on-event my-event
|
||||
*/
|
||||
public function hookTwo()
|
||||
{
|
||||
return 'two';
|
||||
}
|
||||
}
|
14
vendor/consolidation/annotated-command/tests/src/alpha/Exclude/ExcludedCommandFile.php
vendored
Normal file
14
vendor/consolidation/annotated-command/tests/src/alpha/Exclude/ExcludedCommandFile.php
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils\alpha\Exclude;
|
||||
|
||||
/**
|
||||
* Test file used in the testCommandDiscovery() test.
|
||||
*
|
||||
* This commandfile is NOT found by the test. It is in a searched
|
||||
* location (@see Consolidation\TestUtils\alpha\Exclude\IncludedCommandFile),
|
||||
* but it is in a folder named 'Exclude', which is excluded form search.
|
||||
*/
|
||||
class ExcludedCommandFile
|
||||
{
|
||||
|
||||
}
|
16
vendor/consolidation/annotated-command/tests/src/alpha/Inclusive/IncludedCommandFile.php
vendored
Normal file
16
vendor/consolidation/annotated-command/tests/src/alpha/Inclusive/IncludedCommandFile.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils\alpha\Inclusive;
|
||||
|
||||
/**
|
||||
* Test file used in the testCommandDiscovery() test.
|
||||
*
|
||||
* This commandfile is found by the test. The test search base is the
|
||||
* 'src' directory, and 'alpha' is one of the search directories available
|
||||
* for searching. Directories such as this in the search locations list
|
||||
* are searched deeply (to a depth of two), so command files may be
|
||||
* organized into sub-namespaces, if desired.
|
||||
*/
|
||||
class IncludedCommandFile
|
||||
{
|
||||
|
||||
}
|
52
vendor/consolidation/annotated-command/tests/src/beta/BetaCommandFile.php
vendored
Normal file
52
vendor/consolidation/annotated-command/tests/src/beta/BetaCommandFile.php
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
namespace Consolidation\TestUtils\beta;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
|
||||
/**
|
||||
* Test file used in the testCommandDiscovery() test.
|
||||
*
|
||||
* This commandfile is not found by the test. The test search base is the
|
||||
* 'src' directory, but 'beta' is NOT one of the search directories available
|
||||
* for searching, so nothing in this folder will be examined.
|
||||
*/
|
||||
class BetaCommandFile
|
||||
{
|
||||
public function unavailableCommand()
|
||||
{
|
||||
return 'This command is not available, because this commandfile is not in a location that is searched by the tests.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Demonstrate an alter hook with an option
|
||||
*
|
||||
* @hook alter example:table
|
||||
* @option chinese Add a row with Chinese numbers.
|
||||
* @usage example:table --chinese
|
||||
*/
|
||||
public function alterFormattersChinese($result, CommandData $commandData)
|
||||
{
|
||||
if ($commandData->input()->getOption('chinese')) {
|
||||
$result[] = [ 'first' => '壹', 'second' => '貳', 'third' => '叁' ];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demonstrate an alter hook with an option
|
||||
*
|
||||
* @hook alter *
|
||||
* @option kanji Add a row with Kanji numbers.
|
||||
* @usage example:table --kanji
|
||||
*/
|
||||
public function alterFormattersKanji($result, CommandData $commandData)
|
||||
{
|
||||
if ($commandData->input()->getOption('kanji')) {
|
||||
$result[] = [ 'first' => '一', 'second' => '二', 'third' => '三' ];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
45
vendor/consolidation/annotated-command/tests/testAnnotatedCommand.php
vendored
Normal file
45
vendor/consolidation/annotated-command/tests/testAnnotatedCommand.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
class AnnotatedCommandTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
function testMyCatCommand()
|
||||
{
|
||||
$command = new \Consolidation\TestUtils\ExampleAnnotatedCommand();
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('my:cat', $command->getName());
|
||||
$this->assertEquals('This is the my:cat command implemented as an AnnotatedCommand subclass.', $command->getDescription());
|
||||
$this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp());
|
||||
$this->assertEquals('c', implode(',', $command->getAliases()));
|
||||
// Symfony Console composes the synopsis; perhaps we should not test it. Remove if this gives false failures.
|
||||
$this->assertEquals('my:cat [--multiple MULTIPLE] [--flip] [--] <one> [<two>]', $command->getSynopsis());
|
||||
$this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages()));
|
||||
|
||||
$input = new StringInput('my:cat b alpha --multiple=t --multiple=e --flip');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet');
|
||||
}
|
||||
|
||||
// TODO: Make a base test class to hold this.
|
||||
function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0)
|
||||
{
|
||||
$output = new BufferedOutput();
|
||||
|
||||
$application = new Application('TestApplication', '0.0.0');
|
||||
$application->setAutoExit(false);
|
||||
$application->add($command);
|
||||
|
||||
$statusCode = $application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
$this->assertEquals($expectedOutput, $commandOutput);
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
}
|
986
vendor/consolidation/annotated-command/tests/testAnnotatedCommandFactory.php
vendored
Normal file
986
vendor/consolidation/annotated-command/tests/testAnnotatedCommandFactory.php
vendored
Normal file
|
@ -0,0 +1,986 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\TestUtils\ExampleCommandInfoAlterer;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $commandFileInstance;
|
||||
protected $commandFactory;
|
||||
|
||||
function testFibonacci()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'fibonacci');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('fibonacci', $command->getName());
|
||||
$this->assertEquals('fibonacci [--graphic] [--] <start> <steps>', $command->getSynopsis());
|
||||
$this->assertEquals('Calculate the fibonacci sequence between two numbers.', $command->getDescription());
|
||||
$this->assertEquals("Graphic output will look like
|
||||
+----+---+-------------+
|
||||
| | | |
|
||||
| |-+-| |
|
||||
|----+-+-+ |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
+--------+-------------+", $command->getHelp());
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
|
||||
$input = new StringInput('help fibonacci');
|
||||
$this->assertRunCommandViaApplicationContains($command, $input, ['Display the sequence graphically using cube representation']);
|
||||
}
|
||||
|
||||
function testSniff()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'sniff');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('sniff', $command->getName());
|
||||
$this->assertEquals('sniff [--autofix] [--strict] [--] [<file>]', $command->getSynopsis());
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
|
||||
$input = new StringInput('help sniff');
|
||||
$this->assertRunCommandViaApplicationContains($command, $input, ['A file or directory to analyze.']);
|
||||
|
||||
$input = new StringInput('sniff --autofix --strict -- foo');
|
||||
$this->assertRunCommandViaApplicationContains($command, $input, ["'autofix' => true",
|
||||
"'strict' => true"]);
|
||||
}
|
||||
|
||||
function testOptionDefaultValue()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionOne');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('default:option-one', $command->getName());
|
||||
$this->assertEquals('default:option-one [--foo [FOO]]', $command->getSynopsis());
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
|
||||
$input = new StringInput('default:option-one');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is 1');
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionTwo');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('default:option-two', $command->getName());
|
||||
$this->assertEquals('default:option-two [--foo [FOO]]', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('default:option-two');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is 2');
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionNone');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('default:option-none', $command->getName());
|
||||
$this->assertEquals('default:option-none [--foo FOO]', $command->getSynopsis());
|
||||
|
||||
// Skip failing test until Symfony is fixed.
|
||||
$this->markTestSkipped('Symfony Console 3.2.5 and 3.2.6 do not handle default options with required values correctly.');
|
||||
|
||||
$input = new StringInput('default:option-none --foo');
|
||||
$this->assertRunCommandViaApplicationContains($command, $input, ['The "--foo" option requires a value.'], 1);
|
||||
}
|
||||
|
||||
function testGlobalOptionsOnly()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'globalOptionsOnly');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$input = new StringInput('global-options-only test');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Arg is test, options[help] is false");
|
||||
}
|
||||
|
||||
function testOptionWithOptionalValue()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionalValue');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
// Test to see if we can differentiate between a missing option, and
|
||||
// an option that has no value at all.
|
||||
$input = new StringInput('default:optional-value --foo=bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Foo is 'bar'");
|
||||
|
||||
$input = new StringInput('default:optional-value --foo');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true');
|
||||
|
||||
$input = new StringInput('default:optional-value');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is NULL');
|
||||
}
|
||||
|
||||
function testOptionThatDefaultsToTrue()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionDefaultsToTrue');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
// Test to see if we can differentiate between a missing option, and
|
||||
// an option that has no value at all.
|
||||
$input = new StringInput('default:option-defaults-to-true --foo=bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Foo is 'bar'");
|
||||
|
||||
$input = new StringInput('default:option-defaults-to-true --foo');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true');
|
||||
|
||||
$input = new StringInput('default:option-defaults-to-true');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true');
|
||||
|
||||
$input = new StringInput('help default:option-defaults-to-true');
|
||||
$this->assertRunCommandViaApplicationContains(
|
||||
$command,
|
||||
$input,
|
||||
[
|
||||
'--no-foo',
|
||||
'Negate --foo option',
|
||||
]
|
||||
);
|
||||
$input = new StringInput('default:option-defaults-to-true --no-foo');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is false');
|
||||
}
|
||||
/**
|
||||
* Test CommandInfo command caching.
|
||||
*
|
||||
* Sequence:
|
||||
* - Create all of the command info objects from one class, caching them.
|
||||
* - Change the method name of one of the items in the cache to a non-existent method
|
||||
* - Restore all of the cached commandinfo objects
|
||||
* - Ensure that the non-existent method cached commandinfo was not created
|
||||
* - Ensure that the now-missing cached commandinfo was still created
|
||||
*
|
||||
* This tests both save/restore, plus adding a new command method to
|
||||
* a class, and removing a command method from a class.
|
||||
*/
|
||||
function testAnnotatedCommandCache()
|
||||
{
|
||||
$testCacheStore = new \Consolidation\TestUtils\InMemoryCacheStore();
|
||||
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$this->commandFactory->setDataStore($testCacheStore);
|
||||
|
||||
// Make commandInfo objects for every command in the test commandfile.
|
||||
// These will also be stored in our cache.
|
||||
$commandInfoList = $this->commandFactory->getCommandInfoListFromClass($this->commandFileInstance);
|
||||
|
||||
$cachedClassName = get_class($this->commandFileInstance);
|
||||
|
||||
$this->assertTrue($testCacheStore->has($cachedClassName));
|
||||
|
||||
$cachedData = $testCacheStore->get($cachedClassName);
|
||||
$this->assertFalse(empty($cachedData));
|
||||
$this->assertTrue(array_key_exists('testArithmatic', $cachedData));
|
||||
|
||||
$alterCommandInfoCache = $cachedData['testArithmatic'];
|
||||
unset($cachedData['testArithmatic']);
|
||||
$alterCommandInfoCache['method_name'] = 'nonExistentMethod';
|
||||
$cachedData[$alterCommandInfoCache['method_name']] = $alterCommandInfoCache;
|
||||
|
||||
$testCacheStore->set($cachedClassName, $cachedData);
|
||||
|
||||
$restoredCommandInfoList = $this->commandFactory->getCommandInfoListFromClass($this->commandFileInstance);
|
||||
|
||||
$rebuiltCachedData = $testCacheStore->get($cachedClassName);
|
||||
|
||||
$this->assertFalse(empty($rebuiltCachedData));
|
||||
$this->assertTrue(array_key_exists('testArithmatic', $rebuiltCachedData));
|
||||
$this->assertFalse(array_key_exists('nonExistentMethod', $rebuiltCachedData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CommandInfo command annotation parsing.
|
||||
*/
|
||||
function testAnnotatedCommandCreation()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testArithmatic');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:arithmatic', $command->getName());
|
||||
$this->assertEquals('This is the test:arithmatic command', $command->getDescription());
|
||||
$this->assertEquals("This command will add one and two. If the --negate flag\nis provided, then the result is negated.", $command->getHelp());
|
||||
$this->assertEquals('arithmatic', implode(',', $command->getAliases()));
|
||||
$this->assertEquals('test:arithmatic [--negate] [--unused [UNUSED]] [--] <one> [<two>]', $command->getSynopsis());
|
||||
$this->assertEquals('test:arithmatic 2 2 --negate', implode(',', $command->getUsages()));
|
||||
|
||||
$input = new StringInput('arithmatic 2 3 --negate');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '-5');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CommandInfo command annotation altering.
|
||||
*/
|
||||
function testAnnotatedCommandInfoAlteration()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$annotationData = $command->getAnnotationData();
|
||||
$this->assertTrue($annotationData->has('arbitrary'));
|
||||
$this->assertFalse($annotationData->has('dynamic'));
|
||||
|
||||
$this->commandFactory->addCommandInfoAlterer(new ExampleCommandInfoAlterer());
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$annotationData = $command->getAnnotationData();
|
||||
$this->assertTrue($annotationData->has('arbitrary'));
|
||||
$this->assertTrue($annotationData->has('dynamic'));
|
||||
}
|
||||
|
||||
function testMyCatCommand()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('my:cat', $command->getName());
|
||||
$this->assertEquals('This is the my:cat command', $command->getDescription());
|
||||
$this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp());
|
||||
$this->assertEquals('c', implode(',', $command->getAliases()));
|
||||
$this->assertEquals('my:cat [--flip] [--] <one> [<two>]', $command->getSynopsis());
|
||||
$this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages()));
|
||||
|
||||
$input = new StringInput('my:cat bet alpha --flip');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet');
|
||||
}
|
||||
|
||||
function testJoinCommandHelp()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('my:join', $command->getName());
|
||||
$this->assertEquals('This is the my:join command', $command->getDescription());
|
||||
$this->assertEquals("This command will join its parameters together. It can also reverse and repeat its arguments.", $command->getHelp());
|
||||
$this->assertEquals('my:join [--flip] [--repeat [REPEAT]] [--] [<args>]...', $command->getSynopsis());
|
||||
|
||||
// TODO: Extra whitespace character if there are no options et. al. in the
|
||||
// usage. This is uncommon, and the defect is invisible. Maybe find it someday.
|
||||
$actualUsages = implode(',', $command->getUsages());
|
||||
$this->assertEquals('my:join a b,my:join ', $actualUsages);
|
||||
|
||||
$input = new StringInput('my:join bet alpha --flip --repeat=2');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabetalphabet');
|
||||
}
|
||||
|
||||
function testDefaultsCommand()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaults');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('defaults', $command->getName());
|
||||
$this->assertEquals('Test default values in arguments', $command->getDescription());
|
||||
|
||||
$input = new StringInput('defaults');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'nothing provided');
|
||||
|
||||
$input = new StringInput('defaults ichi');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'only ichi');
|
||||
|
||||
$input = new StringInput('defaults I II');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'I and II');
|
||||
}
|
||||
|
||||
function testCommandWithNoOptions()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoOptions');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('command:with-no-options', $command->getName());
|
||||
$this->assertEquals('This is a command with no options', $command->getDescription());
|
||||
$this->assertEquals("This command will concatenate two parameters.", $command->getHelp());
|
||||
$this->assertEquals('nope', implode(',', $command->getAliases()));
|
||||
$this->assertEquals('command:with-no-options <one> [<two>]', $command->getSynopsis());
|
||||
$this->assertEquals('command:with-no-options alpha bet', implode(',', $command->getUsages()));
|
||||
|
||||
$input = new StringInput('command:with-no-options something');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'somethingdefault');
|
||||
|
||||
$input = new StringInput('help command:with-no-options something');
|
||||
$this->assertRunCommandViaApplicationContains(
|
||||
$command,
|
||||
$input,
|
||||
[
|
||||
'The first parameter.',
|
||||
'The other parameter.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
function testCommandWithIOParameters()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithIOParameters');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('command:with-io-parameters', $command->getName());
|
||||
$this->assertEquals("This command work with app's input and output", $command->getDescription());
|
||||
$this->assertEquals('', $command->getHelp());
|
||||
$this->assertEquals('command:with-io-parameters', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('command:with-io-parameters');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'command:with-io-parameters');
|
||||
}
|
||||
|
||||
function testCommandWithNoArguments()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoArguments');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('command:with-no-arguments', $command->getName());
|
||||
$this->assertEquals('This command has no arguments--only options', $command->getDescription());
|
||||
$this->assertEquals("Return a result only if not silent.", $command->getHelp());
|
||||
$this->assertEquals('command:with-no-arguments [-s|--silent]', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('command:with-no-arguments');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world');
|
||||
$input = new StringInput('command:with-no-arguments -s');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '');
|
||||
$input = new StringInput('command:with-no-arguments --silent');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '');
|
||||
}
|
||||
|
||||
function testCommandWithShortcutOnAnnotation()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'shortcutOnAnnotation');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('shortcut:on-annotation', $command->getName());
|
||||
$this->assertEquals('Shortcut on annotation', $command->getDescription());
|
||||
$this->assertEquals("This command defines the option shortcut on the annotation instead of in the options array.", $command->getHelp());
|
||||
$this->assertEquals('shortcut:on-annotation [-s|--silent]', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('shortcut:on-annotation');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world');
|
||||
$input = new StringInput('shortcut:on-annotation -s');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '');
|
||||
$input = new StringInput('shortcut:on-annotation --silent');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '');
|
||||
}
|
||||
|
||||
function testState()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile('secret secret');
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testState');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:state', $command->getName());
|
||||
|
||||
$input = new StringInput('test:state');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'secret secret');
|
||||
}
|
||||
|
||||
function testPassthroughArray()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPassthrough');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:passthrough', $command->getName());
|
||||
|
||||
$input = new StringInput('test:passthrough a b c -- x y z');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'a,b,c,x,y,z');
|
||||
}
|
||||
|
||||
function testPassThroughNonArray()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$input = new StringInput('my:join bet --flip -- x y z');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'zyxbet');
|
||||
// Can't look at 'hasOption' until after the command initializes the
|
||||
// option, because Symfony.
|
||||
$this->assertTrue($input->hasOption('flip'));
|
||||
}
|
||||
|
||||
function testPassThroughWithInputManipulation()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$input = new StringInput('my:join bet --repeat=2 -- x y z');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz');
|
||||
// Symfony does not allow us to manipulate the options via setOption until
|
||||
// the definition from the command object has been set up.
|
||||
$input->setOption('repeat', 3);
|
||||
$this->assertEquals(3, $input->getOption('repeat'));
|
||||
$input->setArgument(0, 'q');
|
||||
// Manipulating $input does not work -- the changes are not effective.
|
||||
// The end result here should be 'qx y yqx y yqx y y'
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz');
|
||||
}
|
||||
|
||||
function testRequiredArrayOption()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testRequiredArrayOption');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('test:required-array-option [-a|--arr ARR]', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('test:required-array-option --arr=1 --arr=2 --arr=3');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3');
|
||||
|
||||
$input = new StringInput('test:required-array-option -a 1 -a 2 -a 3');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3');
|
||||
}
|
||||
|
||||
function testArrayOption()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile;
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testArrayOption');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertEquals('test:array-option [-a|--arr [ARR]]', $command->getSynopsis());
|
||||
|
||||
$input = new StringInput('test:array-option');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3');
|
||||
|
||||
$input = new StringInput('test:array-option --arr=a --arr=b --arr=c');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'a b c');
|
||||
|
||||
$input = new StringInput('test:array-option -a a');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'a');
|
||||
}
|
||||
|
||||
function testHookedCommand()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestHook', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:hook', $command->getName());
|
||||
|
||||
$input = new StringInput('test:hook bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>');
|
||||
|
||||
$input = new StringInput('list --raw');
|
||||
$this->assertRunCommandViaApplicationContains($command, $input, ['This command wraps its parameter in []; its alter hook then wraps the result in .']);
|
||||
}
|
||||
|
||||
function testReplaceCommandHook(){
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestReplaceCommandHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('replace-command test:replace-command', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:replace-command', [HookManager::REPLACE_COMMAND_HOOK]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestReplaceCommandHook', $hookCallback[0][1]);
|
||||
|
||||
$input = new StringInput('test:replace-command foo');
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testReplaceCommand');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "bar", 0);
|
||||
}
|
||||
|
||||
function testPostCommandCalledAfterCommand()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPostCommandHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('post-command test:post-command', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::POST_COMMAND_HOOK]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestPostCommandHook', $hookCallback[0][1]);
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPreCommandHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('pre-command test:post-command', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::PRE_COMMAND_HOOK]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestPreCommandHook', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPostCommand');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:post-command', $command->getName());
|
||||
|
||||
$input = new StringInput('test:post-command bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "foo\nbar\nbaz", 0, $this->commandFileInstance);
|
||||
}
|
||||
|
||||
function testHookAllCommands()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleHookAllCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterAllCommands');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('alter', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('Consolidation\TestUtils\ExampleHookAllCommandFile', [HookManager::ALTER_RESULT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('alterAllCommands', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'doCat');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('do:cat', $command->getName());
|
||||
|
||||
$input = new StringInput('do:cat bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '*** bar ***');
|
||||
}
|
||||
|
||||
function testDoubleDashWithVersion()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleHookAllCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'doCat');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$input = new ArgvInput(['placeholder', 'do:cat', 'one', '--', '--version']);
|
||||
list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
if ($commandOutput == 'TestApplication version 0.0.0') {
|
||||
$this->markTestSkipped('Symfony/Console 2.x does not respect -- with --version');
|
||||
}
|
||||
$this->assertEquals('one--version', $commandOutput);
|
||||
}
|
||||
|
||||
function testAnnotatedHookedCommand()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestAnnotatedHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('alter @hookme', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('@hookme', [HookManager::ALTER_RESULT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestAnnotatedHook', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testAnnotationHook');
|
||||
$annotationData = $commandInfo->getRawAnnotations();
|
||||
$this->assertEquals('hookme,before,after', implode(',', $annotationData->keys()));
|
||||
$this->assertEquals('@hookme,@before,@after', implode(',', array_map(function ($item) { return "@$item"; }, $annotationData->keys())));
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:annotation-hook', $command->getName());
|
||||
|
||||
$input = new StringInput('test:annotation-hook baz');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '>(baz)<');
|
||||
}
|
||||
|
||||
function testHookHasCommandAnnotation()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookAddCommandName');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('alter @addmycommandname', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('@addmycommandname', [HookManager::ALTER_RESULT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookAddCommandName', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMe');
|
||||
$annotationData = $commandInfo->getRawAnnotations();
|
||||
$this->assertEquals('command,addmycommandname', implode(',', $annotationData->keys()));
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('alter-me', $command->getName());
|
||||
|
||||
$input = new StringInput('alter-me');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'splendiferous from alter-me');
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMeToo');
|
||||
$annotationData = $commandInfo->getRawAnnotations();
|
||||
$this->assertEquals('addmycommandname', implode(',', $annotationData->keys()));
|
||||
$annotationData = $commandInfo->getAnnotations();
|
||||
$this->assertEquals('addmycommandname,command,_path,_classname', implode(',', $annotationData->keys()));
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('alter:me-too', $command->getName());
|
||||
|
||||
$input = new StringInput('alter:me-too');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'fantabulous from alter:me-too');
|
||||
}
|
||||
|
||||
function testHookedCommandWithHookAddedLater()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook');
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:hook', $command->getName());
|
||||
|
||||
// Run the command once without the hook
|
||||
$input = new StringInput('test:hook foo');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '[foo]');
|
||||
|
||||
// Register the hook and run the command again
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook'));
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]);;
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('hookTestHook', $hookCallback[0][1]);
|
||||
|
||||
$input = new StringInput('test:hook bar');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>');
|
||||
}
|
||||
|
||||
function testInitializeHook()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'initializeTestHello');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals($hookInfo->getAnnotation('hook'), 'init test:hello');
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INITIALIZE]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('initializeTestHello', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:hello', $command->getName());
|
||||
$commandGetNames = $this->callProtected($command, 'getNames');
|
||||
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
|
||||
|
||||
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'init');
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals('initializeTestHello', $hookCallback[0][1]);
|
||||
|
||||
$input = new StringInput('test:hello');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Hello, Huey.");
|
||||
}
|
||||
|
||||
function testCommandEventHook()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandEventTestHello');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals($hookInfo->getAnnotation('hook'), 'command-event test:hello');
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::COMMAND_EVENT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('commandEventTestHello', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:hello', $command->getName());
|
||||
$commandGetNames = $this->callProtected($command, 'getNames');
|
||||
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
|
||||
|
||||
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'command-event');
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals('commandEventTestHello', $hookCallback[0][1]);
|
||||
|
||||
$input = new StringInput('test:hello Pluto');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Here comes Pluto!\nHello, Pluto.");
|
||||
}
|
||||
|
||||
|
||||
function testInteractAndValidate()
|
||||
{
|
||||
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'interactTestHello');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals($hookInfo->getAnnotation('hook'), 'interact test:hello');
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'validateTestHello');
|
||||
|
||||
$this->assertTrue($hookInfo->hasAnnotation('hook'));
|
||||
$this->assertEquals($hookInfo->getAnnotation('hook'), 'validate test:hello');
|
||||
|
||||
$this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::ARGUMENT_VALIDATOR]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('validateTestHello', $hookCallback[0][1]);
|
||||
|
||||
$hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INTERACT]);
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals(1, count($hookCallback));
|
||||
$this->assertEquals(2, count($hookCallback[0]));
|
||||
$this->assertTrue(is_callable($hookCallback[0]));
|
||||
$this->assertEquals('interactTestHello', $hookCallback[0][1]);
|
||||
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello');
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
|
||||
|
||||
$this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command);
|
||||
$this->assertEquals('test:hello', $command->getName());
|
||||
$commandGetNames = $this->callProtected($command, 'getNames');
|
||||
$this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames));
|
||||
|
||||
$testInteractInput = new StringInput('test:hello');
|
||||
$definition = new \Symfony\Component\Console\Input\InputDefinition(
|
||||
[
|
||||
new \Symfony\Component\Console\Input\InputArgument('application', \Symfony\Component\Console\Input\InputArgument::REQUIRED),
|
||||
new \Symfony\Component\Console\Input\InputArgument('who', \Symfony\Component\Console\Input\InputArgument::REQUIRED),
|
||||
]
|
||||
);
|
||||
$testInteractInput->bind($definition);
|
||||
$testInteractOutput = new BufferedOutput();
|
||||
$command->commandProcessor()->interact(
|
||||
$testInteractInput,
|
||||
$testInteractOutput,
|
||||
$commandGetNames,
|
||||
$command->getAnnotationData()
|
||||
);
|
||||
$this->assertEquals('Goofey', $testInteractInput->getArgument('who'));
|
||||
|
||||
$hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'interact');
|
||||
$this->assertTrue($hookCallback != null);
|
||||
$this->assertEquals('interactTestHello', $hookCallback[0][1]);
|
||||
|
||||
$input = new StringInput('test:hello "Mickey Mouse"');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Mickey Mouse.');
|
||||
|
||||
$input = new StringInput('test:hello');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Goofey.');
|
||||
|
||||
$input = new StringInput('test:hello "Donald Duck"');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "I won't say hello to Donald Duck.", 1);
|
||||
|
||||
$input = new StringInput('test:hello "Drumph"');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "Irrational value error.", 1);
|
||||
|
||||
// Try the last test again with a display error function installed.
|
||||
$this->commandFactory->commandProcessor()->setDisplayErrorFunction(
|
||||
function ($output, $message) {
|
||||
$output->writeln("*** $message ****");
|
||||
}
|
||||
);
|
||||
|
||||
$input = new StringInput('test:hello "Drumph"');
|
||||
$this->assertRunCommandViaApplicationEquals($command, $input, "*** Irrational value error. ****", 1);
|
||||
}
|
||||
|
||||
function callProtected($object, $method, $args = [])
|
||||
{
|
||||
$r = new \ReflectionMethod($object, $method);
|
||||
$r->setAccessible(true);
|
||||
return $r->invokeArgs($object, $args);
|
||||
}
|
||||
|
||||
function assertRunCommandViaApplicationContains($command, $input, $containsList, $expectedStatusCode = 0)
|
||||
{
|
||||
list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
foreach ($containsList as $contains) {
|
||||
$this->assertContains($contains, $commandOutput);
|
||||
}
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
|
||||
function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0)
|
||||
{
|
||||
list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$this->assertEquals($expectedOutput, $commandOutput);
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
|
||||
function runCommandViaApplication($command, $input)
|
||||
{
|
||||
$output = new BufferedOutput();
|
||||
if ($this->commandFileInstance && method_exists($this->commandFileInstance, 'setOutput')) {
|
||||
$this->commandFileInstance->setOutput($output);
|
||||
}
|
||||
|
||||
$application = new Application('TestApplication', '0.0.0');
|
||||
$alterOptionsEventManager = new AlterOptionsCommandEvent($application);
|
||||
|
||||
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
|
||||
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
|
||||
$this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager);
|
||||
$application->setDispatcher($eventDispatcher);
|
||||
|
||||
$application->setAutoExit(false);
|
||||
$application->add($command);
|
||||
|
||||
$statusCode = $application->run($input, $output);
|
||||
$commandOutput = trim(str_replace("\r", '', $output->fetch()));
|
||||
|
||||
return [$statusCode, $commandOutput];
|
||||
}
|
||||
}
|
82
vendor/consolidation/annotated-command/tests/testCommandFileDiscovery.php
vendored
Normal file
82
vendor/consolidation/annotated-command/tests/testCommandFileDiscovery.php
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
class CommandFileDiscoveryTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
function testCommandDiscovery()
|
||||
{
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setSearchLocations(['alpha']);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$commandFilePaths = array_keys($commandFiles);
|
||||
$commandFileNamespaces = array_values($commandFiles);
|
||||
|
||||
// Ensure that the command files that we expected to
|
||||
// find were all found. We don't find anything in
|
||||
// 'beta' because only 'alpha' is in the search path.
|
||||
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/alpha/Inclusive/IncludedCommandFile.php', $commandFilePaths);
|
||||
|
||||
// Make sure that there are no additional items found.
|
||||
$this->assertEquals(4, count($commandFilePaths));
|
||||
|
||||
// Ensure that the command file namespaces that we expected
|
||||
// to be generated all match.
|
||||
$this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\alpha\Inclusive\IncludedCommandFile', $commandFileNamespaces);
|
||||
|
||||
// We do not need to test for additional namespace items, because we
|
||||
// know that the length of the array_keys must be the same as the
|
||||
// length of the array_values.
|
||||
}
|
||||
|
||||
function testDeepCommandDiscovery()
|
||||
{
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setSearchDepth(1)
|
||||
->setSearchLocations([]);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$commandFilePaths = array_keys($commandFiles);
|
||||
$commandFileNamespaces = array_values($commandFiles);
|
||||
|
||||
// Ensure that the command files that we expected to
|
||||
// find were all found. We find both 'alpha' and 'beta'
|
||||
// items because the search locations is empty, which
|
||||
// causes the search at the base directory to be deep.
|
||||
// We do not find alpha/Inclusive, though, as the search
|
||||
// depth is only 2, which excludes directories that are
|
||||
// three levels deep.
|
||||
$this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths);
|
||||
$this->assertContains('./src/beta/BetaCommandFile.php', $commandFilePaths);
|
||||
|
||||
// Make sure that there are no additional items found.
|
||||
$this->assertEquals(4, count($commandFilePaths));
|
||||
|
||||
// Ensure that the command file namespaces that we expected
|
||||
// to be generated all match.
|
||||
$this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces);
|
||||
$this->assertContains('\Consolidation\TestUtils\beta\BetaCommandFile', $commandFileNamespaces);
|
||||
|
||||
// We do not need to test for additional namespace items, because we
|
||||
// know that the length of the array_keys must be the same as the
|
||||
// length of the array_values.
|
||||
}
|
||||
}
|
102
vendor/consolidation/annotated-command/tests/testCommandInfo.php
vendored
Normal file
102
vendor/consolidation/annotated-command/tests/testCommandInfo.php
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfoSerializer;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfoDeserializer;
|
||||
|
||||
class CommandInfoTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
function flattenArray($actualValue)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($actualValue as $key => $value) {
|
||||
if (!is_string($value)) {
|
||||
$value = var_export($value, true);
|
||||
}
|
||||
$result[] = "{$key}=>{$value}";
|
||||
}
|
||||
return implode("\n", $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CommandInfo command annotation parsing.
|
||||
*/
|
||||
function testParsing()
|
||||
{
|
||||
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\ExampleCommandFile', 'testArithmatic');
|
||||
$this->assertCommandInfoIsAsExpected($commandInfo);
|
||||
|
||||
$serializer = new CommandInfoSerializer();
|
||||
$serialized = $serializer->serialize($commandInfo);
|
||||
|
||||
$deserializer = new CommandInfoDeserializer();
|
||||
|
||||
$deserializedCommandInfo = $deserializer->deserialize($serialized);
|
||||
$this->assertCommandInfoIsAsExpected($deserializedCommandInfo);
|
||||
}
|
||||
|
||||
function testWithConfigImport()
|
||||
{
|
||||
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\ExampleCommandFile', 'import');
|
||||
$this->assertEquals('config:import', $commandInfo->getName());
|
||||
|
||||
$this->assertEquals(
|
||||
'A config directory label (i.e. a key in \$config_directories array in settings.php).',
|
||||
$commandInfo->arguments()->getDescription('label')
|
||||
);
|
||||
}
|
||||
|
||||
function assertCommandInfoIsAsExpected($commandInfo)
|
||||
{
|
||||
$this->assertEquals('test:arithmatic', $commandInfo->getName());
|
||||
$this->assertEquals(
|
||||
'This is the test:arithmatic command',
|
||||
$commandInfo->getDescription()
|
||||
);
|
||||
$this->assertEquals(
|
||||
"This command will add one and two. If the --negate flag\nis provided, then the result is negated.",
|
||||
$commandInfo->getHelp()
|
||||
);
|
||||
$this->assertEquals('arithmatic', implode(',', $commandInfo->getAliases()));
|
||||
$this->assertEquals(
|
||||
'2 2 --negate=>Add two plus two and then negate.',
|
||||
$this->flattenArray($commandInfo->getExampleUsages())
|
||||
);
|
||||
$this->assertEquals(
|
||||
'The first number to add.',
|
||||
$commandInfo->arguments()->getDescription('one')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'The other number to add.',
|
||||
$commandInfo->arguments()->getDescription('two')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'2',
|
||||
$commandInfo->arguments()->get('two')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Whether or not the result should be negated.',
|
||||
$commandInfo->options()->getDescription('negate')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'bob',
|
||||
$commandInfo->options()->get('unused')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'one,two',
|
||||
$commandInfo->getAnnotation('dup')
|
||||
);
|
||||
$this->assertEquals(
|
||||
['one','two'],
|
||||
$commandInfo->getAnnotationList('dup')
|
||||
);
|
||||
}
|
||||
|
||||
function testReturnValue()
|
||||
{
|
||||
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
|
||||
$this->assertEquals('example:table', $commandInfo->getName());
|
||||
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
|
||||
}
|
||||
}
|
530
vendor/consolidation/annotated-command/tests/testFullStack.php
vendored
Normal file
530
vendor/consolidation/annotated-command/tests/testFullStack.php
vendored
Normal file
|
@ -0,0 +1,530 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\CommandProcessor;
|
||||
use Consolidation\AnnotatedCommand\Hooks\AlterResultInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ExtractOutputInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ProcessResultInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\StatusDeterminerInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ValidatorInterface;
|
||||
use Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\OutputFormatters\FormatterManager;
|
||||
use Consolidation\TestUtils\TestTerminal;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Consolidation\TestUtils\ApplicationWithTerminalWidth;
|
||||
use Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption;
|
||||
use Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface;
|
||||
use Consolidation\AnnotatedCommand\Events\CustomEventAwareTrait;
|
||||
|
||||
/**
|
||||
* Do a test of all of the classes in this project, top-to-bottom.
|
||||
*/
|
||||
class FullStackTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $application;
|
||||
protected $commandFactory;
|
||||
|
||||
function setup() {
|
||||
$this->application = new ApplicationWithTerminalWidth('TestApplication', '0.0.0');
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
$alterOptionsEventManager = new AlterOptionsCommandEvent($this->application);
|
||||
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
|
||||
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
|
||||
$this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager);
|
||||
$this->application->setDispatcher($eventDispatcher);
|
||||
$this->application->setAutoExit(false);
|
||||
}
|
||||
|
||||
function testValidFormats()
|
||||
{
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
|
||||
$this->assertEquals('example:table', $commandInfo->getName());
|
||||
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
|
||||
}
|
||||
|
||||
function testAutomaticOptions()
|
||||
{
|
||||
$commandFileInstance = new \Consolidation\TestUtils\alpha\AlphaCommandFile;
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
|
||||
$this->commandFactory->commandProcessor()->setFormatterManager($formatter);
|
||||
$this->assertAutomaticOptionsForCommand($commandFileInstance, 'exampleTable', 'example:table');
|
||||
$this->assertAutomaticOptionsForCommand($commandFileInstance, 'exampleTableTwo', 'example:table2');
|
||||
}
|
||||
|
||||
function assertAutomaticOptionsForCommand($commandFileInstance, $functionName, $commandName)
|
||||
{
|
||||
$commandInfo = $this->commandFactory->createCommandInfo($commandFileInstance, $functionName);
|
||||
|
||||
$command = $this->commandFactory->createCommand($commandInfo, $commandFileInstance);
|
||||
$this->application->add($command);
|
||||
|
||||
$containsList =
|
||||
[
|
||||
'--format[=FORMAT] Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml [default: "table"]',
|
||||
'--fields[=FIELDS] Available fields: I (first), II (second), III (third) [default: ""]',
|
||||
];
|
||||
$this->assertRunCommandViaApplicationContains('help ' . $commandName, $containsList);
|
||||
}
|
||||
|
||||
function testCommandsAndHooks()
|
||||
{
|
||||
// First, search for commandfiles in the 'alpha'
|
||||
// directory. Note that this same functionality
|
||||
// is tested more thoroughly in isolation in
|
||||
// testCommandFileDiscovery.php
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setIncludeFilesAtBase(false)
|
||||
->setSearchLocations(['alpha']);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
$hookManager = new HookManager();
|
||||
$terminalWidthOption = new PrepareTerminalWidthOption();
|
||||
$terminalWidthOption->enableWrap(true);
|
||||
$terminalWidthOption->setApplication($this->application);
|
||||
$testTerminal = new TestTerminal(0);
|
||||
$terminalWidthOption->setTerminal($testTerminal);
|
||||
$commandProcessor = new CommandProcessor($hookManager);
|
||||
$commandProcessor->setFormatterManager($formatter);
|
||||
$commandProcessor->addPrepareFormatter($terminalWidthOption);
|
||||
|
||||
// Create a new factory, and load all of the files
|
||||
// discovered above.
|
||||
$factory = new AnnotatedCommandFactory();
|
||||
$factory->setCommandProcessor($commandProcessor);
|
||||
// Add a listener to configure our command handler object
|
||||
$factory->addListernerCallback(function($command) use($hookManager) {
|
||||
if ($command instanceof CustomEventAwareInterface) {
|
||||
$command->setHookManager($hookManager);
|
||||
}
|
||||
} );
|
||||
$factory->setIncludeAllPublicMethods(false);
|
||||
$this->addDiscoveredCommands($factory, $commandFiles);
|
||||
|
||||
$this->assertRunCommandViaApplicationContains('list', ['example:table'], ['additional:option', 'without:annotations']);
|
||||
|
||||
$this->assertTrue($this->application->has('example:table'));
|
||||
$this->assertFalse($this->application->has('without:annotations'));
|
||||
|
||||
// Run the use:event command that defines a custom event, my-event.
|
||||
$this->assertRunCommandViaApplicationEquals('use:event', 'one,two');
|
||||
// Watch as we dynamically add a custom event to the hook manager to change the command results:
|
||||
$hookManager->add(function () { return 'three'; }, HookManager::ON_EVENT, 'my-event');
|
||||
$this->assertRunCommandViaApplicationEquals('use:event', 'one,three,two');
|
||||
|
||||
// Fetch a reference to the 'example:table' command and test its valid format types
|
||||
$exampleTableCommand = $this->application->find('example:table');
|
||||
$returnType = $exampleTableCommand->getReturnType();
|
||||
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $returnType);
|
||||
$validFormats = $formatter->validFormats($returnType);
|
||||
$this->assertEquals('csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml', implode(',', $validFormats));
|
||||
|
||||
// Control: run commands without hooks.
|
||||
$this->assertRunCommandViaApplicationEquals('always:fail', 'This command always fails.', 13);
|
||||
$this->assertRunCommandViaApplicationEquals('simulated:status', '42');
|
||||
$this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World.');
|
||||
$this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphabet');
|
||||
$this->assertRunCommandViaApplicationEquals('example:echo a b c', "a\tb\tc");
|
||||
$this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.');
|
||||
$this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument', 'Hello, world');
|
||||
$this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument Joe', 'Hello, Joe');
|
||||
|
||||
// Add some hooks.
|
||||
$factory->hookManager()->addValidator(new ExampleValidator());
|
||||
$factory->hookManager()->addResultProcessor(new ExampleResultProcessor());
|
||||
$factory->hookManager()->addAlterResult(new ExampleResultAlterer());
|
||||
$factory->hookManager()->addStatusDeterminer(new ExampleStatusDeterminer());
|
||||
$factory->hookManager()->addOutputExtractor(new ExampleOutputExtractor());
|
||||
|
||||
// Run the same commands as before, and confirm that results
|
||||
// are different now that the hooks are in place.
|
||||
$this->assertRunCommandViaApplicationEquals('simulated:status', '', 42);
|
||||
$this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World!');
|
||||
$this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphareplaced');
|
||||
$this->assertRunCommandViaApplicationEquals('example:echo a b c', 'a,b,c');
|
||||
$this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.');
|
||||
|
||||
$expected = <<<EOT
|
||||
------ ------ -------
|
||||
I II III
|
||||
------ ------ -------
|
||||
One Two Three
|
||||
Eins Zwei Drei
|
||||
Ichi Ni San
|
||||
Uno Dos Tres
|
||||
------ ------ -------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:table', $expected);
|
||||
|
||||
$expected = <<<EOT
|
||||
------- ------
|
||||
III II
|
||||
------- ------
|
||||
Three Two
|
||||
Drei Zwei
|
||||
San Ni
|
||||
Tres Dos
|
||||
------- ------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:table --fields=III,II', $expected);
|
||||
|
||||
$expectedSingleField = <<<EOT
|
||||
Two
|
||||
Zwei
|
||||
Ni
|
||||
Dos
|
||||
EOT;
|
||||
|
||||
// When --field is specified (instead of --fields), then the format
|
||||
// is forced to 'string'.
|
||||
$this->assertRunCommandViaApplicationEquals('example:table --field=II', $expectedSingleField);
|
||||
|
||||
// Check the help for the example table command and see if the options
|
||||
// from the alter hook were added. We expect that we should not see
|
||||
// any of the information from the alter hook in the 'beta' folder yet.
|
||||
$this->assertRunCommandViaApplicationContains('help example:table',
|
||||
[
|
||||
'Option added by @hook option example:table',
|
||||
'example:table --french',
|
||||
'Add a row with French numbers.'
|
||||
],
|
||||
[
|
||||
'chinese',
|
||||
'kanji',
|
||||
]
|
||||
);
|
||||
|
||||
$expectedOutputWithFrench = <<<EOT
|
||||
------ ------ -------
|
||||
I II III
|
||||
------ ------ -------
|
||||
One Two Three
|
||||
Eins Zwei Drei
|
||||
Ichi Ni San
|
||||
Uno Dos Tres
|
||||
Un Deux Trois
|
||||
------ ------ -------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:table --french', $expectedOutputWithFrench);
|
||||
|
||||
$expectedAssociativeListTable = <<<EOT
|
||||
--------------- ----------------------------------------------------------------------------------------
|
||||
SFTP Command sftp -o Port=2222 dev@appserver.dev.drush.in
|
||||
Git Command git clone ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git wp-update
|
||||
MySQL Command mysql -u pantheon -p4b33cb -h dbserver.dev.drush.in -P 16191 pantheon
|
||||
--------------- ----------------------------------------------------------------------------------------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:list', $expectedAssociativeListTable);
|
||||
$this->assertRunCommandViaApplicationEquals('example:list --field=sftp_command', 'sftp -o Port=2222 dev@appserver.dev.drush.in');
|
||||
|
||||
$this->assertRunCommandViaApplicationEquals('get:serious', 'very serious');
|
||||
$this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1);
|
||||
|
||||
$this->assertRunCommandViaApplicationContains('help example:wrap',
|
||||
[
|
||||
'Test word wrapping',
|
||||
'[default: "table"]',
|
||||
]
|
||||
);
|
||||
|
||||
$expectedUnwrappedOutput = <<<EOT
|
||||
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
First Second
|
||||
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines. This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.
|
||||
-------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
EOT;
|
||||
$this->application->setWidthAndHeight(0, 0);
|
||||
$this->assertRunCommandViaApplicationEquals('example:wrap', $expectedUnwrappedOutput);
|
||||
|
||||
$expectedWrappedOutput = <<<EOT
|
||||
------------------ --------------------
|
||||
First Second
|
||||
------------------ --------------------
|
||||
This is a really This is the second
|
||||
long cell that column of the same
|
||||
contains a lot table. It is also
|
||||
of data. When it very long, and
|
||||
is rendered, it should be wrapped
|
||||
should be across multiple
|
||||
wrapped across lines, just like
|
||||
multiple lines. the first column.
|
||||
------------------ --------------------
|
||||
EOT;
|
||||
$this->application->setWidthAndHeight(42, 24);
|
||||
$testTerminal->setWidth(42);
|
||||
$this->assertRunCommandViaApplicationEquals('example:wrap', $expectedWrappedOutput);
|
||||
}
|
||||
|
||||
function testCommandsAndHooksIncludeAllPublicMethods()
|
||||
{
|
||||
// First, search for commandfiles in the 'alpha'
|
||||
// directory. Note that this same functionality
|
||||
// is tested more thoroughly in isolation in
|
||||
// testCommandFileDiscovery.php
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setIncludeFilesAtBase(false)
|
||||
->setSearchLocations(['alpha']);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
$hookManager = new HookManager();
|
||||
$commandProcessor = new CommandProcessor($hookManager);
|
||||
$commandProcessor->setFormatterManager($formatter);
|
||||
|
||||
// Create a new factory, and load all of the files
|
||||
// discovered above. The command factory class is
|
||||
// tested in isolation in testAnnotatedCommandFactory.php,
|
||||
// but this is the only place where
|
||||
$factory = new AnnotatedCommandFactory();
|
||||
$factory->setCommandProcessor($commandProcessor);
|
||||
// $factory->addListener(...);
|
||||
|
||||
// Now we will once again add all commands, this time including all
|
||||
// public methods. The command 'withoutAnnotations' should now be found.
|
||||
$factory->setIncludeAllPublicMethods(true);
|
||||
$this->addDiscoveredCommands($factory, $commandFiles);
|
||||
$this->assertTrue($this->application->has('without:annotations'));
|
||||
|
||||
$this->assertRunCommandViaApplicationContains('list', ['example:table', 'without:annotations'], ['alter:formatters']);
|
||||
|
||||
$this->assertRunCommandViaApplicationEquals('get:serious', 'very serious');
|
||||
$this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1);
|
||||
}
|
||||
|
||||
function testCommandsAndHooksWithBetaFolder()
|
||||
{
|
||||
// First, search for commandfiles in the 'alpha'
|
||||
// directory. Note that this same functionality
|
||||
// is tested more thoroughly in isolation in
|
||||
// testCommandFileDiscovery.php
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setIncludeFilesAtBase(false)
|
||||
->setSearchLocations(['alpha', 'beta']);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
$hookManager = new HookManager();
|
||||
$commandProcessor = new CommandProcessor($hookManager);
|
||||
$commandProcessor->setFormatterManager($formatter);
|
||||
|
||||
// Create a new factory, and load all of the files
|
||||
// discovered above. The command factory class is
|
||||
// tested in isolation in testAnnotatedCommandFactory.php,
|
||||
// but this is the only place where
|
||||
$factory = new AnnotatedCommandFactory();
|
||||
$factory->setCommandProcessor($commandProcessor);
|
||||
// $factory->addListener(...);
|
||||
$factory->setIncludeAllPublicMethods(true);
|
||||
$this->addDiscoveredCommands($factory, $commandFiles);
|
||||
|
||||
// A few asserts, to make sure that our hooks all get registered.
|
||||
$allRegisteredHooks = $hookManager->getAllHooks();
|
||||
$registeredHookNames = array_keys($allRegisteredHooks);
|
||||
sort($registeredHookNames);
|
||||
$this->assertEquals('*,example:table,my-event', implode(',', $registeredHookNames));
|
||||
$allHooksForExampleTable = $allRegisteredHooks['example:table'];
|
||||
$allHookPhasesForExampleTable = array_keys($allHooksForExampleTable);
|
||||
sort($allHookPhasesForExampleTable);
|
||||
$this->assertEquals('alter,option', implode(',', $allHookPhasesForExampleTable));
|
||||
|
||||
$this->assertContains('alterFormattersChinese', var_export($allHooksForExampleTable, true));
|
||||
|
||||
$alterHooksForExampleTable = $this->callProtected($hookManager, 'getHooks', [['example:table'], 'alter']);
|
||||
$this->assertContains('alterFormattersKanji', var_export($alterHooksForExampleTable, true));
|
||||
|
||||
$allHooksForAnyCommand = $allRegisteredHooks['*'];
|
||||
$allHookPhasesForAnyCommand = array_keys($allHooksForAnyCommand);
|
||||
sort($allHookPhasesForAnyCommand);
|
||||
$this->assertEquals('alter', implode(',', $allHookPhasesForAnyCommand));
|
||||
|
||||
$this->assertContains('alterFormattersKanji', var_export($allHooksForAnyCommand, true));
|
||||
|
||||
// Help should have the information from the hooks in the 'beta' folder
|
||||
$this->assertRunCommandViaApplicationContains('help example:table',
|
||||
[
|
||||
'Option added by @hook option example:table',
|
||||
'example:table --french',
|
||||
'Add a row with French numbers.',
|
||||
'chinese',
|
||||
'kanji',
|
||||
]
|
||||
);
|
||||
|
||||
// Confirm that the "unavailable" command is now available
|
||||
$this->assertTrue($this->application->has('unavailable:command'));
|
||||
|
||||
$expectedOutputWithChinese = <<<EOT
|
||||
------ ------ -------
|
||||
I II III
|
||||
------ ------ -------
|
||||
One Two Three
|
||||
Eins Zwei Drei
|
||||
Ichi Ni San
|
||||
Uno Dos Tres
|
||||
壹 貳 叁
|
||||
------ ------ -------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:table --chinese', $expectedOutputWithChinese);
|
||||
|
||||
$expectedOutputWithKanji = <<<EOT
|
||||
------ ------ -------
|
||||
I II III
|
||||
------ ------ -------
|
||||
One Two Three
|
||||
Eins Zwei Drei
|
||||
Ichi Ni San
|
||||
Uno Dos Tres
|
||||
一 二 三
|
||||
------ ------ -------
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('example:table --kanji', $expectedOutputWithKanji);
|
||||
}
|
||||
|
||||
public function addDiscoveredCommands($factory, $commandFiles) {
|
||||
foreach ($commandFiles as $path => $commandClass) {
|
||||
$this->assertFileExists($path);
|
||||
if (!class_exists($commandClass)) {
|
||||
include $path;
|
||||
}
|
||||
$commandInstance = new $commandClass();
|
||||
$commandList = $factory->createCommandsFromClass($commandInstance);
|
||||
foreach ($commandList as $command) {
|
||||
$this->application->add($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertRunCommandViaApplicationEquals($cmd, $expectedOutput, $expectedStatusCode = 0)
|
||||
{
|
||||
$input = new StringInput($cmd);
|
||||
$output = new BufferedOutput();
|
||||
|
||||
$statusCode = $this->application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
$expectedOutput = $this->simplifyWhitespace($expectedOutput);
|
||||
$commandOutput = $this->simplifyWhitespace($commandOutput);
|
||||
|
||||
$this->assertEquals($expectedOutput, $commandOutput);
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
|
||||
function assertRunCommandViaApplicationContains($cmd, $containsList, $doesNotContainList = [], $expectedStatusCode = 0)
|
||||
{
|
||||
$input = new StringInput($cmd);
|
||||
$output = new BufferedOutput();
|
||||
$containsList = (array) $containsList;
|
||||
|
||||
$statusCode = $this->application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
$commandOutput = $this->simplifyWhitespace($commandOutput);
|
||||
|
||||
foreach ($containsList as $expectedToContain) {
|
||||
$this->assertContains($this->simplifyWhitespace($expectedToContain), $commandOutput);
|
||||
}
|
||||
foreach ($doesNotContainList as $expectedToNotContain) {
|
||||
$this->assertNotContains($this->simplifyWhitespace($expectedToNotContain), $commandOutput);
|
||||
}
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
|
||||
function simplifyWhitespace($data)
|
||||
{
|
||||
return trim(preg_replace('#\s+$#m', '', $data));
|
||||
}
|
||||
|
||||
function callProtected($object, $method, $args = [])
|
||||
{
|
||||
$r = new \ReflectionMethod($object, $method);
|
||||
$r->setAccessible(true);
|
||||
return $r->invokeArgs($object, $args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ExampleValidator implements ValidatorInterface
|
||||
{
|
||||
public function validate(CommandData $commandData)
|
||||
{
|
||||
$args = $commandData->arguments();
|
||||
if (isset($args['one']) && ($args['one'] == 'bet')) {
|
||||
$commandData->input()->setArgument('one', 'replaced');
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleResultProcessor implements ProcessResultInterface
|
||||
{
|
||||
public function process($result, CommandData $commandData)
|
||||
{
|
||||
if (is_array($result) && array_key_exists('item-list', $result)) {
|
||||
return implode(',', $result['item-list']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleResultAlterer implements AlterResultInterface
|
||||
{
|
||||
public function process($result, CommandData $commandData)
|
||||
{
|
||||
if (is_string($result) && ($result == 'Hello, World.')) {
|
||||
return 'Hello, World!';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleStatusDeterminer implements StatusDeterminerInterface
|
||||
{
|
||||
public function determineStatusCode($result)
|
||||
{
|
||||
if (is_array($result) && array_key_exists('status-code', $result)) {
|
||||
return $result['status-code'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleOutputExtractor implements ExtractOutputInterface
|
||||
{
|
||||
public function extractOutput($result)
|
||||
{
|
||||
if (is_array($result) && array_key_exists('message', $result)) {
|
||||
return $result['message'];
|
||||
}
|
||||
}
|
||||
}
|
313
vendor/consolidation/annotated-command/tests/testHelp.php
vendored
Normal file
313
vendor/consolidation/annotated-command/tests/testHelp.php
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
<?php
|
||||
namespace Consolidation\AnnotatedCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Help\HelpCommand;
|
||||
|
||||
use Consolidation\AnnotatedCommand\AnnotationData;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Consolidation\AnnotatedCommand\CommandProcessor;
|
||||
use Consolidation\AnnotatedCommand\Hooks\AlterResultInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ExtractOutputInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ProcessResultInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\StatusDeterminerInterface;
|
||||
use Consolidation\AnnotatedCommand\Hooks\ValidatorInterface;
|
||||
use Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent;
|
||||
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
||||
use Consolidation\OutputFormatters\FormatterManager;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Consolidation\TestUtils\ApplicationWithTerminalWidth;
|
||||
use Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption;
|
||||
|
||||
/**
|
||||
* Test our 'help' command.
|
||||
*/
|
||||
class HelpTests extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $application;
|
||||
protected $commandFactory;
|
||||
|
||||
function setup()
|
||||
{
|
||||
$this->application = new ApplicationWithTerminalWidth('TestApplication', '0.0.0');
|
||||
$this->commandFactory = new AnnotatedCommandFactory();
|
||||
// $factory->addListener(...);
|
||||
$alterOptionsEventManager = new AlterOptionsCommandEvent($this->application);
|
||||
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
|
||||
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
|
||||
$this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager);
|
||||
$this->application->setDispatcher($eventDispatcher);
|
||||
$this->application->setAutoExit(false);
|
||||
|
||||
$discovery = new CommandFileDiscovery();
|
||||
$discovery
|
||||
->setSearchPattern('*CommandFile.php')
|
||||
->setIncludeFilesAtBase(false)
|
||||
->setSearchLocations(['alpha']);
|
||||
|
||||
chdir(__DIR__);
|
||||
$commandFiles = $discovery->discover('.', '\Consolidation\TestUtils');
|
||||
|
||||
$formatter = new FormatterManager();
|
||||
$formatter->addDefaultFormatters();
|
||||
$formatter->addDefaultSimplifiers();
|
||||
$terminalWidthOption = new PrepareTerminalWidthOption();
|
||||
$terminalWidthOption->setApplication($this->application);
|
||||
$this->commandFactory->commandProcessor()->setFormatterManager($formatter);
|
||||
$this->commandFactory->commandProcessor()->addPrepareFormatter($terminalWidthOption);
|
||||
|
||||
$this->commandFactory->setIncludeAllPublicMethods(false);
|
||||
$this->addDiscoveredCommands($this->commandFactory, $commandFiles);
|
||||
|
||||
$helpCommandfile = new HelpCommand($this->application);
|
||||
$commandList = $this->commandFactory->createCommandsFromClass($helpCommandfile);
|
||||
foreach ($commandList as $command) {
|
||||
$this->application->add($command);
|
||||
}
|
||||
}
|
||||
|
||||
public function addDiscoveredCommands($factory, $commandFiles) {
|
||||
foreach ($commandFiles as $path => $commandClass) {
|
||||
$this->assertFileExists($path);
|
||||
if (!class_exists($commandClass)) {
|
||||
include $path;
|
||||
}
|
||||
$commandInstance = new $commandClass();
|
||||
$commandList = $factory->createCommandsFromClass($commandInstance);
|
||||
foreach ($commandList as $command) {
|
||||
$this->application->add($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertRunCommandViaApplicationEquals($cmd, $expectedOutput, $expectedStatusCode = 0)
|
||||
{
|
||||
$input = new StringInput($cmd);
|
||||
$output = new BufferedOutput();
|
||||
|
||||
$statusCode = $this->application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
$expectedOutput = $this->simplifyWhitespace($expectedOutput);
|
||||
$commandOutput = $this->simplifyWhitespace($commandOutput);
|
||||
|
||||
$this->assertEquals($expectedOutput, $commandOutput);
|
||||
$this->assertEquals($expectedStatusCode, $statusCode);
|
||||
}
|
||||
|
||||
function simplifyWhitespace($data)
|
||||
{
|
||||
return trim(preg_replace('#\s+$#m', '', $data));
|
||||
}
|
||||
|
||||
function testHelp()
|
||||
{
|
||||
$expectedXML = <<<EOT
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<command id="example:table" name="example:table">
|
||||
<usages>
|
||||
<usage>example:table [--format [FORMAT]] [--fields [FIELDS]] [--field FIELD] [--] [<unused>]</usage>
|
||||
</usages>
|
||||
<examples>
|
||||
<example>
|
||||
<usage>example:table --format=yml</usage>
|
||||
<description>Show the example table in yml format.</description>
|
||||
</example>
|
||||
<example>
|
||||
<usage>example:table --fields=first,third</usage>
|
||||
<description>Show only the first and third fields in the table.</description>
|
||||
</example>
|
||||
<example>
|
||||
<usage>example:table --fields=II,III</usage>
|
||||
<description>Note that either the field ID or the visible field label may be used.</description>
|
||||
</example>
|
||||
</examples>
|
||||
<description>Test command with formatters</description>
|
||||
<arguments>
|
||||
<argument name="unused" is_required="0" is_array="0">
|
||||
<description>An unused argument</description>
|
||||
<defaults/>
|
||||
</argument>
|
||||
</arguments>
|
||||
<options>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="0" is_multiple="0">
|
||||
<description>Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml</description>
|
||||
<defaults>
|
||||
<default>table</default>
|
||||
</defaults>
|
||||
</option>
|
||||
<option name="--fields" shortcut="" accept_value="1" is_value_required="0" is_multiple="0">
|
||||
<description>Available fields: I (first), II (second), III (third)</description>
|
||||
<defaults/>
|
||||
</option>
|
||||
<option name="--field" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>Select just one field, and force format to 'string'.</description>
|
||||
<defaults/>
|
||||
</option>
|
||||
<option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Display this help message</description>
|
||||
</option>
|
||||
<option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Do not output any message</description>
|
||||
</option>
|
||||
<option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
|
||||
</option>
|
||||
<option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Display this application version</description>
|
||||
</option>
|
||||
<option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Force ANSI output</description>
|
||||
</option>
|
||||
<option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Disable ANSI output</description>
|
||||
</option>
|
||||
<option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>Do not ask any interactive question</description>
|
||||
</option>
|
||||
</options>
|
||||
<help>Test command with formatters</help>
|
||||
<aliases>
|
||||
<alias>extab</alias>
|
||||
</aliases>
|
||||
<topics>
|
||||
<topic>docs-tables</topic>
|
||||
</topics>
|
||||
</command>
|
||||
EOT;
|
||||
|
||||
$this->assertRunCommandViaApplicationEquals('my-help --format=xml example:table', $expectedXML);
|
||||
|
||||
$expectedJSON = <<<EOT
|
||||
{
|
||||
"id": "example:table",
|
||||
"name": "example:table",
|
||||
"usages": [
|
||||
"example:table [--format [FORMAT]] [--fields [FIELDS]] [--field FIELD] [--] [<unused>]"
|
||||
],
|
||||
"examples": [
|
||||
{
|
||||
"usage": "example:table --format=yml",
|
||||
"description": "Show the example table in yml format."
|
||||
},
|
||||
{
|
||||
"usage": "example:table --fields=first,third",
|
||||
"description": "Show only the first and third fields in the table."
|
||||
},
|
||||
{
|
||||
"usage": "example:table --fields=II,III",
|
||||
"description": "Note that either the field ID or the visible field label may be used."
|
||||
}
|
||||
],
|
||||
"description": "Test command with formatters",
|
||||
"arguments": {
|
||||
"unused": {
|
||||
"name": "unused",
|
||||
"is_required": "0",
|
||||
"is_array": "0",
|
||||
"description": "An unused argument"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"format": {
|
||||
"name": "--format",
|
||||
"shortcut": "",
|
||||
"accept_value": "1",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml",
|
||||
"defaults": [
|
||||
"table"
|
||||
]
|
||||
},
|
||||
"fields": {
|
||||
"name": "--fields",
|
||||
"shortcut": "",
|
||||
"accept_value": "1",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Available fields: I (first), II (second), III (third)"
|
||||
},
|
||||
"field": {
|
||||
"name": "--field",
|
||||
"shortcut": "",
|
||||
"accept_value": "1",
|
||||
"is_value_required": "1",
|
||||
"is_multiple": "0",
|
||||
"description": "Select just one field, and force format to 'string'."
|
||||
},
|
||||
"help": {
|
||||
"name": "--help",
|
||||
"shortcut": "-h",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Display this help message"
|
||||
},
|
||||
"quiet": {
|
||||
"name": "--quiet",
|
||||
"shortcut": "-q",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Do not output any message"
|
||||
},
|
||||
"verbose": {
|
||||
"name": "--verbose",
|
||||
"shortcut": "-v",
|
||||
"shortcuts": "-v|-vv|-vvv",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug"
|
||||
},
|
||||
"version": {
|
||||
"name": "--version",
|
||||
"shortcut": "-V",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Display this application version"
|
||||
},
|
||||
"ansi": {
|
||||
"name": "--ansi",
|
||||
"shortcut": "",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Force ANSI output"
|
||||
},
|
||||
"no-ansi": {
|
||||
"name": "--no-ansi",
|
||||
"shortcut": "",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Disable ANSI output"
|
||||
},
|
||||
"no-interaction": {
|
||||
"name": "--no-interaction",
|
||||
"shortcut": "-n",
|
||||
"accept_value": "0",
|
||||
"is_value_required": "0",
|
||||
"is_multiple": "0",
|
||||
"description": "Do not ask any interactive question"
|
||||
}
|
||||
},
|
||||
"help": "Test command with formatters",
|
||||
"aliases": [
|
||||
"extab"
|
||||
],
|
||||
"topics": [
|
||||
"docs-tables"
|
||||
]
|
||||
}
|
||||
EOT;
|
||||
$this->assertRunCommandViaApplicationEquals('my-help --format=json example:table', $expectedJSON);
|
||||
}
|
||||
}
|
15
vendor/consolidation/output-formatters/.editorconfig
vendored
Normal file
15
vendor/consolidation/output-formatters/.editorconfig
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[**.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
11
vendor/consolidation/output-formatters/.github/issue_template.md
vendored
Normal file
11
vendor/consolidation/output-formatters/.github/issue_template.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
### Steps to reproduce
|
||||
What did you do?
|
||||
|
||||
### Expected behavior
|
||||
Tell us what should happen
|
||||
|
||||
### Actual behavior
|
||||
Tell us what happens instead
|
||||
|
||||
### System Configuration
|
||||
Which O.S. and PHP version are you using?
|
13
vendor/consolidation/output-formatters/.github/pull_request_template.md
vendored
Normal file
13
vendor/consolidation/output-formatters/.github/pull_request_template.md
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
### Overview
|
||||
This pull request:
|
||||
|
||||
- [ ] Fixes a bug
|
||||
- [ ] Adds a feature
|
||||
- [ ] Breaks backwards compatibility
|
||||
- [ ] Has tests that cover changes
|
||||
|
||||
### Summary
|
||||
Short overview of what changed.
|
||||
|
||||
### Description
|
||||
Any additional information.
|
6
vendor/consolidation/output-formatters/.gitignore
vendored
Normal file
6
vendor/consolidation/output-formatters/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
.DS_Store
|
||||
.idea
|
||||
phpunit.xml
|
||||
build
|
||||
vendor
|
||||
main.php
|
49
vendor/consolidation/output-formatters/.travis.yml
vendored
Normal file
49
vendor/consolidation/output-formatters/.travis.yml
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
language: php
|
||||
|
||||
branches:
|
||||
# Only test the master branch and SemVer tags.
|
||||
only:
|
||||
- master
|
||||
- /^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+.*$/
|
||||
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
php: 7.1
|
||||
env: 'HIGHEST_LOWEST="update" STABILITY="RC"'
|
||||
-
|
||||
php: 7.0.11
|
||||
-
|
||||
php: 5.6
|
||||
-
|
||||
php: 5.5
|
||||
-
|
||||
php: 5.4
|
||||
env: 'HIGHEST_LOWEST="update --prefer-lowest"'
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_script:
|
||||
# If running a highest/lowest dependencies test, get rid of composer.lock
|
||||
- |
|
||||
if [ -n "$HIGHEST_LOWEST" ] ; then
|
||||
rm composer.lock
|
||||
composer config --unset platform.php
|
||||
composer config minimum-stability ${STABILITY-stable}
|
||||
fi
|
||||
- 'composer -n ${HIGHEST_LOWEST-install} --prefer-dist'
|
||||
- composer why symfony/console
|
||||
# Print out all of the installed packages in alphabetical order, with versions
|
||||
- composer licenses
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit
|
||||
- vendor/bin/phpcs --standard=PSR2 -n src
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/coveralls -v
|
78
vendor/consolidation/output-formatters/CHANGELOG.md
vendored
Normal file
78
vendor/consolidation/output-formatters/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
# Change Log
|
||||
|
||||
### 3.1.13 - 29 November 2017
|
||||
|
||||
- Allow XML output for RowsOfFields (#60).
|
||||
- Allow Symfony 4 components and add make tests run on three versions of Symfony.
|
||||
|
||||
### 3.1.12 - 12 October 2017
|
||||
|
||||
- Bugfix: Use InputOption::VALUE_REQUIRED instead of InputOption::VALUE_OPTIONAL
|
||||
for injected options such as --format and --fields.
|
||||
- Bugfix: Ignore empty properties in the property parser.
|
||||
|
||||
### 3.1.11 - 17 August 2017
|
||||
|
||||
- Add ListDataFromKeys marker data type.
|
||||
|
||||
### 3.1.10 - 6 June 2017
|
||||
|
||||
- Typo in CalculateWidths::distributeLongColumns causes failure for some column width distributions
|
||||
|
||||
### 3.1.9 - 8 May 2017
|
||||
|
||||
- Improve wrapping algorithm
|
||||
|
||||
### 3.1.7 - 20 Jan 2017
|
||||
|
||||
- Add Windows testing
|
||||
|
||||
### 3.1.6 - 8 Jan 2017
|
||||
|
||||
- Move victorjonsson/markdowndocs to require-dev
|
||||
|
||||
### 3.1.5 - 23 November 2016
|
||||
|
||||
- When converting from XML to an array, use the 'id' or 'name' element as the array key value.
|
||||
|
||||
### 3.1.4 - 20 November 2016
|
||||
|
||||
- Add a 'list delimiter' formatter option, so that we can create a Drush-style table for property lists.
|
||||
|
||||
### 3.1.1 ~ 3.1.3 - 18 November 2016
|
||||
|
||||
- Fine-tune wordwrapping.
|
||||
|
||||
### 3.1.0 - 17 November 2016
|
||||
|
||||
- Add wordwrapping to table formatter.
|
||||
|
||||
### 3.0.0 - 14 November 2016
|
||||
|
||||
- **Breaking** The RenderCellInterface is now provided a reference to the entire row data. Existing clients need only add the new parameter to their method defnition to update.
|
||||
- Rename AssociativeList to PropertyList, as many people seemed to find the former name confusing. AssociativeList is still available for use to preserve backwards compatibility, but it is deprecated.
|
||||
|
||||
|
||||
### 2.1.0 - 7 November 2016
|
||||
|
||||
- Add RenderCellCollections to structured lists, so that commands may add renderers to structured data without defining a new structured data subclass.
|
||||
- Throw an exception if the client requests a field that does not exist.
|
||||
- Remove unwanted extra layer of nesting when formatting an PropertyList with an array formatter (json, yaml, etc.).
|
||||
|
||||
|
||||
### 2.0.0 - 30 September 2016
|
||||
|
||||
- **Breaking** The default `string` format now converts non-string results into a tab-separated-value table if possible. Commands may select a single field to emit in this instance with an annotation: `@default-string-field email`. By this means, a given command may by default emit a single value, but also provide more rich output that may be shown by selecting --format=table, --format=yaml or the like. This change might cause some commands to produce output in situations that previously were not documented as producing output.
|
||||
- **Breaking** FormatterManager::addFormatter() now takes the format identifier and a FormatterInterface, rather than an identifier and a Formatter classname (string).
|
||||
- --field is a synonym for --fields with a single field.
|
||||
- Wildcards and regular expressions can now be used in --fields expressions.
|
||||
|
||||
|
||||
### 1.1.0 - 14 September 2016
|
||||
|
||||
Add tab-separated-value (tsv) formatter.
|
||||
|
||||
|
||||
### 1.0.0 - 19 May 2016
|
||||
|
||||
First stable release.
|
31
vendor/consolidation/output-formatters/CONTRIBUTING.md
vendored
Normal file
31
vendor/consolidation/output-formatters/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Contributing to Consolidation
|
||||
|
||||
Thank you for your interest in contributing to the Consolidation effort! Consolidation aims to provide reusable, loosely-coupled components useful for building command-line tools. Consolidation is built on top of Symfony Console, but aims to separate the tool from the implementation details of Symfony.
|
||||
|
||||
Here are some of the guidelines you should follow to make the most of your efforts:
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
Consolidation adheres to the [PSR-2 Coding Style Guide](http://www.php-fig.org/psr/psr-2/) for PHP code.
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
Every pull request is run through:
|
||||
|
||||
- phpcs -n --standard=PSR2 src
|
||||
- phpunit
|
||||
- [Scrutinizer](https://scrutinizer-ci.com/g/consolidation/output-formatters/)
|
||||
|
||||
It is easy to run the unit tests and code sniffer locally; just run:
|
||||
|
||||
- composer cs
|
||||
|
||||
To run the code beautifier, which will fix many of the problems reported by phpcs:
|
||||
|
||||
- composer cbf
|
||||
|
||||
These two commands (`composer cs` and `composer cbf`) are defined in the `scripts` section of [composer.json](composer.json).
|
||||
|
||||
After submitting a pull request, please examine the Scrutinizer report. It is not required to fix all Scrutinizer issues; you may ignore recommendations that you disagree with. The spacing patches produced by Scrutinizer do not conform to PSR2 standards, and therefore should never be applied. DocBlock patches may be applied at your discression. Things that Scrutinizer identifies as a bug nearly always need to be addressed.
|
||||
|
||||
Pull requests must pass phpcs and phpunit in order to be merged; ideally, new functionality will also include new unit tests.
|
8
vendor/consolidation/output-formatters/LICENSE
vendored
Normal file
8
vendor/consolidation/output-formatters/LICENSE
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
Copyright (c) 2016 Consolidation Org Developers
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
135
vendor/consolidation/output-formatters/README.md
vendored
Normal file
135
vendor/consolidation/output-formatters/README.md
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
# Consolidation\OutputFormatters
|
||||
|
||||
Apply transformations to structured data to write output in different formats.
|
||||
|
||||
[](https://travis-ci.org/consolidation/output-formatters)
|
||||
[](https://ci.appveyor.com/project/greg-1-anderson/output-formatters)
|
||||
[](https://scrutinizer-ci.com/g/consolidation/output-formatters/?branch=master)
|
||||
[](https://coveralls.io/github/consolidation/output-formatters?branch=master)
|
||||
[](https://packagist.org/packages/consolidation/output-formatters)
|
||||
|
||||
## Component Status
|
||||
|
||||
Currently in use in [Robo](https://github.com/consolidation/Robo) (1.x+), [Drush](https://github.com/drush-ops/drush) (9.x+) and [Terminus](https://github.com/pantheon-systems/terminus) (1.x+).
|
||||
|
||||
## Motivation
|
||||
|
||||
Formatters are used to allow simple commandline tool commands to be implemented in a manner that is completely independent from the Symfony Console output interfaces. A command receives its input via its method parameters, and returns its result as structured data (e.g. a php standard object or array). The structured data is then formatted by a formatter, and the result is printed.
|
||||
|
||||
This process is managed by the [Consolidation/AnnotationCommand](https://github.com/consolidation/annotation-command) project.
|
||||
|
||||
## Library Usage
|
||||
|
||||
This is a library intended to be used in some other project. Require from your composer.json file:
|
||||
```
|
||||
"require": {
|
||||
"consolidation/output-formatters": "~3"
|
||||
},
|
||||
```
|
||||
If you require the feature that allows a data table to be automatically reduced to a single element when the `string` format is selected, then you should require version "~2" instead. In most other respects, the 1.x and 2.x versions are compatible. See the [CHANGELOG](CHANGELOG.md) for details.
|
||||
|
||||
## Example Formatter
|
||||
|
||||
Simple formatters are very easy to write.
|
||||
```php
|
||||
class YamlFormatter implements FormatterInterface
|
||||
{
|
||||
public function write(OutputInterface $output, $data, FormatterOptions $options)
|
||||
{
|
||||
$dumper = new Dumper();
|
||||
$output->writeln($dumper->dump($data));
|
||||
}
|
||||
}
|
||||
```
|
||||
The formatter is passed the set of `$options` that the user provided on the command line. These may optionally be examined to alter the behavior of the formatter, if needed.
|
||||
|
||||
Formatters may also implement different interfaces to alter the behavior of the rendering engine.
|
||||
|
||||
- `ValidationInterface`: A formatter should implement this interface to test to see if the provided data type can be processed. Any formatter that does **not** implement this interface is presumed to operate exclusively on php arrays. The formatter manager will always convert any provided data into an array before passing it to a formatter that does not implement ValidationInterface. These formatters will not be made available when the returned data type cannot be converted into an array.
|
||||
- `OverrideRestructureInterface`: A formatter that implements this interface will be given the option to act on the provided structured data object before it restructures itself. See the section below on structured data for details on data restructuring.
|
||||
|
||||
## Structured Data
|
||||
|
||||
Most formatters will operate on any array or ArrayObject data. Some formatters require that specific data types be used. The following data types, all of which are subclasses of ArrayObject, are available for use:
|
||||
|
||||
- `RowsOfFields`: Each row contains an associative array of field:value pairs. It is also assumed that the fields of each row are the same for every row. This format is ideal for displaying in a table, with labels in the top row.
|
||||
- `PropertyList`: Each row contains a field:value pair. Each field is unique. This format is ideal for displaying in a table, with labels in the first column and values in the second common.
|
||||
- `ListDataFromKeys`: The result may be structured or unstructured data. When formatted with the --format=list formatter, the result will come from the array keys instead of the array values.
|
||||
- `DOMDocument`: The standard PHP DOM document class may be used by functions that need to be able to presicely specify the exact attributes and children when the XML output format is used.
|
||||
|
||||
Commands that return table structured data with fields can be filtered and/or re-ordered by using the --fields option. These structured data types can also be formatted into a more generic type such as yaml or json, even after being filtered. This capabilities are not available if the data is returned in a bare php array.
|
||||
|
||||
The formatter manager will do its best to convert from an array to a DOMDocument, or from a DOMDocument to an array. It is important to note that a DOMDocument does not have a 1-to-1 mapping with a PHP array. DOM elements contain both attributes and elements; a simple string property 'foo' may be represented either as <element foo="value"/> or <element><foo>value</foo></element>. Also, there may be multiple XML elements with the same name, whereas php associative arrays must always have unique keys. When converting from an array to a DOM document, the XML formatter will default to representing the string properties of an array as attributes of the element. Sets of elements with the same name may be used only if they are wrapped in a containing parent element--e.g. <element><foos><foo>one</foo><foo>two</foo></foos></element>. The XMLSchema class may be used to provide control over whether a property is rendered as an attribute or an element; however, in instances where the schema of the XML output is important, it is best for a function to return its result as a DOMDocument rather than an array.
|
||||
|
||||
A function may also define its own structured data type to return, usually by extending one of the types mentioned above. If a custom structured data class implements an appropriate interface, then it can provide its own conversion function to one of the other data types:
|
||||
|
||||
- `DomDataInterface`: The data object may produce a DOMDocument via its `getDomData()` method, which will be called in any instance where a DOM document is needed--typically with the xml formatter.
|
||||
- `ListDataInterface`: Any structured data object that implements this interface may use the `getListData()` method to produce the data set that will be used with the list formatter.
|
||||
- `TableDataInterface`: Any structured data object that implements this interface may use the `getTableData()` method to produce the data set that will be used with the table formatter.
|
||||
- `RenderCellInterface`: Structured data can also provide fine-grain control over how each cell in a table is rendered by implementing the RenderCellInterface. See the section below for information on how this is done.
|
||||
- `RestructureInterface`: The restructure interface can be implemented by a structured data object to restructure the data in response to options provided by the user. For example, the RowsOfFields and PropertyList data types use this interface to select and reorder the fields that were selected to appear in the output. Custom data types usually will not need to implement this interface, as they can inherit this behavior by extending RowsOfFields or PropertyList.
|
||||
|
||||
Additionally, structured data may be simplified to arrays via an array simplification object. To provide an array simplifier, implement `SimplifyToArrayInterface`, and register the simplifier via `FormatterManager::addSimplifier()`.
|
||||
|
||||
## Rendering Table Cells
|
||||
|
||||
By default, both the RowsOfFields and PropertyList data types presume that the contents of each cell is a simple string. To render more complicated cell contents, create a custom structured data class by extending either RowsOfFields or PropertyList, as desired, and implement RenderCellInterface. The `renderCell()` method of your class will then be called for each cell, and you may act on it as appropriate.
|
||||
```php
|
||||
public function renderCell($key, $cellData, FormatterOptions $options, $rowData)
|
||||
{
|
||||
// 'my-field' is always an array; convert it to a comma-separated list.
|
||||
if ($key == 'my-field') {
|
||||
return implode(',', $cellData);
|
||||
}
|
||||
// MyStructuredCellType has its own render function
|
||||
if ($cellData instanceof MyStructuredCellType) {
|
||||
return $cellData->myRenderfunction();
|
||||
}
|
||||
// If we do not recognize the cell data, return it unchnaged.
|
||||
return $cellData;
|
||||
}
|
||||
```
|
||||
Note that if your data structure is printed with a formatter other than one such as the table formatter, it will still be reordered per the selected fields, but cell rendering will **not** be done.
|
||||
|
||||
## API Usage
|
||||
|
||||
It is recommended to use [Consolidation/AnnotationCommand](https://github.com/consolidation/annotation-command) to manage commands and formatters. See the [AnnotationCommand API Usage](https://github.com/consolidation/annotation-command#api-usage) for details.
|
||||
|
||||
The FormatterManager may also be used directly, if desired:
|
||||
```php
|
||||
/**
|
||||
* @param OutputInterface $output Output stream to write to
|
||||
* @param string $format Data format to output in
|
||||
* @param mixed $structuredOutput Data to output
|
||||
* @param FormatterOptions $options Configuration informatin and User options
|
||||
*/
|
||||
function doFormat(
|
||||
OutputInterface $output,
|
||||
string $format,
|
||||
array $data,
|
||||
FormatterOptions $options)
|
||||
{
|
||||
$formatterManager = new FormatterManager();
|
||||
$formatterManager->write(output, $format, $data, $options);
|
||||
}
|
||||
```
|
||||
The FormatterOptions class is used to hold the configuration for the command output--things such as the default field list for tabular output, and so on--and also the current user-selected options to use during rendering, which may be provided using a Symfony InputInterface object:
|
||||
```
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$options = new FormatterOptions();
|
||||
$options
|
||||
->setInput($input)
|
||||
->setFieldLabels(['id' => 'ID', 'one' => 'First', 'two' => 'Second'])
|
||||
->setDefaultStringField('id');
|
||||
|
||||
$data = new RowsOfFields($this->getSomeData($input));
|
||||
return $this->doFormat($output, $options->getFormat(), $data, $options);
|
||||
}
|
||||
```
|
||||
## Comparison to Existing Solutions
|
||||
|
||||
Formatters have been in use in Drush since version 5. Drush allows formatters to be defined using simple classes, some of which may be configured using metadata. Furthermore, nested formatters are also allowed; for example, a list formatter may be given another formatter to use to format each of its rows. Nested formatters also require nested metadata, causing the code that constructed formatters to become very complicated and unweildy.
|
||||
|
||||
Consolidation/OutputFormatters maintains the simplicity of use provided by Drush formatters, but abandons nested metadata configuration in favor of using code in the formatter to configure itself, in order to keep the code simpler.
|
||||
|
68
vendor/consolidation/output-formatters/appveyor.yml
vendored
Normal file
68
vendor/consolidation/output-formatters/appveyor.yml
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
build: false
|
||||
shallow_clone: true
|
||||
platform: 'x86'
|
||||
clone_folder: C:\projects\output-formatters
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
## Cache composer bits
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\Composer\files -> composer.lock'
|
||||
|
||||
init:
|
||||
#https://github.com/composer/composer/blob/master/appveyor.yml
|
||||
#- SET ANSICON=121x90 (121x90)
|
||||
|
||||
# Inspired by https://github.com/Codeception/base/blob/master/appveyor.yml and https://github.com/phpmd/phpmd/blob/master/appveyor.yml
|
||||
install:
|
||||
- cinst -y curl
|
||||
- SET PATH=C:\Program Files\curl;%PATH%
|
||||
#which is only needed by the test suite.
|
||||
- cinst -y which
|
||||
- SET PATH=C:\Program Files\which;%PATH%
|
||||
- git clone -q https://github.com/acquia/DevDesktopCommon.git #For tar, cksum, ...
|
||||
- SET PATH=%APPVEYOR_BUILD_FOLDER%/DevDesktopCommon/bintools-win/msys/bin;%PATH%
|
||||
- SET PATH=C:\Program Files\MySql\MySQL Server 5.7\bin\;%PATH%
|
||||
#Install PHP per https://blog.wyrihaximus.net/2016/11/running-php-unit-tests-on-windows-using-appveyor-and-chocolatey/
|
||||
- ps: appveyor-retry cinst --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $Env:php_ver_target | Select-Object -first 1) -replace '[php|]','')
|
||||
- cd c:\tools\php70
|
||||
- copy php.ini-production php.ini
|
||||
|
||||
- echo extension_dir=ext >> php.ini
|
||||
- echo extension=php_openssl.dll >> php.ini
|
||||
- echo date.timezone="UTC" >> php.ini
|
||||
- echo variables_order="EGPCS" >> php.ini #May be unneeded.
|
||||
- echo mbstring.http_input=pass >> php.ini
|
||||
- echo mbstring.http_output=pass >> php.ini
|
||||
- echo sendmail_path=nul >> php.ini
|
||||
- echo extension=php_mbstring.dll >> php.ini
|
||||
- echo extension=php_curl.dll >> php.ini
|
||||
- echo extension=php_pdo_mysql.dll >> php.ini
|
||||
- echo extension=php_pdo_pgsql.dll >> php.ini
|
||||
- echo extension=php_pdo_sqlite.dll >> php.ini
|
||||
- echo extension=php_pgsql.dll >> php.ini
|
||||
- echo extension=php_gd2.dll >> php.ini
|
||||
- SET PATH=C:\tools\php70;%PATH%
|
||||
#Install Composer
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
#- appveyor DownloadFile https://getcomposer.org/composer.phar
|
||||
- php -r "readfile('http://getcomposer.org/installer');" | php
|
||||
#Install dependencies via Composer.
|
||||
#Newer versions of the dependencies have whitespace differences that break tests.
|
||||
#Maybe we should fix and do highest/lowest here someday.
|
||||
- copy composer.windows.lock composer.lock
|
||||
- php composer.phar -q install --prefer-dist -n
|
||||
- SET PATH=%APPVEYOR_BUILD_FOLDER%;%APPVEYOR_BUILD_FOLDER%/vendor/bin;%PATH%
|
||||
#Create a sandbox for testing. Don't think we need this.
|
||||
- mkdir c:\test_temp
|
||||
|
||||
test_script:
|
||||
- php composer.phar test
|
||||
- php composer.phar cs
|
||||
|
||||
# environment variables
|
||||
environment:
|
||||
global:
|
||||
php_ver_target: 7.0
|
||||
|
48
vendor/consolidation/output-formatters/composer.json
vendored
Normal file
48
vendor/consolidation/output-formatters/composer.json
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "consolidation/output-formatters",
|
||||
"description": "Format text by applying transformations provided by plug-in formatters.",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Greg Anderson",
|
||||
"email": "greg.1.anderson@greenknowe.org"
|
||||
}
|
||||
],
|
||||
"autoload":{
|
||||
"psr-4":{
|
||||
"Consolidation\\OutputFormatters\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Consolidation\\TestUtils\\": "tests/src"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"symfony/console": "^2.8|^3|^4",
|
||||
"symfony/finder": "^2.5|^3|^4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"satooshi/php-coveralls": "^1.0.2 | dev-master",
|
||||
"squizlabs/php_codesniffer": "^2.7",
|
||||
"victorjonsson/markdowndocs": "^1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"api": "phpdoc-md generate src > docs/api.md",
|
||||
"cs": "phpcs --standard=PSR2 -n src",
|
||||
"cbf": "phpcbf --standard=PSR2 -n src",
|
||||
"test": "phpunit --colors=always"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "5.6"
|
||||
}
|
||||
}
|
||||
}
|
2017
vendor/consolidation/output-formatters/composer.lock
generated
vendored
Normal file
2017
vendor/consolidation/output-formatters/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1897
vendor/consolidation/output-formatters/composer.windows.lock
vendored
Normal file
1897
vendor/consolidation/output-formatters/composer.windows.lock
vendored
Normal file
File diff suppressed because it is too large
Load diff
781
vendor/consolidation/output-formatters/docs/api.md
vendored
Normal file
781
vendor/consolidation/output-formatters/docs/api.md
vendored
Normal file
|
@ -0,0 +1,781 @@
|
|||
## Table of contents
|
||||
|
||||
- [\Consolidation\OutputFormatters\FormatterManager](#class-consolidationoutputformattersformattermanager)
|
||||
- [\Consolidation\OutputFormatters\Exception\UnknownFormatException](#class-consolidationoutputformattersexceptionunknownformatexception)
|
||||
- [\Consolidation\OutputFormatters\Exception\AbstractDataFormatException (abstract)](#class-consolidationoutputformattersexceptionabstractdataformatexception-abstract)
|
||||
- [\Consolidation\OutputFormatters\Exception\IncompatibleDataException](#class-consolidationoutputformattersexceptionincompatibledataexception)
|
||||
- [\Consolidation\OutputFormatters\Exception\InvalidFormatException](#class-consolidationoutputformattersexceptioninvalidformatexception)
|
||||
- [\Consolidation\OutputFormatters\Exception\UnknownFieldException](#class-consolidationoutputformattersexceptionunknownfieldexception)
|
||||
- [\Consolidation\OutputFormatters\Formatters\ListFormatter](#class-consolidationoutputformattersformatterslistformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\SectionsFormatter](#class-consolidationoutputformattersformatterssectionsformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\JsonFormatter](#class-consolidationoutputformattersformattersjsonformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\FormatterInterface (interface)](#interface-consolidationoutputformattersformattersformatterinterface)
|
||||
- [\Consolidation\OutputFormatters\Formatters\CsvFormatter](#class-consolidationoutputformattersformatterscsvformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\SerializeFormatter](#class-consolidationoutputformattersformattersserializeformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\StringFormatter](#class-consolidationoutputformattersformattersstringformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\VarExportFormatter](#class-consolidationoutputformattersformattersvarexportformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\YamlFormatter](#class-consolidationoutputformattersformattersyamlformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\TableFormatter](#class-consolidationoutputformattersformatterstableformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\XmlFormatter](#class-consolidationoutputformattersformattersxmlformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\PrintRFormatter](#class-consolidationoutputformattersformattersprintrformatter)
|
||||
- [\Consolidation\OutputFormatters\Formatters\RenderDataInterface (interface)](#interface-consolidationoutputformattersformattersrenderdatainterface)
|
||||
- [\Consolidation\OutputFormatters\Formatters\TsvFormatter](#class-consolidationoutputformattersformatterstsvformatter)
|
||||
- [\Consolidation\OutputFormatters\Options\OverrideOptionsInterface (interface)](#interface-consolidationoutputformattersoptionsoverrideoptionsinterface)
|
||||
- [\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\ListDataInterface (interface)](#interface-consolidationoutputformattersstructureddatalistdatainterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\TableDataInterface (interface)](#interface-consolidationoutputformattersstructureddatatabledatainterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\HelpDocument](#class-consolidationoutputformattersstructureddatahelpdocument)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\OriginalDataInterface (interface)](#interface-consolidationoutputformattersstructureddataoriginaldatainterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\RowsOfFields](#class-consolidationoutputformattersstructureddatarowsoffields)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\RestructureInterface (interface)](#interface-consolidationoutputformattersstructureddatarestructureinterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\AbstractStructuredList (abstract)](#class-consolidationoutputformattersstructureddataabstractstructuredlist-abstract)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\ListDataFromKeys](#class-consolidationoutputformattersstructureddatalistdatafromkeys)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\PropertyList](#class-consolidationoutputformattersstructureddatapropertylist)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface (interface)](#interface-consolidationoutputformattersstructureddatarendercellinterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\CallableRenderer](#class-consolidationoutputformattersstructureddatacallablerenderer)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface (interface)](#interface-consolidationoutputformattersstructureddatarendercellcollectioninterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\AssociativeList](#class-consolidationoutputformattersstructureddataassociativelist)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\Xml\XmlSchemaInterface (interface)](#interface-consolidationoutputformattersstructureddataxmlxmlschemainterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\Xml\DomDataInterface (interface)](#interface-consolidationoutputformattersstructureddataxmldomdatainterface)
|
||||
- [\Consolidation\OutputFormatters\StructuredData\Xml\XmlSchema](#class-consolidationoutputformattersstructureddataxmlxmlschema)
|
||||
- [\Consolidation\OutputFormatters\Transformations\PropertyParser](#class-consolidationoutputformatterstransformationspropertyparser)
|
||||
- [\Consolidation\OutputFormatters\Transformations\PropertyListTableTransformation](#class-consolidationoutputformatterstransformationspropertylisttabletransformation)
|
||||
- [\Consolidation\OutputFormatters\Transformations\TableTransformation](#class-consolidationoutputformatterstransformationstabletransformation)
|
||||
- [\Consolidation\OutputFormatters\Transformations\ReorderFields](#class-consolidationoutputformatterstransformationsreorderfields)
|
||||
- [\Consolidation\OutputFormatters\Transformations\DomToArraySimplifier](#class-consolidationoutputformatterstransformationsdomtoarraysimplifier)
|
||||
- [\Consolidation\OutputFormatters\Transformations\WordWrapper](#class-consolidationoutputformatterstransformationswordwrapper)
|
||||
- [\Consolidation\OutputFormatters\Transformations\OverrideRestructureInterface (interface)](#interface-consolidationoutputformatterstransformationsoverriderestructureinterface)
|
||||
- [\Consolidation\OutputFormatters\Transformations\SimplifyToArrayInterface (interface)](#interface-consolidationoutputformatterstransformationssimplifytoarrayinterface)
|
||||
- [\Consolidation\OutputFormatters\Transformations\Wrap\CalculateWidths](#class-consolidationoutputformatterstransformationswrapcalculatewidths)
|
||||
- [\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)
|
||||
- [\Consolidation\OutputFormatters\Validate\ValidationInterface (interface)](#interface-consolidationoutputformattersvalidatevalidationinterface)
|
||||
- [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface (interface)](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface)
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\FormatterManager
|
||||
|
||||
> Manage a collection of formatters; return one on request.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct()</strong> : <em>void</em> |
|
||||
| public | <strong>addDefaultFormatters()</strong> : <em>void</em> |
|
||||
| public | <strong>addDefaultSimplifiers()</strong> : <em>void</em> |
|
||||
| public | <strong>addFormatter(</strong><em>string</em> <strong>$key</strong>, <em>string/[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>)</strong> : <em>[\Consolidation\OutputFormatters\FormatterManager](#class-consolidationoutputformattersformattermanager)</em><br /><em>Add a formatter</em> |
|
||||
| public | <strong>addSimplifier(</strong><em>[\Consolidation\OutputFormatters\Transformations\SimplifyToArrayInterface](#interface-consolidationoutputformatterstransformationssimplifytoarrayinterface)</em> <strong>$simplifier</strong>)</strong> : <em>[\Consolidation\OutputFormatters\FormatterManager](#class-consolidationoutputformattersformattermanager)</em><br /><em>Add a simplifier</em> |
|
||||
| public | <strong>automaticOptions(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>, <em>mixed</em> <strong>$dataType</strong>)</strong> : <em>\Symfony\Component\Console\Input\InputOption[]</em><br /><em>Return a set of InputOption based on the annotations of a command.</em> |
|
||||
| public | <strong>getFormatter(</strong><em>string</em> <strong>$format</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em><br /><em>Fetch the requested formatter.</em> |
|
||||
| public | <strong>hasFormatter(</strong><em>mixed</em> <strong>$format</strong>)</strong> : <em>bool</em><br /><em>Test to see if the stipulated format exists</em> |
|
||||
| public | <strong>isValidDataType(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em> |
|
||||
| public | <strong>isValidFormat(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$dataType</strong>)</strong> : <em>bool</em> |
|
||||
| public | <strong>overrideOptions(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Allow the formatter to mess with the configuration options before any transformations et. al. get underway.</em> |
|
||||
| public | <strong>overrideRestructure(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Allow the formatter access to the raw structured data prior to restructuring. For example, the 'list' formatter may wish to display the row keys when provided table output. If this function returns a result that does not evaluate to 'false', then that result will be used as-is, and restructuring and validation will not occur.</em> |
|
||||
| public | <strong>renderData(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Render the data as necessary (e.g. to select or reorder fields).</em> |
|
||||
| public | <strong>restructureData(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Restructure the data as necessary (e.g. to select or reorder fields).</em> |
|
||||
| public | <strong>validFormats(</strong><em>mixed</em> <strong>$dataType</strong>)</strong> : <em>array</em><br /><em>Return the identifiers for all valid data types that have been registered.</em> |
|
||||
| public | <strong>validateData(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Determine if the provided data is compatible with the formatter being used.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>string</em> <strong>$format</strong>, <em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em><br /><em>Format and write output</em> |
|
||||
| protected | <strong>availableFieldsList(</strong><em>mixed</em> <strong>$availableFields</strong>)</strong> : <em>string[]</em><br /><em>Given a list of available fields, return a list of field descriptions.</em> |
|
||||
| protected | <strong>canSimplifyToArray(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$structuredOutput</strong>)</strong> : <em>bool</em> |
|
||||
| protected | <strong>simplifyToArray(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>validateAndRestructure(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Exception\UnknownFormatException
|
||||
|
||||
> Indicates that the requested format does not exist.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$format</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends \Exception*
|
||||
|
||||
*This class implements \Throwable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Exception\AbstractDataFormatException (abstract)
|
||||
|
||||
> Contains some helper functions used by exceptions in this project.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| protected static | <strong>describeAllowedTypes(</strong><em>mixed</em> <strong>$allowedTypes</strong>)</strong> : <em>void</em> |
|
||||
| protected static | <strong>describeDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$data</strong>)</strong> : <em>string</em><br /><em>Return a description of the data type represented by the provided parameter. \ArrayObject is used as a proxy to mean an array primitive (or an ArrayObject).</em> |
|
||||
| protected static | <strong>describeListOfAllowedTypes(</strong><em>mixed</em> <strong>$allowedTypes</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends \Exception*
|
||||
|
||||
*This class implements \Throwable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Exception\IncompatibleDataException
|
||||
|
||||
> Represents an incompatibility between the output data and selected formatter.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>[\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)</em> <strong>$formatter</strong>, <em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$allowedTypes</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\Exception\AbstractDataFormatException](#class-consolidationoutputformattersexceptionabstractdataformatexception-abstract)*
|
||||
|
||||
*This class implements \Throwable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Exception\InvalidFormatException
|
||||
|
||||
> Represents an incompatibility between the output data and selected formatter.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$format</strong>, <em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$validFormats</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\Exception\AbstractDataFormatException](#class-consolidationoutputformattersexceptionabstractdataformatexception-abstract)*
|
||||
|
||||
*This class implements \Throwable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Exception\UnknownFieldException
|
||||
|
||||
> Indicates that the requested format does not exist.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$field</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends \Exception*
|
||||
|
||||
*This class implements \Throwable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\ListFormatter
|
||||
|
||||
> Display the data in a simple list. This formatter prints a plain, unadorned list of data, with each data item appearing on a separate line. If you wish your list to contain headers, then use the table formatter, and wrap your data in an PropertyList.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>overrideRestructure(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Select data to use directly from the structured output, before the restructure operation has been executed.</em> |
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected | <strong>renderEachCell(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Transformations\OverrideRestructureInterface](#interface-consolidationoutputformatterstransformationsoverriderestructureinterface), [\Consolidation\OutputFormatters\Formatters\RenderDataInterface](#interface-consolidationoutputformattersformattersrenderdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\SectionsFormatter
|
||||
|
||||
> Display sections of data. This formatter takes data in the RowsOfFields data type. Each row represents one section; the data in each section is rendered in two columns, with the key in the first column and the value in the second column.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>Return the list of data types acceptable to this formatter</em> |
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
| public | <strong>validDataTypes()</strong> : <em>void</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>mixed</em><br /><em>Throw an IncompatibleDataException if the provided data cannot be processed by this formatter. Return the source data if it is valid. The data may be encapsulated or converted if necessary.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected | <strong>renderEachCell(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface), [\Consolidation\OutputFormatters\Formatters\RenderDataInterface](#interface-consolidationoutputformattersformattersrenderdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\JsonFormatter
|
||||
|
||||
> Json formatter Convert an array or ArrayObject into Json.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Formatters\FormatterInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\CsvFormatter
|
||||
|
||||
> Comma-separated value formatters Display the provided structured data in a comma-separated list. If there are multiple records provided, then they will be printed one per line. The primary data types accepted are RowsOfFields and PropertyList. The later behaves exactly like the former, save for the fact that it contains but a single row. This formmatter can also accept a PHP array; this is also interpreted as a single-row of data with no header.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>Return the list of data types acceptable to this formatter</em> |
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
| public | <strong>validDataTypes()</strong> : <em>void</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected | <strong>csvEscape(</strong><em>mixed</em> <strong>$data</strong>, <em>string</em> <strong>$delimiter=`','`</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>getDefaultFormatterOptions()</strong> : <em>array</em><br /><em>Return default values for formatter options</em> |
|
||||
| protected | <strong>renderEachCell(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>writeOneLine(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface), [\Consolidation\OutputFormatters\Formatters\RenderDataInterface](#interface-consolidationoutputformattersformattersrenderdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\SerializeFormatter
|
||||
|
||||
> Serialize formatter Run provided date thruogh serialize.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\StringFormatter
|
||||
|
||||
> String formatter This formatter is used as the default action when no particular formatter is requested. It will print the provided data only if it is a string; if any other type is given, then nothing is printed.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>All data types are acceptable.</em> |
|
||||
| public | <strong>overrideOptions(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Allow the formatter to mess with the configuration options before any transformations et. al. get underway.</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>void</em><br /><em>Always validate any data, though. This format will never cause an error if it is selected for an incompatible data type; at worse, it simply does not print any data.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected | <strong>reduceToSigleFieldAndWrite(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em><br /><em>If the data provided to a 'string' formatter is a table, then try to emit it as a TSV value.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface), [\Consolidation\OutputFormatters\Options\OverrideOptionsInterface](#interface-consolidationoutputformattersoptionsoverrideoptionsinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\VarExportFormatter
|
||||
|
||||
> Var_export formatter Run provided date thruogh var_export.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\YamlFormatter
|
||||
|
||||
> Yaml formatter Convert an array or ArrayObject into Yaml.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\TableFormatter
|
||||
|
||||
> Display a table of data with the Symfony Table class. This formatter takes data of either the RowsOfFields or PropertyList data type. Tables can be rendered with the rows running either vertically (the normal orientation) or horizontally. By default, associative lists will be displayed as two columns, with the key in the first column and the value in the second column.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct()</strong> : <em>void</em> |
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>Return the list of data types acceptable to this formatter</em> |
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
| public | <strong>validDataTypes()</strong> : <em>void</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>mixed</em><br /><em>Throw an IncompatibleDataException if the provided data cannot be processed by this formatter. Return the source data if it is valid. The data may be encapsulated or converted if necessary.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected static | <strong>addCustomTableStyles(</strong><em>mixed</em> <strong>$table</strong>)</strong> : <em>void</em><br /><em>Add our custom table style(s) to the table.</em> |
|
||||
| protected | <strong>renderEachCell(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>wrap(</strong><em>mixed</em> <strong>$headers</strong>, <em>array</em> <strong>$data</strong>, <em>\Symfony\Component\Console\Helper\TableStyle</em> <strong>$tableStyle</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>array</em><br /><em>Wrap the table data</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface), [\Consolidation\OutputFormatters\Formatters\RenderDataInterface](#interface-consolidationoutputformattersformattersrenderdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\XmlFormatter
|
||||
|
||||
> Display a table of data with the Symfony Table class. This formatter takes data of either the RowsOfFields or PropertyList data type. Tables can be rendered with the rows running either vertically (the normal orientation) or horizontally. By default, associative lists will be displayed as two columns, with the key in the first column and the value in the second column.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct()</strong> : <em>void</em> |
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>Return the list of data types acceptable to this formatter</em> |
|
||||
| public | <strong>validDataTypes()</strong> : <em>void</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>mixed</em><br /><em>Throw an IncompatibleDataException if the provided data cannot be processed by this formatter. Return the source data if it is valid. The data may be encapsulated or converted if necessary.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface), [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\PrintRFormatter
|
||||
|
||||
> Print_r formatter Run provided date thruogh print_r.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Formatters\RenderDataInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Formatters\TsvFormatter
|
||||
|
||||
> Tab-separated value formatters Display the provided structured data in a tab-separated list. Output escaping is much lighter, since there is no allowance for altering the delimiter.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>renderData(</strong><em>mixed</em> <strong>$originalData</strong>, <em>mixed</em> <strong>$restructuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of the output data just before it is to be printed, prior to output but after restructuring and validation.</em> |
|
||||
| public | <strong>write(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>string</em><br /><em>Given structured data, apply appropriate formatting, and return a printable string.</em> |
|
||||
| protected | <strong>getDefaultFormatterOptions()</strong> : <em>mixed</em> |
|
||||
| protected | <strong>tsvEscape(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>writeOneLine(</strong><em>\Symfony\Component\Console\Output\OutputInterface</em> <strong>$output</strong>, <em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\Formatters\CsvFormatter](#class-consolidationoutputformattersformatterscsvformatter)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Formatters\RenderDataInterface](#interface-consolidationoutputformattersformattersrenderdatainterface), [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface), [\Consolidation\OutputFormatters\Validate\ValidDataTypesInterface](#interface-consolidationoutputformattersvalidatevaliddatatypesinterface), [\Consolidation\OutputFormatters\Formatters\FormatterInterface](#interface-consolidationoutputformattersformattersformatterinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Options\OverrideOptionsInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>overrideOptions(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Allow the formatter to mess with the configuration options before any transformations et. al. get underway.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Options\FormatterOptions
|
||||
|
||||
> FormetterOptions holds information that affects the way a formatter renders its output. There are three places where a formatter might get options from: 1. Configuration associated with the command that produced the output. This is passed in to FormatterManager::write() along with the data to format. It might originally come from annotations on the command, or it might come from another source. Examples include the field labels for a table, or the default list of fields to display. 2. Options specified by the user, e.g. by commandline options. 3. Default values associated with the formatter itself. This class caches configuration from sources (1) and (2), and expects to be provided the defaults, (3), whenever a value is requested.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>array</em> <strong>$configurationData=array()</strong>, <em>array</em> <strong>$options=array()</strong>)</strong> : <em>void</em><br /><em>Create a new FormatterOptions with the configuration data and the user-specified options for this request.</em> |
|
||||
| public | <strong>get(</strong><em>string</em> <strong>$key</strong>, <em>array</em> <strong>$defaults=array()</strong>, <em>bool/mixed</em> <strong>$default=false</strong>)</strong> : <em>mixed</em><br /><em>Get a formatter option</em> |
|
||||
| public | <strong>getConfigurationData()</strong> : <em>array</em><br /><em>Return a reference to the configuration data for this object.</em> |
|
||||
| public | <strong>getFormat(</strong><em>array</em> <strong>$defaults=array()</strong>)</strong> : <em>string</em><br /><em>Determine the format that was requested by the caller.</em> |
|
||||
| public | <strong>getInputOptions(</strong><em>array</em> <strong>$defaults</strong>)</strong> : <em>array</em><br /><em>Return all of the options from the provided $defaults array that exist in our InputInterface object.</em> |
|
||||
| public | <strong>getOptions()</strong> : <em>array</em><br /><em>Return a reference to the user-specified options for this request.</em> |
|
||||
| public | <strong>getXmlSchema()</strong> : <em>[\Consolidation\OutputFormatters\StructuredData\Xml\XmlSchema](#class-consolidationoutputformattersstructureddataxmlxmlschema)</em><br /><em>Return the XmlSchema to use with --format=xml for data types that support that. This is used when an array needs to be converted into xml.</em> |
|
||||
| public | <strong>override(</strong><em>array</em> <strong>$configurationData</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Create a new FormatterOptions object with new configuration data (provided), and the same options data as this instance.</em> |
|
||||
| public | <strong>parsePropertyList(</strong><em>string</em> <strong>$value</strong>)</strong> : <em>array</em><br /><em>Convert from a textual list to an array</em> |
|
||||
| public | <strong>setConfigurationData(</strong><em>array</em> <strong>$configurationData</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Change the configuration data for this formatter options object.</em> |
|
||||
| public | <strong>setConfigurationDefault(</strong><em>string</em> <strong>$key</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>\Consolidation\OutputFormatters\Options\FormetterOptions</em><br /><em>Change one configuration value for this formatter option, but only if it does not already have a value set.</em> |
|
||||
| public | <strong>setDefaultFields(</strong><em>mixed</em> <strong>$fields</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setDefaultStringField(</strong><em>mixed</em> <strong>$defaultStringField</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setDelimiter(</strong><em>mixed</em> <strong>$delimiter</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setFieldLabels(</strong><em>mixed</em> <strong>$fieldLabels</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setIncludeFieldLables(</strong><em>mixed</em> <strong>$includFieldLables</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setInput(</strong><em>\Symfony\Component\Console\Input\InputInterface</em> <strong>$input</strong>)</strong> : <em>\Consolidation\OutputFormatters\Options\type</em><br /><em>Provide a Symfony Console InputInterface containing the user-specified options for this request.</em> |
|
||||
| public | <strong>setListDelimiter(</strong><em>mixed</em> <strong>$listDelimiter</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setListOrientation(</strong><em>mixed</em> <strong>$listOrientation</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setOption(</strong><em>string</em> <strong>$key</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Change one option value specified by the user for this request.</em> |
|
||||
| public | <strong>setOptions(</strong><em>array</em> <strong>$options</strong>)</strong> : <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em><br /><em>Set all of the options that were specified by the user for this request.</em> |
|
||||
| public | <strong>setRowLabels(</strong><em>mixed</em> <strong>$rowLabels</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setTableStyle(</strong><em>mixed</em> <strong>$style</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>setWidth(</strong><em>mixed</em> <strong>$width</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>defaultsForKey(</strong><em>string</em> <strong>$key</strong>, <em>array</em> <strong>$defaults</strong>, <em>bool</em> <strong>$default=false</strong>)</strong> : <em>array</em><br /><em>Reduce provided defaults to the single item identified by '$key', if it exists, or an empty array otherwise.</em> |
|
||||
| protected | <strong>fetch(</strong><em>string</em> <strong>$key</strong>, <em>array</em> <strong>$defaults=array()</strong>, <em>bool/mixed</em> <strong>$default=false</strong>)</strong> : <em>mixed</em><br /><em>Look up a key, and return its raw value.</em> |
|
||||
| protected | <strong>fetchRawValues(</strong><em>array</em> <strong>$defaults=array()</strong>)</strong> : <em>array</em><br /><em>Look up all of the items associated with the provided defaults.</em> |
|
||||
| protected | <strong>getOptionFormat(</strong><em>string</em> <strong>$key</strong>)</strong> : <em>string</em><br /><em>Given a specific key, return the class method name of the parsing method for data stored under this key.</em> |
|
||||
| protected | <strong>parse(</strong><em>string</em> <strong>$key</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>mixed</em><br /><em>Given the raw value for a specific key, do any type conversion (e.g. from a textual list to an array) needed for the data.</em> |
|
||||
| protected | <strong>setConfigurationValue(</strong><em>string</em> <strong>$key</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>\Consolidation\OutputFormatters\Options\FormetterOptions</em><br /><em>Change one configuration value for this formatter option.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\ListDataInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getListData(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>array</em><br /><em>Convert data to a format suitable for use in a list. By default, the array values will be used. Implement ListDataInterface to use some other criteria (e.g. array keys).</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\TableDataInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getOriginalData()</strong> : <em>mixed</em><br /><em>Return the original data for this table. Used by any formatter that is -not- a table.</em> |
|
||||
| public | <strong>getTableData(</strong><em>bool/boolean</em> <strong>$includeRowKey=false</strong>)</strong> : <em>array</em><br /><em>Convert structured data into a form suitable for use by the table formatter. key from each row.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\HelpDocument
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getDomData()</strong> : <em>[\DomDocument](http://php.net/manual/en/class.domdocument.php)</em><br /><em>Convert data into a \DomDocument.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\Xml\DomDataInterface](#interface-consolidationoutputformattersstructureddataxmldomdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\OriginalDataInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getOriginalData()</strong> : <em>mixed</em><br /><em>Return the original data for this table. Used by any formatter that expects an array.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\RowsOfFields
|
||||
|
||||
> Holds an array where each element of the array is one row, and each row contains an associative array where the keys are the field names, and the values are the field data. It is presumed that every row contains the same keys.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getListData(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em> |
|
||||
| public | <strong>restructure(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>\Consolidation\OutputFormatters\StructuredData\Consolidation\OutputFormatters\Transformations\TableTransformation</em><br /><em>Restructure this data for output by converting it into a table transformation object.</em> |
|
||||
| protected | <strong>defaultOptions()</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\StructuredData\AbstractStructuredList](#class-consolidationoutputformattersstructureddataabstractstructuredlist-abstract)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface](#interface-consolidationoutputformattersstructureddatarendercellcollectioninterface), [\Consolidation\OutputFormatters\StructuredData\RestructureInterface](#interface-consolidationoutputformattersstructureddatarestructureinterface), \Countable, \Serializable, \ArrayAccess, \Traversable, \IteratorAggregate, [\Consolidation\OutputFormatters\StructuredData\ListDataInterface](#interface-consolidationoutputformattersstructureddatalistdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\RestructureInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>restructure(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em><br /><em>Allow structured data to be restructured -- i.e. to select fields to show, reorder fields, etc.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\AbstractStructuredList (abstract)
|
||||
|
||||
> Holds an array where each element of the array is one row, and each row contains an associative array where the keys are the field names, and the values are the field data. It is presumed that every row contains the same keys.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>addRenderer(</strong><em>[\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)</em> <strong>$renderer</strong>, <em>string</em> <strong>$priority=`'normal'`</strong>)</strong> : <em>\Consolidation\OutputFormatters\StructuredData\$this</em><br /><em>Add a renderer</em> |
|
||||
| public | <strong>addRendererFunction(</strong><em>\callable</em> <strong>$rendererFn</strong>, <em>string</em> <strong>$priority=`'normal'`</strong>)</strong> : <em>\Consolidation\OutputFormatters\StructuredData\$this</em><br /><em>Add a callable as a renderer</em> |
|
||||
| public | <strong>renderCell(</strong><em>mixed</em> <strong>$key</strong>, <em>mixed</em> <strong>$cellData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>, <em>mixed</em> <strong>$rowData</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>abstract restructure(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>createTableTransformation(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$options</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>defaultOptions()</strong> : <em>array</em><br /><em>A structured list may provide its own set of default options. These will be used in place of the command's default options (from the annotations) in instances where the user does not provide the options explicitly (on the commandline) or implicitly (via a configuration file).</em> |
|
||||
| protected | <strong>getFields(</strong><em>mixed</em> <strong>$options</strong>, <em>mixed</em> <strong>$defaults</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>getReorderedFieldLabels(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$options</strong>, <em>mixed</em> <strong>$defaults</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>instantiateTableTransformation(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$fieldLabels</strong>, <em>mixed</em> <strong>$rowLabels</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\StructuredData\ListDataFromKeys](#class-consolidationoutputformattersstructureddatalistdatafromkeys)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\ListDataInterface](#interface-consolidationoutputformattersstructureddatalistdatainterface), \IteratorAggregate, \Traversable, \ArrayAccess, \Serializable, \Countable, [\Consolidation\OutputFormatters\StructuredData\RestructureInterface](#interface-consolidationoutputformattersstructureddatarestructureinterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface](#interface-consolidationoutputformattersstructureddatarendercellcollectioninterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\ListDataFromKeys
|
||||
|
||||
> Represents aribtrary array data (structured or unstructured) where the data to display in --list format comes from the array keys.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>getListData(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em> |
|
||||
|
||||
*This class extends \ArrayObject*
|
||||
|
||||
*This class implements \Countable, \Serializable, \ArrayAccess, \Traversable, \IteratorAggregate, [\Consolidation\OutputFormatters\StructuredData\ListDataInterface](#interface-consolidationoutputformattersstructureddatalistdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\PropertyList
|
||||
|
||||
> Holds an array where each element of the array is one key : value pair. The keys must be unique, as is typically the case for associative arrays.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getListData(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em> |
|
||||
| public | <strong>restructure(</strong><em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>\Consolidation\OutputFormatters\StructuredData\Consolidation\OutputFormatters\Transformations\TableTransformation</em><br /><em>Restructure this data for output by converting it into a table transformation object.</em> |
|
||||
| protected | <strong>defaultOptions()</strong> : <em>void</em> |
|
||||
| protected | <strong>instantiateTableTransformation(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$fieldLabels</strong>, <em>mixed</em> <strong>$rowLabels</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\StructuredData\AbstractStructuredList](#class-consolidationoutputformattersstructureddataabstractstructuredlist-abstract)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface](#interface-consolidationoutputformattersstructureddatarendercellcollectioninterface), [\Consolidation\OutputFormatters\StructuredData\RestructureInterface](#interface-consolidationoutputformattersstructureddatarestructureinterface), \Countable, \Serializable, \ArrayAccess, \Traversable, \IteratorAggregate, [\Consolidation\OutputFormatters\StructuredData\ListDataInterface](#interface-consolidationoutputformattersstructureddatalistdatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\RenderCellInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>renderCell(</strong><em>string</em> <strong>$key</strong>, <em>mixed</em> <strong>$cellData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>, <em>array</em> <strong>$rowData</strong>)</strong> : <em>mixed</em><br /><em>Convert the contents of one table cell into a string, so that it may be placed in the table. Renderer should return the $cellData passed to it if it does not wish to process it.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\CallableRenderer
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>\callable</em> <strong>$renderFunction</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>renderCell(</strong><em>mixed</em> <strong>$key</strong>, <em>mixed</em> <strong>$cellData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>, <em>mixed</em> <strong>$rowData</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>addRenderer(</strong><em>[\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)</em> <strong>$renderer</strong>)</strong> : <em>\Consolidation\OutputFormatters\StructuredData\$this</em><br /><em>Add a renderer</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\AssociativeList
|
||||
|
||||
> Old name for PropertyList class.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\StructuredData\PropertyList](#class-consolidationoutputformattersstructureddatapropertylist)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\ListDataInterface](#interface-consolidationoutputformattersstructureddatalistdatainterface), \IteratorAggregate, \Traversable, \ArrayAccess, \Serializable, \Countable, [\Consolidation\OutputFormatters\StructuredData\RestructureInterface](#interface-consolidationoutputformattersstructureddatarestructureinterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellCollectionInterface](#interface-consolidationoutputformattersstructureddatarendercellcollectioninterface), [\Consolidation\OutputFormatters\StructuredData\RenderCellInterface](#interface-consolidationoutputformattersstructureddatarendercellinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\Xml\XmlSchemaInterface
|
||||
|
||||
> When using arrays, we could represent XML data in a number of different ways. For example, given the following XML data strucutre: <document id="1" name="doc"> <foobars> <foobar id="123"> <name>blah</name> <widgets> <widget> <foo>a</foo> <bar>b</bar> <baz>c</baz> </widget> </widgets> </foobar> </foobars> </document> This could be: [ 'id' => 1, 'name' => 'doc', 'foobars' => [ [ 'id' => '123', 'name' => 'blah', 'widgets' => [ [ 'foo' => 'a', 'bar' => 'b', 'baz' => 'c', ] ], ], ] ] The challenge is more in going from an array back to the more structured xml format. Note that any given key => string mapping could represent either an attribute, or a simple XML element containing only a string value. In general, we do *not* want to add extra layers of nesting in the data structure to disambiguate between these kinds of data, as we want the source data to render cleanly into other formats, e.g. yaml, json, et. al., and we do not want to force every data provider to have to consider the optimal xml schema for their data. Our strategy, therefore, is to expect clients that wish to provide a very specific xml representation to return a DOMDocument, and, for other data structures where xml is a secondary concern, then we will use some default heuristics to convert from arrays to xml.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>arrayToXml(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>[\DOMDocument](http://php.net/manual/en/class.domdocument.php)</em><br /><em>Convert data to a format suitable for use in a list. By default, the array values will be used. Implement ListDataInterface to use some other criteria (e.g. array keys).</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\StructuredData\Xml\DomDataInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getDomData()</strong> : <em>[\DomDocument](http://php.net/manual/en/class.domdocument.php)</em><br /><em>Convert data into a \DomDocument.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\StructuredData\Xml\XmlSchema
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>array</em> <strong>$elementList=array()</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>arrayToXML(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>addXmlChildren(</strong><em>[\DOMDocument](http://php.net/manual/en/class.domdocument.php)</em> <strong>$dom</strong>, <em>mixed</em> <strong>$xmlParent</strong>, <em>mixed</em> <strong>$elementName</strong>, <em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>addXmlData(</strong><em>[\DOMDocument](http://php.net/manual/en/class.domdocument.php)</em> <strong>$dom</strong>, <em>mixed</em> <strong>$xmlParent</strong>, <em>mixed</em> <strong>$elementName</strong>, <em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>addXmlDataOrAttribute(</strong><em>[\DOMDocument](http://php.net/manual/en/class.domdocument.php)</em> <strong>$dom</strong>, <em>mixed</em> <strong>$xmlParent</strong>, <em>mixed</em> <strong>$elementName</strong>, <em>mixed</em> <strong>$key</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>determineElementName(</strong><em>mixed</em> <strong>$key</strong>, <em>mixed</em> <strong>$childElementName</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>getDefaultElementName(</strong><em>mixed</em> <strong>$parentElementName</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>getTopLevelElementName(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>inElementList(</strong><em>mixed</em> <strong>$parentElementName</strong>, <em>mixed</em> <strong>$elementName</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>isAssoc(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>bool</em> |
|
||||
| protected | <strong>isAttribute(</strong><em>mixed</em> <strong>$parentElementName</strong>, <em>mixed</em> <strong>$elementName</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>bool</em> |
|
||||
| protected | <strong>singularForm(</strong><em>mixed</em> <strong>$name</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\Xml\XmlSchemaInterface](#interface-consolidationoutputformattersstructureddataxmlxmlschemainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\PropertyParser
|
||||
|
||||
> Transform a string of properties into a PHP associative array. Input: one: red two: white three: blue Output: [ 'one' => 'red', 'two' => 'white', 'three' => 'blue', ]
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public static | <strong>parse(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>void</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\PropertyListTableTransformation
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>getOriginalData()</strong> : <em>mixed</em> |
|
||||
|
||||
*This class extends [\Consolidation\OutputFormatters\Transformations\TableTransformation](#class-consolidationoutputformatterstransformationstabletransformation)*
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\StructuredData\OriginalDataInterface](#interface-consolidationoutputformattersstructureddataoriginaldatainterface), [\Consolidation\OutputFormatters\StructuredData\TableDataInterface](#interface-consolidationoutputformattersstructureddatatabledatainterface), \IteratorAggregate, \Traversable, \ArrayAccess, \Serializable, \Countable*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\TableTransformation
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$fieldLabels</strong>, <em>array</em> <strong>$rowLabels=array()</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>getHeader(</strong><em>mixed</em> <strong>$key</strong>)</strong> : <em>mixed</em> |
|
||||
| public | <strong>getHeaders()</strong> : <em>mixed</em> |
|
||||
| public | <strong>getLayout()</strong> : <em>mixed</em> |
|
||||
| public | <strong>getOriginalData()</strong> : <em>mixed</em> |
|
||||
| public | <strong>getRowLabel(</strong><em>mixed</em> <strong>$rowid</strong>)</strong> : <em>mixed</em> |
|
||||
| public | <strong>getRowLabels()</strong> : <em>mixed</em> |
|
||||
| public | <strong>getTableData(</strong><em>bool</em> <strong>$includeRowKey=false</strong>)</strong> : <em>mixed</em> |
|
||||
| public | <strong>isList()</strong> : <em>bool</em> |
|
||||
| public | <strong>setLayout(</strong><em>mixed</em> <strong>$layout</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>convertTableToList()</strong> : <em>void</em> |
|
||||
| protected | <strong>getRowDataWithKey(</strong><em>mixed</em> <strong>$data</strong>)</strong> : <em>mixed</em> |
|
||||
| protected static | <strong>transformRow(</strong><em>mixed</em> <strong>$row</strong>, <em>mixed</em> <strong>$fieldLabels</strong>)</strong> : <em>void</em> |
|
||||
| protected static | <strong>transformRows(</strong><em>mixed</em> <strong>$data</strong>, <em>mixed</em> <strong>$fieldLabels</strong>)</strong> : <em>void</em> |
|
||||
|
||||
*This class extends \ArrayObject*
|
||||
|
||||
*This class implements \Countable, \Serializable, \ArrayAccess, \Traversable, \IteratorAggregate, [\Consolidation\OutputFormatters\StructuredData\TableDataInterface](#interface-consolidationoutputformattersstructureddatatabledatainterface), [\Consolidation\OutputFormatters\StructuredData\OriginalDataInterface](#interface-consolidationoutputformattersstructureddataoriginaldatainterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\ReorderFields
|
||||
|
||||
> Reorder the field labels based on the user-selected fields to display.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>reorder(</strong><em>string/array</em> <strong>$fields</strong>, <em>array</em> <strong>$fieldLabels</strong>, <em>array</em> <strong>$data</strong>)</strong> : <em>array</em><br /><em>Given a simple list of user-supplied field keys or field labels, return a reordered version of the field labels matching the user selection. key to the field label</em> |
|
||||
| protected | <strong>convertToRegex(</strong><em>mixed</em> <strong>$str</strong>)</strong> : <em>void</em><br /><em>Convert the provided string into a regex suitable for use in preg_match. Matching occurs in the same way as the Symfony Finder component: http://symfony.com/doc/current/components/finder.html#file-name</em> |
|
||||
| protected | <strong>getSelectedFieldKeys(</strong><em>mixed</em> <strong>$fields</strong>, <em>mixed</em> <strong>$fieldLabels</strong>)</strong> : <em>mixed</em> |
|
||||
| protected | <strong>isRegex(</strong><em>string</em> <strong>$str</strong>)</strong> : <em>bool Whether the given string is a regex</em><br /><em>Checks whether the string is a regex. This function is copied from MultiplePcreFilterIterator in the Symfony Finder component.</em> |
|
||||
| protected | <strong>matchFieldInLabelMap(</strong><em>mixed</em> <strong>$field</strong>, <em>mixed</em> <strong>$fieldLabels</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>reorderFieldLabels(</strong><em>mixed</em> <strong>$fields</strong>, <em>mixed</em> <strong>$fieldLabels</strong>, <em>mixed</em> <strong>$data</strong>)</strong> : <em>void</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\DomToArraySimplifier
|
||||
|
||||
> Simplify a DOMDocument to an array.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct()</strong> : <em>void</em> |
|
||||
| public | <strong>canSimplify(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em> |
|
||||
| public | <strong>simplifyToArray(</strong><em>mixed</em> <strong>$structuredData</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>void</em> |
|
||||
| protected | <strong>elementToArray(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Recursively convert the provided DOM element into a php array.</em> |
|
||||
| protected | <strong>getIdOfValue(</strong><em>mixed</em> <strong>$value</strong>)</strong> : <em>string</em><br /><em>If the object has an 'id' or 'name' element, then use that as the array key when storing this value in its parent.</em> |
|
||||
| protected | <strong>getNodeAttributes(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Get all of the attributes of the provided element.</em> |
|
||||
| protected | <strong>getNodeChildren(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Get all of the children of the provided element, with simplification.</em> |
|
||||
| protected | <strong>getNodeChildrenData(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Get the data from the children of the provided node in preliminary form.</em> |
|
||||
| protected | <strong>getUniformChildren(</strong><em>string</em> <strong>$parentKey</strong>, <em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Convert the children of the provided DOM element into an array. Here, 'uniform' means that all of the element names of the children are identical, and further, the element name of the parent is the plural form of the child names. When the children are uniform in this way, then the parent element name will be used as the key to store the children in, and the child list will be returned as a simple list with their (duplicate) element names omitted.</em> |
|
||||
| protected | <strong>getUniqueChildren(</strong><em>string</em> <strong>$parentKey</strong>, <em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>array</em><br /><em>Convert the children of the provided DOM element into an array. Here, 'unique' means that all of the element names of the children are different. Since the element names will become the key of the associative array that is returned, so duplicates are not supported. If there are any duplicates, then an exception will be thrown.</em> |
|
||||
| protected | <strong>hasUniformChildren(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$element</strong>)</strong> : <em>boolean</em><br /><em>Determine whether the children of the provided element are uniform.</em> |
|
||||
| protected | <strong>valueCanBeSimplified(</strong><em>[\DOMNode](http://php.net/manual/en/class.domnode.php)</em> <strong>$value</strong>)</strong> : <em>boolean</em><br /><em>Determine whether the provided value has additional unnecessary nesting. {"color": "red"} is converted to "red". No other simplification is done.</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Transformations\SimplifyToArrayInterface](#interface-consolidationoutputformatterstransformationssimplifytoarrayinterface)*
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\WordWrapper
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>mixed</em> <strong>$width</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>minimumWidth(</strong><em>mixed</em> <strong>$colkey</strong>, <em>mixed</em> <strong>$width</strong>)</strong> : <em>void</em><br /><em>Set the minimum width of just one column</em> |
|
||||
| public | <strong>setMinimumWidths(</strong><em>array</em> <strong>$minimumWidths</strong>)</strong> : <em>void</em><br /><em>If columns have minimum widths, then set them here.</em> |
|
||||
| public | <strong>setPaddingFromStyle(</strong><em>\Symfony\Component\Console\Helper\TableStyle</em> <strong>$style</strong>)</strong> : <em>void</em><br /><em>Calculate our padding widths from the specified table style.</em> |
|
||||
| public | <strong>wrap(</strong><em>array</em> <strong>$rows</strong>, <em>array</em> <strong>$widths=array()</strong>)</strong> : <em>array</em><br /><em>Wrap the cells in each part of the provided data table</em> |
|
||||
| protected | <strong>calculateWidths(</strong><em>mixed</em> <strong>$rows</strong>, <em>array</em> <strong>$widths=array()</strong>)</strong> : <em>void</em><br /><em>Determine what widths we'll use for wrapping.</em> |
|
||||
| protected | <strong>wrapCell(</strong><em>mixed</em> <strong>$cell</strong>, <em>string</em> <strong>$cellWidth</strong>)</strong> : <em>mixed</em><br /><em>Wrap one cell. Guard against modifying non-strings and then call through to wordwrap().</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Transformations\OverrideRestructureInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>overrideRestructure(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>mixed</em><br /><em>Select data to use directly from the structured output, before the restructure operation has been executed.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Transformations\SimplifyToArrayInterface
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>canSimplify(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$structuredOutput</strong>)</strong> : <em>bool</em><br /><em>Indicate whether or not the given data type can be simplified to an array</em> |
|
||||
| public | <strong>simplifyToArray(</strong><em>mixed</em> <strong>$structuredOutput</strong>, <em>[\Consolidation\OutputFormatters\Options\FormatterOptions](#class-consolidationoutputformattersoptionsformatteroptions)</em> <strong>$options</strong>)</strong> : <em>array</em><br /><em>Convert structured data into a generic array, usable by generic array-based formatters. Objects that implement this interface may be attached to the FormatterManager, and will be used on any data structure that needs to be simplified into an array. An array simplifier should take no action other than to return its input data if it cannot simplify the provided data into an array.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\Wrap\CalculateWidths
|
||||
|
||||
> Calculate column widths for table cells. Influenced by Drush and webmozart/console.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct()</strong> : <em>void</em> |
|
||||
| public | <strong>calculate(</strong><em>mixed</em> <strong>$availableWidth</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$dataWidths</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$minimumWidths</strong>)</strong> : <em>void</em><br /><em>Given the total amount of available space, and the width of the columns to place, calculate the optimum column widths to use.</em> |
|
||||
| public | <strong>calculateLongestCell(</strong><em>mixed</em> <strong>$rows</strong>)</strong> : <em>void</em><br /><em>Calculate the longest cell data from any row of each of the cells.</em> |
|
||||
| public | <strong>calculateLongestWord(</strong><em>mixed</em> <strong>$rows</strong>)</strong> : <em>void</em><br /><em>Calculate the longest word and longest line in the provided data.</em> |
|
||||
| public | <strong>distributeLongColumns(</strong><em>mixed</em> <strong>$availableWidth</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$dataWidths</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$minimumWidths</strong>)</strong> : <em>void</em><br /><em>Distribute the remainig space among the columns that were not included in the list of "short" columns.</em> |
|
||||
| public | <strong>getShortColumns(</strong><em>mixed</em> <strong>$availableWidth</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$dataWidths</strong>, <em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$minimumWidths</strong>)</strong> : <em>mixed</em><br /><em>Return all of the columns whose longest line length is less than or equal to the average width.</em> |
|
||||
| protected | <strong>calculateColumnWidths(</strong><em>mixed</em> <strong>$rows</strong>, <em>\callable</em> <strong>$fn</strong>)</strong> : <em>void</em> |
|
||||
| protected static | <strong>longestWordLength(</strong><em>string</em> <strong>$str</strong>)</strong> : <em>int</em><br /><em>Return the length of the longest word in the string.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths
|
||||
|
||||
> Calculate the width of data in table cells in preparation for word wrapping.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>__construct(</strong><em>array</em> <strong>$widths=array()</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>adjustMinimumWidths(</strong><em>mixed</em> <strong>$availableWidth</strong>, <em>mixed</em> <strong>$dataCellWidths</strong>)</strong> : <em>void</em><br /><em>If the widths specified by this object do not fit within the provided avaiable width, then reduce them all proportionally.</em> |
|
||||
| public | <strong>averageWidth(</strong><em>mixed</em> <strong>$availableWidth</strong>)</strong> : <em>void</em><br /><em>Calculate how much space is available on average for all columns.</em> |
|
||||
| public | <strong>combine(</strong><em>[\Consolidation\OutputFormatters\Transformations\Wrap\ColumnWidths](#class-consolidationoutputformatterstransformationswrapcolumnwidths)</em> <strong>$combineWith</strong>)</strong> : <em>void</em><br /><em>Combine this set of widths with another set, and return a new set that contains the entries from both.</em> |
|
||||
| public | <strong>count()</strong> : <em>void</em><br /><em>Return the number of columns.</em> |
|
||||
| public | <strong>distribute(</strong><em>mixed</em> <strong>$availableWidth</strong>)</strong> : <em>void</em><br /><em>Return proportional weights</em> |
|
||||
| public | <strong>enforceMinimums(</strong><em>mixed</em> <strong>$minimumWidths</strong>)</strong> : <em>void</em><br /><em>Ensure that every item in $widths that has a corresponding entry in $minimumWidths is as least as large as the minimum value held there.</em> |
|
||||
| public | <strong>findShortColumns(</strong><em>mixed</em> <strong>$thresholdWidth</strong>)</strong> : <em>mixed</em><br /><em>Find all of the columns that are shorter than the specified threshold.</em> |
|
||||
| public | <strong>findUndersizedColumns(</strong><em>mixed</em> <strong>$minimumWidths</strong>)</strong> : <em>mixed</em><br /><em>Find all of the columns that are shorter than the corresponding minimum widths.</em> |
|
||||
| public | <strong>isEmpty()</strong> : <em>bool</em><br /><em>Return true if there is no data in this object</em> |
|
||||
| public | <strong>keys()</strong> : <em>void</em><br /><em>Return the available keys (column identifiers) from the calculated data set.</em> |
|
||||
| public | <strong>lastColumn()</strong> : <em>void</em> |
|
||||
| public | <strong>paddingSpace(</strong><em>mixed</em> <strong>$paddingInEachCell</strong>, <em>mixed</em> <strong>$extraPaddingAtEndOfLine</strong>, <em>mixed</em> <strong>$extraPaddingAtBeginningOfLine</strong>)</strong> : <em>void</em> |
|
||||
| public | <strong>removeColumns(</strong><em>mixed</em> <strong>$columnKeys</strong>)</strong> : <em>void</em><br /><em>Remove all of the specified columns from this data structure.</em> |
|
||||
| public | <strong>selectColumns(</strong><em>mixed</em> <strong>$columnKeys</strong>)</strong> : <em>void</em><br /><em>Select all columns that exist in the provided list of keys.</em> |
|
||||
| public | <strong>setWidth(</strong><em>mixed</em> <strong>$key</strong>, <em>mixed</em> <strong>$width</strong>)</strong> : <em>void</em><br /><em>Set the length of the specified column.</em> |
|
||||
| public static | <strong>sumWidth(</strong><em>mixed</em> <strong>$widths</strong>)</strong> : <em>void</em><br /><em>Return the sum of the lengths of the provided widths.</em> |
|
||||
| public | <strong>totalWidth()</strong> : <em>void</em><br /><em>Return the sum of the lengths of the provided widths.</em> |
|
||||
| public | <strong>width(</strong><em>mixed</em> <strong>$key</strong>)</strong> : <em>void</em><br /><em>Return the length of the specified column.</em> |
|
||||
| public | <strong>widths()</strong> : <em>void</em><br /><em>Return all of the lengths</em> |
|
||||
| protected | <strong>findColumnsUnderThreshold(</strong><em>array</em> <strong>$thresholdWidths</strong>)</strong> : <em>mixed</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Validate\ValidationInterface
|
||||
|
||||
> Formatters may implement ValidationInterface in order to indicate whether a particular data structure is supported. Any formatter that does not implement ValidationInterface is assumed to only operate on arrays, or data types that implement SimplifyToArrayInterface.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>isValidDataType(</strong><em>[\ReflectionClass](http://php.net/manual/en/class.reflectionclass.php)</em> <strong>$dataType</strong>)</strong> : <em>bool</em><br /><em>Return true if the specified format is valid for use with this formatter.</em> |
|
||||
| public | <strong>validate(</strong><em>mixed</em> <strong>$structuredData</strong>)</strong> : <em>mixed</em><br /><em>Throw an IncompatibleDataException if the provided data cannot be processed by this formatter. Return the source data if it is valid. The data may be encapsulated or converted if necessary.</em> |
|
||||
|
||||
<hr />
|
||||
|
||||
### Interface: \Consolidation\OutputFormatters\Validate\ValidDataTypesInterface
|
||||
|
||||
> Formatters may implement ValidDataTypesInterface in order to indicate exactly which formats they support. The validDataTypes method can be called to retrieve a list of data types useful in providing hints in exception messages about which data types can be used with the formatter. Note that it is OPTIONAL for formatters to implement this interface. If a formatter implements only ValidationInterface, then clients that request the formatter via FormatterManager::write() will still get a list (via an InvalidFormatException) of all of the formats that are usable with the provided data type. Implementing ValidDataTypesInterface is benefitial to clients who instantiate a formatter directly (via `new`). Formatters that implement ValidDataTypesInterface may wish to use ValidDataTypesTrait.
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public | <strong>validDataTypes()</strong> : <em>[\ReflectionClass[]](http://php.net/manual/en/class.reflectionclass.php)</em><br /><em>Return the list of data types acceptable to this formatter</em> |
|
||||
|
||||
*This class implements [\Consolidation\OutputFormatters\Validate\ValidationInterface](#interface-consolidationoutputformattersvalidatevalidationinterface)*
|
||||
|
3
vendor/consolidation/output-formatters/docs/index.md
vendored
Normal file
3
vendor/consolidation/output-formatters/docs/index.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Consolidation Output Formatters
|
||||
|
||||
This is a placeholder for the output formatters documentation.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue