Add pear modules, mail and net_smtp via composer (#93)

Add pear modules, mail and net_smtp via composer, remove php 5.6 build due to phpunit 6
This commit is contained in:
Thilina Hasantha
2018-01-08 23:13:43 +01:00
committed by GitHub
parent 359e3f8382
commit e7792e7d79
2349 changed files with 117270 additions and 83170 deletions

View 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);
}
}

View File

@@ -19,12 +19,12 @@ class ExampleAnnotatedCommand extends AnnotatedCommand
/**
* Do the main function of the my:cat command.
*/
public function myCat($one, $two = '', $flip = false)
public function myCat($one, $two = '', $multiple = [], $flip = false)
{
if ($flip) {
return "{$two}{$one}";
return "{$two}{$one}" . implode('', array_reverse($multiple));
}
return "{$one}{$two}";
return "{$one}{$two}" . implode('', $multiple);
}
/**
@@ -37,6 +37,8 @@ class ExampleAnnotatedCommand extends AnnotatedCommand
* @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
@@ -46,9 +48,10 @@ class ExampleAnnotatedCommand extends AnnotatedCommand
{
$one = $input->getArgument('one');
$two = $input->getArgument('two');
$multiple = $input->getOption('multiple');
$flip = $input->getOption('flip');
$result = $this->myCat($one, $two, $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

View File

@@ -7,6 +7,7 @@ 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;
/**
@@ -32,6 +33,65 @@ class ExampleCommandFile
$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
*
@@ -46,7 +106,7 @@ class ExampleCommandFile
* Concatenate "alpha" and "bet".
* @arbitrary This annotation is here merely as a marker used in testing.
*/
public function myCat($one, $two = '', $options = ['flip' => false])
public function myCat($one, $two = '', array $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
@@ -57,15 +117,23 @@ class ExampleCommandFile
/**
* @command my:repeat
*/
public function myRepeat($one, $two = '', $options = ['repeat' => 1])
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, $options = ['flip' => false, 'repeat' => 1])
public function myJoin(array $args, array $options = ['flip' => false, 'repeat' => 1])
{
if ($options['flip']) {
$args = array_reverse($args);
@@ -90,6 +158,16 @@ class ExampleCommandFile
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
*
@@ -97,7 +175,7 @@ class ExampleCommandFile
*
* @option silent Supress output.
*/
public function commandWithNoArguments($opts = ['silent|s' => false])
public function commandWithNoArguments(array $opts = ['silent|s' => false])
{
if (!$opts['silent']) {
return "Hello, world";
@@ -112,7 +190,7 @@ class ExampleCommandFile
* @param $opts The options
* @option silent|s Supress output.
*/
public function shortcutOnAnnotation($opts = ['silent' => false])
public function shortcutOnAnnotation(array $opts = ['silent' => false])
{
if (!$opts['silent']) {
return "Hello, world";
@@ -133,8 +211,10 @@ class ExampleCommandFile
* @usage 2 2 --negate
* Add two plus two and then negate.
* @custom
* @dup one
* @dup two
*/
public function testArithmatic($one, $two, $options = ['negate' => false])
public function testArithmatic($one, $two = 2, array $options = ['negate' => false, 'unused' => 'bob'])
{
$result = $one + $two;
if ($options['negate']) {
@@ -246,6 +326,22 @@ class ExampleCommandFile
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
*/
@@ -348,4 +444,78 @@ class ExampleCommandFile
}
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";
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -7,6 +7,11 @@ 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.
@@ -15,8 +20,10 @@ use Consolidation\AnnotatedCommand\CommandData;
* 'src' directory, and 'alpha' is one of the search directories available
* for searching.
*/
class AlphaCommandFile
class AlphaCommandFile implements CustomEventAwareInterface
{
use CustomEventAwareTrait;
/**
* @command always:fail
*/
@@ -25,6 +32,11 @@ class AlphaCommandFile
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
*/
@@ -72,17 +84,52 @@ class AlphaCommandFile
* Test command with formatters
*
* @command example:table
* @param $unused An unused argument
* @field-labels
* first: I
* second: II
* third: III
* @usage example:table --format=yaml
* @usage example:table --format=csv
* @usage example:table --format=yml
* Show the example table in yml format.
* @usage example:table --fields=first,third
* @usage example:table --fields=III,II
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
* 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($options = ['format' => 'table', 'fields' => ''])
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' ],
@@ -117,7 +164,7 @@ class AlphaCommandFile
/**
* @hook option example:table
*/
public function additionalOptionForExampleTable($command, $annotationData)
public function additionalOptionForExampleTable(Command $command, AnnotationData $annotationData)
{
$command->addOption(
'dynamic',
@@ -240,4 +287,39 @@ class AlphaCommandFile
{
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';
}
}

View File

@@ -20,10 +20,10 @@ class AnnotatedCommandTests extends \PHPUnit_Framework_TestCase
$this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp());
$this->assertEquals('c', implode(',', $command->getAliases()));
// Symfony Console composes the synopsis; perhaps we should not test it. Remove if this gives false failures.
$this->assertEquals('my:cat [--flip] [--] <one> [<two>]', $command->getSynopsis());
$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 bet alpha --flip');
$input = new StringInput('my:cat b alpha --multiple=t --multiple=e --flip');
$this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet');
}

View File

@@ -10,6 +10,7 @@ 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;
@@ -19,6 +20,207 @@ 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.
*/
@@ -35,7 +237,7 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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] [--] <one> <two>', $command->getSynopsis());
$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');
@@ -86,6 +288,29 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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;
@@ -126,6 +351,34 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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()
@@ -237,6 +490,41 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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();
@@ -264,6 +552,33 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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()
@@ -338,6 +653,22 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$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();
@@ -404,7 +735,7 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$annotationData = $commandInfo->getRawAnnotations();
$this->assertEquals('addmycommandname', implode(',', $annotationData->keys()));
$annotationData = $commandInfo->getAnnotations();
$this->assertEquals('addmycommandname,command', implode(',', $annotationData->keys()));
$this->assertEquals('addmycommandname,command,_path,_classname', implode(',', $annotationData->keys()));
$command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance);
@@ -415,7 +746,6 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$this->assertRunCommandViaApplicationEquals($command, $input, 'fantabulous from alter:me-too');
}
function testHookedCommandWithHookAddedLater()
{
$this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile();
@@ -612,7 +942,25 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
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')) {
@@ -624,16 +972,15 @@ class AnnotatedCommandFactoryTests extends \PHPUnit_Framework_TestCase
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
$eventDispatcher->addSubscriber($alterOptionsEventManager);
$this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager);
$application->setDispatcher($eventDispatcher);
$application->setAutoExit(false);
$application->add($command);
$statusCode = $application->run($input, $output);
$commandOutput = trim($output->fetch());
$commandOutput = trim(str_replace("\r", '', $output->fetch()));
$this->assertEquals($expectedOutput, $commandOutput);
$this->assertEquals($expectedStatusCode, $statusCode);
return [$statusCode, $commandOutput];
}
}

View File

@@ -2,6 +2,8 @@
namespace Consolidation\AnnotatedCommand;
use Consolidation\AnnotatedCommand\Parser\CommandInfo;
use Consolidation\AnnotatedCommand\Parser\CommandInfoSerializer;
use Consolidation\AnnotatedCommand\Parser\CommandInfoDeserializer;
class CommandInfoTests extends \PHPUnit_Framework_TestCase
{
@@ -22,8 +24,31 @@ class CommandInfoTests extends \PHPUnit_Framework_TestCase
*/
function testParsing()
{
$commandInfo = new CommandInfo('\Consolidation\TestUtils\ExampleCommandFile', 'testArithmatic');
$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',
@@ -46,15 +71,31 @@ class CommandInfoTests extends \PHPUnit_Framework_TestCase
'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 = new CommandInfo('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$this->assertEquals('example:table', $commandInfo->getName());
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
}

View File

@@ -13,6 +13,7 @@ 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;
@@ -21,6 +22,8 @@ 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.
@@ -36,7 +39,7 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
$alterOptionsEventManager = new AlterOptionsCommandEvent($this->application);
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager());
$eventDispatcher->addSubscriber($alterOptionsEventManager);
$this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager);
$this->application->setDispatcher($eventDispatcher);
$this->application->setAutoExit(false);
}
@@ -46,7 +49,7 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
$formatter = new FormatterManager();
$formatter->addDefaultFormatters();
$formatter->addDefaultSimplifiers();
$commandInfo = new CommandInfo('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable');
$this->assertEquals('example:table', $commandInfo->getName());
$this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType());
}
@@ -59,7 +62,13 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
$formatter->addDefaultSimplifiers();
$this->commandFactory->commandProcessor()->setFormatterManager($formatter);
$commandInfo = $this->commandFactory->createCommandInfo($commandFileInstance, 'exampleTable');
$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);
@@ -69,7 +78,7 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
'--format[=FORMAT] Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml [default: "table"]',
'--fields[=FIELDS] Available fields: I (first), II (second), III (third) [default: ""]',
];
$this->assertRunCommandViaApplicationContains('help example:table', $containsList);
$this->assertRunCommandViaApplicationContains('help ' . $commandName, $containsList);
}
function testCommandsAndHooks()
@@ -92,18 +101,24 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
$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. The command factory class is
// tested in isolation in testAnnotatedCommandFactory.php,
// but this is the only place where
// discovered above.
$factory = new AnnotatedCommandFactory();
$factory->setCommandProcessor($commandProcessor);
// $factory->addListener(...);
// 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);
@@ -112,6 +127,12 @@ class FullStackTests extends \PHPUnit_Framework_TestCase
$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();
@@ -238,20 +259,21 @@ EOT;
$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 of table. It is also
data. When it is very long, and
rendered, it should be wrapped
should be wrapped across multiple
across multiple lines, just like
lines. the first column.
------------------- --------------------
------------------ --------------------
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);
}
@@ -333,7 +355,7 @@ EOT;
$allRegisteredHooks = $hookManager->getAllHooks();
$registeredHookNames = array_keys($allRegisteredHooks);
sort($registeredHookNames);
$this->assertEquals('*,example:table', implode(',', $registeredHookNames));
$this->assertEquals('*,example:table,my-event', implode(',', $registeredHookNames));
$allHooksForExampleTable = $allRegisteredHooks['example:table'];
$allHookPhasesForExampleTable = array_keys($allHooksForExampleTable);
sort($allHookPhasesForExampleTable);
@@ -443,7 +465,7 @@ EOT;
function simplifyWhitespace($data)
{
return trim(preg_replace('#[ \t]+$#m', '', $data));
return trim(preg_replace('#\s+$#m', '', $data));
}
function callProtected($object, $method, $args = [])

View 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] [--] [&lt;unused&gt;]</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);
}
}