This commit is contained in:
2022-10-23 01:39:27 +02:00
parent 8c17aab483
commit 1929b84685
4130 changed files with 479334 additions and 0 deletions

3
vendor/corneltek/getoptionkit/.gitignore vendored Executable file
View File

@@ -0,0 +1,3 @@
/build
/vendor
*.tgz

29
vendor/corneltek/getoptionkit/.travis.yml vendored Executable file
View File

@@ -0,0 +1,29 @@
language: php
php:
- 5.6
- 7.0
- 7.1
- hhvm
install:
- phpenv rehash
- composer require "satooshi/php-coveralls" "^1" --dev --no-update
- composer install --no-interaction
script:
- phpunit -c phpunit.xml.dist
after_success:
- php vendor/bin/coveralls -v
matrix:
fast_finish: true
allow_failures:
- php: hhvm
- php: '5.6'
cache:
apt: true
directories:
- vendor
notifications:
email:
on_success: change
on_failure: change
slack:
secure: dKH3qw9myjwDO+OIz6qBqn5vJJqoFyD2frS4eH68jI5gtxHX2PJVwaP9waXTSu+FFq9wILsHGQezrawWHcMkbEo4gxbri2Ne7gFT4CJD0DAOyf02JgQ1A/cJaqQ5XrLO9CwjP0/8PKaMCHiND4SLEWgmtlFRoB7gr33QjbQjBvc=

56
vendor/corneltek/getoptionkit/CHANGELOG.md vendored Executable file
View File

@@ -0,0 +1,56 @@
CHANGELOG
==================
## v2.3.0 - Thu May 12 10:29:19 2016
- Fixed bugs for multiple value parsing with arguments.
- OptionParser::parse(argv) now expects the first argument to be the program name,
so you can pass argv directly to the parser.
## v2.2.5-6 - Wed May 11 2016
- Fixed bugs for ContinuousOptionParser.
## v2.2.4 - Fri Oct 2 15:53:33 2015
- ContinuousOptionParser improvements.
## v2.2.2 - Tue Jul 14 00:15:26 2015
- Added PathType.
## v2.2.1 - Tue Jul 14 00:17:19 2015
Merged PRs:
- Commit 7bbb91b: Merge pull request #34 from 1Franck/master
added value type option(s) support, added class RegexType
- Commit 3722992: Merge pull request #33 from 1Franck/patch-1
Clarified InvalidOptionValue exception message
## v2.2.0 - Thu Jun 4 13:51:47 2015
- Added more types for type constraint option. url, ip, ipv4, ipv6, email by @1Franck++
- Several bug fixes by @1Franck++
## v2.1.0 - Fri Apr 24 16:43:00 2015
- Added incremental option value support.
- Fixed #21 for negative value.
- Used autoloading with PSR-4
## v2.0.12 - Tue Apr 21 18:51:12 2015
- Improved hinting text for default value
- Some coding style fix
- Added default value support
- Updated default value support for ContinuousOptionParser
- Added getValue() accessor on OptionSpec class
- Merged pull request #22 from Gasol/zero-option. @Gasol++
- Fix option that can't not be 0

View File

@@ -0,0 +1,11 @@
Bitdeli Chef <chef@bitdeli.com>
Dlussky Kirill <kirill@dlussky.ru>
Francois Lajoie <snake386@hotmail.com>
Gasol Wu <gasol.wu@gmail.com>
Igor Santos <igorsantos07@gmail.com>
Jevon Wright <jevon@jevon.org>
MartyIX <vseticka.martin@gmail.com>
Michał Kniotek <michal.kniotek@uj.edu.pl>
Robbert Klarenbeek <robbertkl@renbeek.nl>
Yo-An Lin <cornelius.howl@gmail.com>
Yo-An Lin <yoanlin93@gmail.com>

19
vendor/corneltek/getoptionkit/LICENSE vendored Executable file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2013 Yo-An Lin <yoan.lin@gmail.com>
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.

370
vendor/corneltek/getoptionkit/README.md vendored Executable file
View File

@@ -0,0 +1,370 @@
GetOptionKit
============
Code Quality
[![Build Status](https://travis-ci.org/c9s/GetOptionKit.svg?branch=master)](https://travis-ci.org/c9s/GetOptionKit)
[![Coverage Status](https://coveralls.io/repos/github/c9s/GetOptionKit/badge.svg?branch=master)](https://coveralls.io/github/c9s/GetOptionKit?branch=master)
Versions & Stats
[![Latest Stable Version](https://poser.pugx.org/corneltek/getoptionkit/v/stable)](https://packagist.org/packages/corneltek/getoptionkit)
[![Latest Unstable Version](https://poser.pugx.org/corneltek/getoptionkit/v/unstable)](https://packagist.org/packages/corneltek/getoptionkit)
[![Total Downloads](https://poser.pugx.org/corneltek/getoptionkit/downloads)](https://packagist.org/packages/corneltek/getoptionkit)
[![Monthly Downloads](https://poser.pugx.org/corneltek/getoptionkit/d/monthly)](https://packagist.org/packages/corneltek/getoptionkit)
[![Daily Downloads](https://poser.pugx.org/corneltek/getoptionkit/d/daily)](https://packagist.org/packages/corneltek/getoptionkit)
[![License](https://poser.pugx.org/corneltek/getoptionkit/license)](https://packagist.org/packages/corneltek/getoptionkit)
A powerful option parser toolkit for PHP, supporting type constraints,
flag, multiple flag, multiple values and required value checking.
GetOptionKit supports PHP5.3, with fine unit testing with PHPUnit testing
framework.
GetOptionKit is object-oriented, it's flexible and extendable.
Powering PHPBrew <https://github.com/phpbrew/phpbrew>, CLIFramework <https://github.com/c9s/CLIFramework> and AssetKit <https://github.com/c9s/AssetKit>
## Features
- Simple format.
- Type constrant.
- Multiple value, requried value, optional value checking.
- Auto-generated help text from defined options.
- Support app/subcommand option parsing.
- Option Value Validator
- Option Suggestions
- SPL library.
- HHVM support.
## Requirements
* PHP 5.3+
## Install From Composer
```sh
composer require corneltek/getoptionkit
```
## Supported Option Formats
simple flags:
```sh
program.php -a -b -c
program.php -abc
program.php -vvv # incremental flag v=3
program.php -a -bc
```
with multiple values:
```sh
program.php -a foo -a bar -a zoo -b -b -b
```
specify value with equal sign:
```sh
program.php -a=foo
program.php --long=foo
```
with normal arguments:
```
program.php -a=foo -b=bar arg1 arg2 arg3
program.php arg1 arg2 arg3 -a=foo -b=bar
```
## Option SPEC
v|verbose flag option (with boolean value true)
d|dir: option require a value (MUST require)
d|dir+ option with multiple values.
d|dir? option with optional value
dir:=string option with type constraint of string
dir:=number option with type constraint of number
dir:=file option with type constraint of file
dir:=date option with type constraint of date
dir:=boolean option with type constraint of boolean
d single character only option
dir long option name
## Command Line Forms
app [app-opts] [app arguments]
app [app-opts] subcommand [subcommand-opts] [subcommand-args]
app [app-opts] subcmd1 [subcmd-opts1] subcmd2 [subcmd-opts] subcmd3 [subcmd-opts3] [subcommand arguments....]
## Documentation
See more details in the [documentation](https://github.com/c9s/GetOptionKit/wiki)
## Demo
Please check `examples/demo.php`.
Run:
```sh
% php examples/demo.php -f test -b 123 -b 333
```
Print:
* Available options:
-f, --foo <value> option requires a value.
-b, --bar <value>+ option with multiple value.
-z, --zoo [<value>] option with optional value.
-v, --verbose verbose message.
-d, --debug debug message.
--long long option name only.
-s short option name only.
Enabled options:
* key:foo spec:-f, --foo <value> desc:option requires a value.
value => test
* key:bar spec:-b, --bar <value>+ desc:option with multiple value.
Array
(
[0] => 123
[1] => 333
)
## Synopsis
```php
use GetOptionKit\OptionCollection;
use GetOptionKit\OptionParser;
use GetOptionKit\OptionPrinter\ConsoleOptionPrinter;
$specs = new OptionCollection;
$specs->add('f|foo:', 'option requires a value.' )
->isa('String');
$specs->add('b|bar+', 'option with multiple value.' )
->isa('Number');
$specs->add('ip+', 'Ip constraint' )
->isa('Ip');
$specs->add('email+', 'Email address constraint' )
->isa('Email');
$specs->add('z|zoo?', 'option with optional value.' )
->isa('Boolean');
$specs->add('file:', 'option value should be a file.' )
->isa('File');
$specs->add('v|verbose', 'verbose message.' );
$specs->add('d|debug', 'debug message.' );
$specs->add('long', 'long option name only.' );
$specs->add('s', 'short option name only.' );
$printer = new ConsoleOptionPrinter();
echo $printer->render($specs);
$parser = new OptionParser($specs);
echo "Enabled options: \n";
try {
$result = $parser->parse( $argv );
foreach ($result->keys as $key => $spec) {
print_r($spec);
}
$opt = $result->keys['foo']; // return the option object.
$str = $result->keys['foo']->value; // return the option value
print_r($opt);
var_dump($str);
} catch( Exception $e ) {
echo $e->getMessage();
}
```
## Documentation
See <https://github.com/c9s/GetOptionKit/wiki> for more details.
### Option Value Type
The option value type help you validate the input,
the following list is the current supported types:
- `string`
- `number`
- `boolean`
- `file`
- `date`
- `url`
- `email`
- `ip`
- `ipv4`
- `ipv6`
- `regex`
And here is the related sample code:
```php
$opt->add( 'f|foo:' , 'with string type value' )
->isa('string');
$opt->add( 'b|bar+' , 'with number type value' )
->isa('number');
$opt->add( 'z|zoo?' , 'with boolean type value' )
->isa('boolean');
$opt->add( 'file:' , 'with file type value' )
->isa('file');
$opt->add( 'date:' , 'with date type value' )
->isa('date');
$opt->add( 'url:' , 'with url type value' )
->isa('url');
$opt->add( 'email:' , 'with email type value' )
->isa('email');
$opt->add( 'ip:' , 'with ip(v4/v6) type value' )
->isa('ip');
$opt->add( 'ipv4:' , 'with ipv4 type value' )
->isa('ipv4');
$opt->add( 'ipv6:' , 'with ipv6 type value' )
->isa('ipv6');
$specs->add('r|regex:', 'with custom regex type value')
->isa('Regex', '/^([a-z]+)$/');
```
> Please note that currently only `string`, `number`, `boolean` types can be validated.
### ContinuousOptionParser
```php
$specs = new OptionCollection;
$spec_verbose = $specs->add('v|verbose');
$spec_color = $specs->add('c|color');
$spec_debug = $specs->add('d|debug');
$spec_verbose->description = 'verbose flag';
// ContinuousOptionParser
$parser = new ContinuousOptionParser( $specs );
$result = $parser->parse(explode(' ','program -v -d test -a -b -c subcommand -e -f -g subcommand2'));
$result2 = $parser->continueParse();
```
### OptionPrinter
GetOptionKit\OptionPrinter can print options for you:
* Available options:
-f, --foo option requires a value.
-b, --bar option with multiple value.
-z, --zoo option with optional value.
-v, --verbose verbose message.
-d, --debug debug message.
--long long option name only.
-s short option name only.
## Command-line app with subcommands
For application with subcommands is designed by following form:
[app name] [app opts]
[subcommand1] [subcommand-opts]
[subcommand2] [subcommand-opts]
[subcommand3] [subcommand-opts]
[arguments]
You can check the `tests/GetOptionKit/ContinuousOptionParserTest.php` unit test file:
```php
// subcommand stack
$subcommands = array('subcommand1','subcommand2','subcommand3');
// different command has its own options
$subcommandSpecs = array(
'subcommand1' => $cmdspecs,
'subcommand2' => $cmdspecs,
'subcommand3' => $cmdspecs,
);
// for saved options
$subcommandOptions = array();
// command arguments
$arguments = array();
$argv = explode(' ','program -v -d -c subcommand1 -a -b -c subcommand2 -c subcommand3 arg1 arg2 arg3');
// parse application options first
$parser = new ContinuousOptionParser( $appspecs );
$app_options = $parser->parse( $argv );
while (! $parser->isEnd()) {
if (@$subcommands[0] && $parser->getCurrentArgument() == $subcommands[0]) {
$parser->advance();
$subcommand = array_shift( $subcommands );
$parser->setSpecs( $subcommandSpecs[$subcommand] );
$subcommandOptions[ $subcommand ] = $parser->continueParse();
} else {
$arguments[] = $parser->advance();
}
}
```
## Todo
* Option Spec group.
* option valid value checking.
* custom command mapping.
## Command Line Utility Design Concept
* main program name should be easy to type, easy to remember.
* subcommand should be easy to type, easy to remember. length should be shorter than 7 characters.
* options should always have long descriptive name
* a program should be easy to check usage.
## General command interface
To list usage of all subcommands or the program itself:
$ prog help
To list the subcommand usage
$ prog help subcommand subcommand2 subcommand3
## Hacking
Fork this repository and clone it:
$ git clone git://github.com/c9s/GetOptionKit.git
$ cd GetOptionKit
$ composer install
Run PHPUnit to test:
$ phpunit
## License
This project is released under MIT License.

185
vendor/corneltek/getoptionkit/build.xml vendored Executable file
View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="GetOptionKit" default="build">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<target name="build"
depends="prepare,bundle,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpdox,phpunit,phpcb,package"/>
<target name="build-parallel"
depends="prepare,lint,tools-parallel,phpunit,phpcb"/>
<target name="tools-parallel" description="Run tools in parallel">
<parallel threadCount="2">
<sequential>
<antcall target="pdepend"/>
<antcall target="phpmd-ci"/>
</sequential>
<antcall target="phpcpd"/>
<antcall target="phpcs-ci"/>
<antcall target="phploc"/>
<antcall target="phpdox"/>
</parallel>
</target>
<target name="clean" description="Cleanup build artifacts">
<delete dir="${basedir}/build/api"/>
<delete dir="${basedir}/build/code-browser"/>
<delete dir="${basedir}/build/coverage"/>
<delete dir="${basedir}/build/logs"/>
<delete dir="${basedir}/build/pdepend"/>
</target>
<target name="prepare" depends="clean" description="Prepare for build">
<mkdir dir="${basedir}/build/api"/>
<mkdir dir="${basedir}/build/code-browser"/>
<mkdir dir="${basedir}/build/coverage"/>
<mkdir dir="${basedir}/build/logs"/>
<mkdir dir="${basedir}/build/pdepend"/>
<mkdir dir="${basedir}/build/phpdox"/>
</target>
<target name="lint" description="Perform syntax check of sourcecode files">
<apply executable="php" failonerror="true">
<arg value="-l" />
<fileset dir="${basedir}/src">
<include name="**/*.php" />
<modified />
</fileset>
<fileset dir="${basedir}/tests">
<include name="**/*.php" />
<modified />
</fileset>
</apply>
</target>
<target name="phploc" description="Measure project size using PHPLOC">
<exec executable="phploc">
<arg value="--log-csv" />
<arg value="${basedir}/build/logs/phploc.csv" />
<arg path="${basedir}/src" />
</exec>
</target>
<target name="pdepend" description="Calculate software metrics using PHP_Depend">
<exec executable="pdepend">
<arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
<arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
<arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
<arg path="${basedir}/src" />
</exec>
</target>
<target name="phpmd"
description="Perform project mess detection using PHPMD and print human readable output. Intended for usage on the command line before committing.">
<exec executable="phpmd">
<arg path="${basedir}/src" />
<arg value="text" />
<arg value="${basedir}/build/phpmd.xml" />
</exec>
</target>
<target name="phpmd-ci" description="Perform project mess detection using PHPMD creating a log file for the continuous integration server">
<exec executable="phpmd">
<arg path="${basedir}/src" />
<arg value="xml" />
<arg value="${basedir}/build/phpmd.xml" />
<arg value="--reportfile" />
<arg value="${basedir}/build/logs/pmd.xml" />
</exec>
</target>
<target name="phpcs"
description="Find coding standard violations using PHP_CodeSniffer and print human readable output. Intended for usage on the command line before committing.">
<exec executable="phpcs">
<arg value="--standard=${basedir}/build/phpcs.xml" />
<arg path="${basedir}/src" />
</exec>
</target>
<target name="phpcs-ci" description="Find coding standard violations using PHP_CodeSniffer creating a log file for the continuous integration server">
<exec executable="phpcs" output="/dev/null">
<arg value="--report=checkstyle" />
<arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
<arg value="--standard=${basedir}/build/phpcs.xml" />
<arg path="${basedir}/src" />
</exec>
</target>
<target name="phpcpd" description="Find duplicate code using PHPCPD">
<exec executable="phpcpd">
<arg value="--log-pmd" />
<arg value="${basedir}/build/logs/pmd-cpd.xml" />
<arg path="${basedir}/src" />
</exec>
</target>
<target name="phpdox" description="Generate API documentation using phpDox">
<exec executable="phpdox"/>
</target>
<target name="bundle">
<if>
<available file="package.ini"/>
<then>
<exec executable="onion" failonerror="true">
<arg value="-d"/>
<arg value="bundle"/>
</exec>
</then>
</if>
</target>
<target name="package">
<if>
<available file="scripts/compile.sh"/>
<then>
<exec executable="bash" failonerror="true">
<arg value="scripts/compile.sh"/>
</exec>
</then>
</if>
<if>
<available file="package.ini"/>
<then>
<exec executable="onion" failonerror="true">
<arg value="-d"/>
<arg value="build"/>
</exec>
</then>
</if>
</target>
<!-- may we have a simple condition for phpunit.xml and phpunit-ci.xml ? -->
<target name="phpunit" description="Run unit tests with PHPUnit">
<if>
<available file="phpunit-ci.xml"/>
<then>
<exec executable="phpunit" failonerror="true">
<arg value="--configuration"/>
<arg value="${basedir}/phpunit-ci.xml"/>
</exec>
</then>
<else>
<exec executable="phpunit" failonerror="true"/>
</else>
</if>
</target>
<target name="phpcb" description="Aggregate tool output with PHP_CodeBrowser">
<exec executable="phpcb">
<arg value="--log" />
<arg path="${basedir}/build/logs" />
<arg value="--source" />
<arg path="${basedir}/src" />
<arg value="--output" />
<arg path="${basedir}/build/code-browser" />
</exec>
</target>
</project>

16
vendor/corneltek/getoptionkit/composer.json vendored Executable file
View File

@@ -0,0 +1,16 @@
{
"name": "corneltek/getoptionkit",
"homepage": "http://github.com/c9s/GetOptionKit",
"description": "Powerful command-line option toolkit",
"require": {
"php": ">=5.3.0"
},
"license": "MIT",
"authors": [ { "name": "Yo-An Lin", "email": "yoanlin93@gmail.com" } ],
"autoload": {
"psr-4": {
"GetOptionKit\\": "src/"
}
},
"extra": { "branch-alias": { "dev-master": "2.6.x-dev" } }
}

19
vendor/corneltek/getoptionkit/composer.lock generated vendored Executable file
View File

@@ -0,0 +1,19 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "5a9b6e9fccaf89d121650d35313e842b",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.0"
},
"platform-dev": []
}

View File

@@ -0,0 +1,76 @@
#!/usr/bin/env php
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
require 'vendor/autoload.php';
use GetOptionKit\OptionCollection;
use GetOptionKit\OptionParser;
use GetOptionKit\OptionPrinter\ConsoleOptionPrinter;
$specs = new OptionCollection;
$specs->add('f|foo:', 'option requires a value.' )
->isa('String');
$specs->add('b|bar+', 'option with multiple value.' )
->isa('Number');
$specs->add('z|zoo?', 'option with optional value.' )
->isa('Boolean')
;
$specs->add('o|output?', 'option with optional value.' )
->isa('File')
->defaultValue('output.txt')
;
// works for -vvv => verbose = 3
$specs->add('v|verbose', 'verbose')
->isa('Number')
->incremental();
$specs->add('file:', 'option value should be a file.' )
->trigger(function($value) {
echo "Set value to :";
var_dump($value);
})
->isa('File');
$specs->add('r|regex:', 'with custom regex type value')
->isa('Regex', '/^([a-z]+)$/');
$specs->add('d|debug', 'debug message.' );
$specs->add('long', 'long option name only.' );
$specs->add('s', 'short option name only.' );
$specs->add('m', 'short option m');
$specs->add('4', 'short option with digit');
$printer = new ConsoleOptionPrinter;
echo $printer->render($specs);
$parser = new OptionParser($specs);
echo "Enabled options: \n";
try {
$result = $parser->parse( $argv );
foreach ($result->keys as $key => $spec) {
print_r($spec);
}
$opt = $result->keys['foo']; // return the option object.
$str = $result->keys['foo']->value; // return the option value
print_r($opt);
var_dump($str);
} catch( Exception $e ) {
echo $e->getMessage();
}

15
vendor/corneltek/getoptionkit/package.ini vendored Executable file
View File

@@ -0,0 +1,15 @@
[package]
name = GetOptionKit
version = 1.2.2
desc = "A powerful GetOpt toolkit for PHP, which supports type constraints, flag,
multiple flag, multiple values, required value checking."
author = "Yo-An Lin (c9s) <cornelius.howl@gmail.com>"
channel = pear.corneltek.com
stability = stable
[require]
php = 5.3
pearinstaller = 1.4.1
pear.corneltek.com/Universal =
pear.corneltek.com/PHPUnit_TestMore =

16
vendor/corneltek/getoptionkit/phpdox.xml vendored Executable file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<phpdox xmlns="http://phpdox.de/config" silent="false">
<project name="GetOptionKit" source="src" workdir="build/phpdox">
<collector publiconly="false">
<include mask="*.php" />
<exclude mask="*Autoload.php" />
</collector>
<generator output="build">
<build engine="html" enabled="true" output="api"/>
<build engine="graph" enabled="true" output="graph">
<dot executable="/usr/bin/dot" render="true" format="png" />
</build>
</generator>
</project>
</phpdox>

View File

@@ -0,0 +1,2 @@
Steps = PHPUnit, BumpVersion, GitCommit, GitTag, GitPush, GitPushTags
; VersionFrom = src/PHPRelease/Console.php

29
vendor/corneltek/getoptionkit/phpunit-ci.xml vendored Executable file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
verbose="true">
<php>
<!-- Unit Testing Variables -->
<!--
<var name="VAR" value="Values" />
-->
</php>
<testsuites>
<testsuite name="PHPUnit">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-html" target="build/coverage" title="GetOptionKit"
charset="UTF-8" yui="true" highlight="true"
lowUpperBound="35" highLowerBound="70"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="junit" target="build/logs/junit.xml"
logIncompleteSkipped="false"/>
</logging>
</phpunit>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
verbose="true">
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="PHPUnit">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
<log type="coverage-html" target="build/coverage" title="PHP Coveralls" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
</logging>
</phpunit>

119
vendor/corneltek/getoptionkit/src/Argument.php vendored Executable file
View File

@@ -0,0 +1,119 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
class Argument
{
public $arg;
public function __construct($arg)
{
$this->arg = $arg;
}
public function isLongOption()
{
return substr($this->arg, 0, 2) === '--';
}
public function isShortOption()
{
return (substr($this->arg, 0, 1) === '-')
&& (substr($this->arg, 1, 1) !== '-');
}
public function isEmpty()
{
return $this->arg === null || empty($this->arg) && ('0' !== $this->arg);
}
/**
* Check if an option is one of the option in the collection.
*/
public function anyOfOptions(OptionCollection $options)
{
$name = $this->getOptionName();
$keys = $options->keys();
return in_array($name, $keys);
}
/**
* Check current argument is an option by the preceding dash.
* note this method does not work for string with negative value.
*
* -a
* --foo
*/
public function isOption()
{
return $this->isShortOption() || $this->isLongOption();
}
/**
* Parse option and return the name after dash. e.g.,
* '--foo' returns 'foo'
* '-f' returns 'f'.
*
* @return string
*/
public function getOptionName()
{
if (preg_match('/^[-]+([a-zA-Z0-9-]+)/', $this->arg, $regs)) {
return $regs[1];
}
}
public function splitAsOption()
{
return explode('=', $this->arg, 2);
}
public function containsOptionValue()
{
return preg_match('/=.+/', $this->arg);
}
public function getOptionValue()
{
if (preg_match('/=(.+)/', $this->arg, $regs)) {
return $regs[1];
}
return;
}
/**
* Check combined short flags for "-abc" or "-vvv".
*
* like: -abc
*/
public function withExtraFlagOptions()
{
return preg_match('/^-[a-zA-Z0-9]{2,}/', $this->arg);
}
public function extractExtraFlagOptions()
{
$args = array();
for ($i = 2;$i < strlen($this->arg); ++$i) {
$args[] = '-'.$this->arg[$i];
}
$this->arg = substr($this->arg, 0, 2); # -[a-z]
return $args;
}
public function __toString()
{
return $this->arg;
}
}

View File

@@ -0,0 +1,201 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
use Exception;
use LogicException;
use GetOptionKit\Exception\InvalidOptionException;
use GetOptionKit\Exception\RequireValueException;
/**
* A common command line argument format:.
*
* app.php
* [--app-options]
*
* [subcommand
* --subcommand-options]
* [subcommand
* --subcommand-options]
* [subcommand
* --subcommand-options]
*
* [arguments]
*
* ContinuousOptionParser is for the process flow:
*
* init app options,
* parse app options
*
*
*
* while not end
* if stop at command
* shift command
* parse command options
* else if stop at arguments
* shift arguments
* execute current command with the arguments.
*
* Example code:
*
*
* // subcommand stack
* $subcommands = array('subcommand1','subcommand2','subcommand3');
*
* // different command has its own options
* $subcommand_specs = array(
* 'subcommand1' => $cmdspecs,
* 'subcommand2' => $cmdspecs,
* 'subcommand3' => $cmdspecs,
* );
*
* // for saved options
* $subcommand_options = array();
*
* // command arguments
* $arguments = array();
*
* $argv = explode(' ','-v -d -c subcommand1 -a -b -c subcommand2 -c subcommand3 arg1 arg2 arg3');
*
* // parse application options first
* $parser = new ContinuousOptionParser( $appspecs );
* $app_options = $parser->parse( $argv );
* while (! $parser->isEnd()) {
* if( $parser->getCurrentArgument() == $subcommands[0] ) {
* $parser->advance();
* $subcommand = array_shift( $subcommands );
* $parser->setSpecs( $subcommand_specs[$subcommand] );
* $subcommand_options[ $subcommand ] = $parser->continueParse();
* } else {
* $arguments[] = $parser->advance();
* }
* }
**/
class ContinuousOptionParser extends OptionParser
{
public $index;
public $length;
public $argv;
/* for the constructor , the option specs is application options */
public function __construct(OptionCollection $specs)
{
parent::__construct($specs);
$this->index = 1;
}
/**
* @codeCoverageIgnore
*/
public function startFrom($index)
{
$this->index = $index;
}
public function isEnd()
{
# echo "!! {$this->index} >= {$this->length}\n";
return $this->index >= $this->length;
}
/**
* Return the current argument and advance to the next position.
*
* @return string
*/
public function advance()
{
if ($this->index >= $this->length) {
throw new LogicException("Argument index out of bounds.");
}
return $this->argv[$this->index++];
}
/**
* Return the current argument that the index pointed to.
*
* @return string
*/
public function getCurrentArgument()
{
return $this->argv[$this->index];
}
public function continueParse()
{
return $this->parse($this->argv);
}
protected function fillDefaultValues(OptionCollection $opts, OptionResult $result)
{
// register option result from options with default value
foreach ($opts as $opt) {
if ($opt->value === null && $opt->defaultValue !== null) {
$opt->setValue($opt->getDefaultValue());
$result->set($opt->getId(), $opt);
}
}
}
public function parse(array $argv)
{
// create new Result object.
$result = new OptionResult();
list($this->argv, $extra) = $this->preprocessingArguments($argv);
$this->length = count($this->argv);
// from last parse index
for (; $this->index < $this->length; ++$this->index) {
$arg = new Argument($this->argv[$this->index]);
/* let the application decide for: command or arguments */
if (!$arg->isOption()) {
# echo "stop at {$this->index}\n";
$this->fillDefaultValues($this->specs, $result);
return $result;
}
// if the option is with extra flags,
// split it out, and insert into the argv array
//
// like -abc
if ($arg->withExtraFlagOptions()) {
$extra = $arg->extractExtraFlagOptions();
array_splice($this->argv, $this->index + 1, 0, $extra);
$this->argv[$this->index] = $arg->arg; // update argument to current argv list.
$this->length = count($this->argv); // update argv list length
}
$next = null;
if ($this->index + 1 < count($this->argv)) {
$next = new Argument($this->argv[$this->index + 1]);
}
$spec = $this->specs->get($arg->getOptionName());
if (!$spec) {
throw new InvalidOptionException('Invalid option: '.$arg);
}
// This if block is unnecessary
// if ($spec->isRequired() || $spec->isMultiple() || $spec->isOptional() || $spec->isFlag()) {
$this->index += $this->consumeOptionToken($spec, $arg, $next);
$result->set($spec->getId(), $spec);
}
$this->fillDefaultValues($this->specs, $result);
return $result;
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit\Exception;
use Exception;
class InvalidOptionException extends Exception
{
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit\Exception;
use Exception;
class InvalidOptionValueException extends Exception
{
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit\Exception;
use Exception;
class NonNumericException extends Exception
{
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit\Exception;
use Exception;
class OptionConflictException extends Exception
{
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit\Exception;
use Exception;
class RequireValueException extends Exception
{
}

557
vendor/corneltek/getoptionkit/src/Option.php vendored Executable file
View File

@@ -0,0 +1,557 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
use Exception;
use LogicException;
use InvalidArgumentException;
use GetOptionKit\Exception\InvalidOptionValueException;
class Option
{
public $short;
public $long;
/**
* @var string the description of this option
*/
public $desc;
/**
* @var string The option key
*/
public $key; /* key to store values */
public $value;
public $type;
public $valueName; /* name for the value place holder, for printing */
public $isa;
public $isaOption;
public $validValues;
public $suggestions;
public $defaultValue;
public $incremental = false;
/**
* @var Closure The filter closure of the option value.
*/
public $filter;
public $validator;
public $multiple = false;
public $optional = false;
public $required = false;
public $flag = false;
/**
* @var callable trigger callback after value is set.
*/
protected $trigger;
public function __construct($spec)
{
$this->initFromSpecString($spec);
}
/**
* Build spec attributes from spec string.
*
* @param string $specString
*/
protected function initFromSpecString($specString)
{
$pattern = '/
(
(?:[a-zA-Z0-9-]+)
(?:
\|
(?:[a-zA-Z0-9-]+)
)?
)
# option attribute operators
([:+?])?
# value types
(?:=(boolean|string|number|date|file|dir|url|email|ip|ipv6|ipv4))?
/x';
$ret = preg_match($pattern, $specString, $regs);
if ($ret === false || $ret === 0) {
throw new Exception('Incorrect spec string');
}
$orig = $regs[0];
$name = $regs[1];
$attributes = isset($regs[2]) ? $regs[2] : null;
$type = isset($regs[3]) ? $regs[3] : null;
$short = null;
$long = null;
// check long,short option name.
if (strpos($name, '|') !== false) {
list($short, $long) = explode('|', $name);
} else if (strlen($name) === 1) {
$short = $name;
} else if (strlen($name) > 1) {
$long = $name;
}
$this->short = $short;
$this->long = $long;
// option is required.
if (strpos($attributes, ':') !== false) {
$this->required();
} else if (strpos($attributes, '+') !== false) {
// option with multiple value
$this->multiple();
} else if (strpos($attributes, '?') !== false) {
// option is optional.(zero or one value)
$this->optional();
} else {
$this->flag();
}
if ($type) {
$this->isa($type);
}
}
/*
* get the option key for result key mapping.
*/
public function getId()
{
return $this->key ?: $this->long ?: $this->short;
}
/**
* To make -v, -vv, -vvv works.
*/
public function incremental()
{
$this->incremental = true;
return $this;
}
public function required()
{
$this->required = true;
return $this;
}
/**
* Set default value
*
* @param mixed|Closure $value
*/
public function defaultValue($value)
{
$this->defaultValue = $value;
return $this;
}
public function multiple()
{
$this->multiple = true;
$this->value = array(); # for value pushing
return $this;
}
public function optional()
{
$this->optional = true;
return $this;
}
public function flag()
{
$this->flag = true;
return $this;
}
public function trigger(callable $trigger)
{
$this->trigger = $trigger;
return $this;
}
public function isIncremental()
{
return $this->incremental;
}
public function isFlag()
{
return $this->flag;
}
public function isMultiple()
{
return $this->multiple;
}
public function isRequired()
{
return $this->required;
}
public function isOptional()
{
return $this->optional;
}
public function isTypeNumber()
{
return $this->isa == 'number';
}
public function isType($type)
{
return $this->isa === $type;
}
public function getTypeClass()
{
$class = 'GetOptionKit\\ValueType\\'.ucfirst($this->isa).'Type';
if (class_exists($class, true)) {
return new $class($this->isaOption);
}
throw new Exception("Type class '$class' not found.");
}
public function testValue($value)
{
$type = $this->getTypeClass();
return $type->test($value);
}
protected function _preprocessValue($value)
{
$val = $value;
if ($isa = ucfirst($this->isa)) {
$type = $this->getTypeClass();
if ($type->test($value)) {
$val = $type->parse($value);
} else {
if (strtolower($isa) === 'regex') {
$isa .= '('.$this->isaOption.')';
}
throw new InvalidOptionValueException("Invalid value for {$this->renderReadableSpec(false)}. Requires a type $isa.");
}
}
// check pre-filter for option value
if ($this->filter) {
$val = call_user_func($this->filter, $val);
}
// check validValues
if ($validValues = $this->getValidValues()) {
if (!in_array($value, $validValues)) {
throw new InvalidOptionValueException('valid values are: '.implode(', ', $validValues));
}
}
if (!$this->validate($value)[0]) {
throw new InvalidOptionValueException('option is invalid');
}
return $val;
}
protected function callTrigger()
{
if ($this->trigger) {
if ($ret = call_user_func($this->trigger, $this->value)) {
$this->value = $ret;
}
}
}
/*
* set option value
*/
public function setValue($value)
{
$this->value = $this->_preprocessValue($value);
$this->callTrigger();
}
/**
* This method is for incremental option.
*/
public function increaseValue()
{
if (!$this->value) {
$this->value = 1;
} else {
++$this->value;
}
$this->callTrigger();
}
/**
* push option value, when the option accept multiple values.
*
* @param mixed
*/
public function pushValue($value)
{
$value = $this->_preprocessValue($value);
$this->value[] = $value;
$this->callTrigger();
}
public function desc($desc)
{
$this->desc = $desc;
}
/**
* valueName is for option value hinting:.
*
* --name=<name>
*/
public function valueName($name)
{
$this->valueName = $name;
return $this;
}
public function renderValueHint()
{
$n = null;
if ($this->valueName) {
$n = $this->valueName;
} else if ($values = $this->getValidValues()) {
$n = '('.implode(',', $values).')';
} else if ($values = $this->getSuggestions()) {
$n = '['.implode(',', $values).']';
} else if ($val = $this->getDefaultValue()) {
// This allows for `0` and `false` values to be displayed also.
if ((is_scalar($val) && strlen((string) $val)) || is_bool($val)) {
if (is_bool($val)) {
$n = ($val ? 'true' : 'false');
} else {
$n = $val;
}
}
}
if (!$n && $this->isa !== null) {
$n = '<'.$this->isa.'>';
}
if ($this->isRequired()) {
return sprintf('=%s', $n);
} else if ($this->isOptional() || $this->defaultValue) {
return sprintf('[=%s]', $n);
} else if ($n) {
return '='.$n;
}
return '';
}
public function getDefaultValue()
{
if (is_callable($this->defaultValue)) {
return $this->defaultValue;
}
return $this->defaultValue;
}
public function getValue()
{
if (null !== $this->value) {
if (is_callable($this->value)) {
return call_user_func($this->value);
}
return $this->value;
}
return $this->getDefaultValue();
}
/**
* get readable spec for printing.
*
* @param string $renderHint render also value hint
*/
public function renderReadableSpec($renderHint = true)
{
$c1 = '';
if ($this->short && $this->long) {
$c1 = sprintf('-%s, --%s', $this->short, $this->long);
} else if ($this->short) {
$c1 = sprintf('-%s', $this->short);
} else if ($this->long) {
$c1 = sprintf('--%s', $this->long);
}
if ($renderHint) {
return $c1.$this->renderValueHint();
}
return $c1;
}
public function __toString()
{
$c1 = $this->renderReadableSpec();
$return = '';
$return .= sprintf('* key:%-8s spec:%s desc:%s', $this->getId(), $c1, $this->desc)."\n";
$val = $this->getValue();
if (is_array($val)) {
$return .= ' value => ' . join(',', array_map(function($v) { return var_export($v, true); }, $val))."\n";
} else {
$return .= sprintf(' value => %s', $val)."\n";
}
return $return;
}
/**
* Value Type Setters.
*
* @param string $type the value type, valid values are 'number', 'string',
* 'file', 'boolean', you can also use your own value type name.
* @param mixed $option option(s) for value type class (optionnal)
*/
public function isa($type, $option = null)
{
// "bool" was kept for backward compatibility
if ($type === 'bool') {
$type = 'boolean';
}
$this->isa = $type;
$this->isaOption = $option;
return $this;
}
/**
* Assign validValues to member value.
*/
public function validValues($values)
{
$this->validValues = $values;
return $this;
}
/**
* Assign suggestions.
*
* @param Closure|array
*/
public function suggestions($suggestions)
{
$this->suggestions = $suggestions;
return $this;
}
/**
* Return valud values array.
*
* @return string[] or nil
*/
public function getValidValues()
{
if ($this->validValues) {
if (is_callable($this->validValues)) {
return call_user_func($this->validValues);
}
return $this->validValues;
}
return;
}
/**
* Return suggestions.
*
* @return string[] or nil
*/
public function getSuggestions()
{
if ($this->suggestions) {
if (is_callable($this->suggestions)) {
return call_user_func($this->suggestions);
}
return $this->suggestions;
}
return;
}
public function validate($value)
{
if ($this->validator) {
$ret = call_user_func($this->validator, $value);
if (is_array($ret)) {
return $ret;
} else if ($ret === false) {
return array(false, "Invalid value: $value");
} else if ($ret === true) {
return array(true, 'Successfully validated.');
}
throw new InvalidArgumentException('Invalid return value from the validator.');
}
return array(true);
}
public function validator($cb)
{
$this->validator = $cb;
return $this;
}
/**
* Set up a filter function for the option value.
*
* todo: add "callable" type hint later.
*/
public function filter($cb)
{
$this->filter = $cb;
return $this;
}
}

View File

@@ -0,0 +1,207 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
use ArrayIterator;
use IteratorAggregate;
use Countable;
use Exception;
use LogicException;
use GetOptionKit\Exception\OptionConflictException;
class OptionCollection
implements IteratorAggregate, Countable
{
public $data = array();
/**
* @var Option[string]
*
* read-only property
*/
public $longOptions = array();
/**
* @var Option[string]
*
* read-only property
*/
public $shortOptions = array();
/**
* @var Option[]
*
* read-only property
*/
public $options = array();
public function __construct()
{
$this->data = array();
}
public function __clone()
{
foreach ($this->data as $k => $v) {
$this->data[ $k ] = clone $v;
}
foreach ($this->longOptions as $k => $v) {
$this->longOptions[ $k ] = clone $v;
}
foreach ($this->shortOptions as $k => $v) {
$this->shortOptions[ $k ] = clone $v;
}
foreach ($this->options as $k => $v) {
$this->options[ $k ] = clone $v;
}
}
/**
* add( [spec string], [desc string] ).
*
* add( [option object] )
*/
public function add()
{
$num = func_num_args();
$args = func_get_args();
$first = $args[0];
if ($first instanceof Option) {
$this->addOption($first);
} else if (is_string($first)) {
$specString = $args[0];
$desc = isset($args[1]) ? $args[1] : null;
$key = isset($args[2]) ? $args[2] : null;
// parse spec string
$spec = new Option($specString);
if ($desc) {
$spec->desc($desc);
}
if ($key) {
$spec->key = $key;
}
$this->addOption($spec);
return $spec;
} else {
throw new LogicException('Unknown Spec Type');
}
}
/**
* Add option object.
*
* @param object $spec the option object.
*/
public function addOption(Option $spec)
{
$this->data[$spec->getId()] = $spec;
if ($spec->long) {
if (isset($this->longOptions[$spec->long])) {
throw new OptionConflictException('Option conflict: --'.$spec->long.' is already defined.');
}
$this->longOptions[$spec->long] = $spec;
}
if ($spec->short) {
if (isset($this->shortOptions[$spec->short])) {
throw new OptionConflictException('Option conflict: -'.$spec->short.' is already defined.');
}
$this->shortOptions[$spec->short] = $spec;
}
$this->options[] = $spec;
if (!$spec->long && !$spec->short) {
throw new Exception('Neither long option name nor short name is not given.');
}
}
public function getLongOption($name)
{
return isset($this->longOptions[ $name ]) ? $this->longOptions[ $name ] : null;
}
public function getShortOption($name)
{
return isset($this->shortOptions[ $name ]) ? $this->shortOptions[ $name ] : null;
}
/* Get spec by spec id */
public function get($id)
{
if (isset($this->data[$id])) {
return $this->data[$id];
} else if (isset($this->longOptions[$id])) {
return $this->longOptions[$id];
} else if (isset($this->shortOptions[$id])) {
return $this->shortOptions[$id];
}
}
public function find($name)
{
foreach ($this->options as $option) {
if ($option->short === $name || $option->long === $name) {
return $option;
}
}
}
public function size()
{
return count($this->data);
}
public function all()
{
return $this->data;
}
public function toArray()
{
$array = array();
foreach ($this->data as $k => $spec) {
$item = array();
if ($spec->long) {
$item['long'] = $spec->long;
}
if ($spec->short) {
$item['short'] = $spec->short;
}
$item['desc'] = $spec->desc;
$array[] = $item;
}
return $array;
}
public function keys()
{
return array_merge(array_keys($this->longOptions), array_keys($this->shortOptions));
}
public function count()
{
return count($this->data);
}
public function getIterator()
{
return new ArrayIterator($this->data);
}
}

View File

@@ -0,0 +1,193 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
use Exception;
use GetOptionKit\Exception\InvalidOptionException;
use GetOptionKit\Exception\RequireValueException;
class OptionParser
{
public $specs;
public $longOptions;
public $shortOptions;
public function __construct(OptionCollection $specs)
{
$this->specs = $specs;
}
public function setSpecs(OptionCollection $specs)
{
$this->specs = $specs;
}
/**
* consume option value from current argument or from the next argument
*
* @return boolean next token consumed?
*/
protected function consumeOptionToken(Option $spec, $arg, $next, & $success = false)
{
// Check options doesn't require next token before
// all options that require values.
if ($spec->isFlag()) {
if ($spec->isIncremental()) {
$spec->increaseValue();
} else {
$spec->setValue(true);
}
return 0;
} else if ($spec->isRequired()) {
if ($next && !$next->isEmpty() && !$next->anyOfOptions($this->specs)) {
$spec->setValue($next->arg);
return 1;
} else {
throw new RequireValueException("Option '{$arg->getOptionName()}' requires a value.");
}
} else if ($spec->isMultiple()) {
if ($next && !$next->isEmpty() && !$next->anyOfOptions($this->specs)) {
$this->pushOptionValue($spec, $arg, $next);
return 1;
}
} else if ($spec->isOptional() && $next && !$next->isEmpty() && !$next->anyOfOptions($this->specs)) {
$spec->setValue($next->arg);
return 1;
}
return 0;
}
/*
* push value to multipl value option
*/
protected function pushOptionValue(Option $spec, $arg, $next)
{
if ($next && !$next->anyOfOptions($this->specs)) {
$spec->pushValue($next->arg);
}
}
/**
* preprocess the argv array
*
* - split option and option value
* - separate arguments after "--"
*/
protected function preprocessingArguments(array $argv)
{
// preprocessing arguments
$newArgv = array();
$extra = array();
$afterDash = false;
foreach ($argv as $arg) {
if ($arg === '--') {
$afterDash = true;
continue;
}
if ($afterDash) {
$extra[] = $arg;
continue;
}
$a = new Argument($arg);
if ($a->anyOfOptions($this->specs) && $a->containsOptionValue()) {
list($opt, $val) = $a->splitAsOption();
array_push($newArgv, $opt, $val);
} else {
$newArgv[] = $arg;
}
}
return array($newArgv, $extra);
}
protected function fillDefaultValues(OptionCollection $opts, OptionResult $result)
{
// register option result from options with default value
foreach ($opts as $opt) {
if ($opt->value === null && $opt->defaultValue !== null) {
$opt->setValue($opt->getDefaultValue());
$result->set($opt->getId(), $opt);
}
}
}
/**
* @param array $argv
*
* @return OptionResult|Option[]
*
* @throws Exception\RequireValueException
* @throws Exception\InvalidOptionException
* @throws \Exception
*/
public function parse(array $argv)
{
$result = new OptionResult();
list($argv, $extra) = $this->preprocessingArguments($argv);
$len = count($argv);
// some people might still pass only the option names here.
$first = new Argument($argv[0]);
if ($first->isOption()) {
throw new Exception('parse(argv) expects the first argument to be the program name.');
}
for ($i = 1; $i < $len; ++$i) {
$arg = new Argument($argv[$i]);
// if looks like not an option, push it to argument list.
// TODO: we might want to support argument with preceding dash (?)
if (!$arg->isOption()) {
$result->addArgument($arg);
continue;
}
// if the option is with extra flags,
// split the string, and insert into the argv array
if ($arg->withExtraFlagOptions()) {
$extra = $arg->extractExtraFlagOptions();
array_splice($argv, $i + 1, 0, $extra);
$argv[$i] = $arg->arg; // update argument to current argv list.
$len = count($argv); // update argv list length
}
$next = null;
if ($i + 1 < count($argv)) {
$next = new Argument($argv[$i + 1]);
}
$spec = $this->specs->get($arg->getOptionName());
if (!$spec) {
throw new InvalidOptionException('Invalid option: '.$arg);
}
// This if expr might be unnecessary, becase we have default mode - flag
// if ($spec->isRequired() || $spec->isMultiple() || $spec->isOptional() || $spec->isFlag()) {
$i += $this->consumeOptionToken($spec, $arg, $next);
$result->set($spec->getId(), $spec);
}
$this->fillDefaultValues($this->specs, $result);
return $result;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace GetOptionKit\OptionPrinter;
use GetOptionKit\OptionCollection;
use GetOptionKit\Option;
class ConsoleOptionPrinter implements OptionPrinter
{
public $screenWidth = 78;
/**
* Render readable spec.
*/
public function renderOption(Option $opt)
{
$c1 = '';
if ($opt->short && $opt->long) {
$c1 = sprintf('-%s, --%s', $opt->short, $opt->long);
} else if ($opt->short) {
$c1 = sprintf('-%s', $opt->short);
} else if ($opt->long) {
$c1 = sprintf('--%s', $opt->long);
}
$c1 .= $opt->renderValueHint();
return $c1;
}
/**
* render option descriptions.
*
* @return string output
*/
public function render(OptionCollection $options)
{
# echo "* Available options:\n";
$lines = array();
foreach ($options as $option) {
$c1 = $this->renderOption($option);
$lines[] = "\t".$c1;
$lines[] = wordwrap("\t\t".$option->desc, $this->screenWidth, "\n\t\t"); # wrap text
$lines[] = '';
}
return implode("\n", $lines);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace GetOptionKit\OptionPrinter;
use GetOptionKit\OptionCollection;
use GetOptionKit\Option;
interface OptionPrinter
{
public function renderOption(Option $option);
public function render(OptionCollection $options);
}

View File

@@ -0,0 +1,157 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace GetOptionKit;
use ArrayIterator;
use ArrayAccess;
use IteratorAggregate;
use Countable;
/**
* Define the getopt parsing result.
*
* create option result from array()
*
* OptionResult::create($spec, array(
* 'key' => 'value'
* ), array( ... arguments ... ) );
*/
class OptionResult
implements IteratorAggregate, ArrayAccess, Countable
{
/**
* @var array option specs, key => Option object
* */
public $keys = array();
private $currentKey;
/* arguments */
public $arguments = array();
public function getIterator()
{
return new ArrayIterator($this->keys);
}
public function count()
{
return count($this->keys);
}
public function merge(OptionResult $a)
{
$this->keys = array_merge($this->keys, $a->keys);
$this->arguments = array_merge($this->arguments, $a->arguments);
}
public function __isset($key)
{
return isset($this->keys[$key]);
}
public function __get($key)
{
return $this->get($key);
}
public function get($key)
{
if (isset($this->keys[$key])) {
return $this->keys[$key]->getValue();
}
// verifying if we got a camelCased key: http://stackoverflow.com/a/7599674/102960
// get $options->baseDir as $option->{'base-dir'}
$parts = preg_split('/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/', $key);
if (sizeof($parts) > 1) {
$key = implode('-', array_map('strtolower', $parts));
}
if (isset($this->keys[$key])) {
return $this->keys[$key]->getValue();
}
}
public function __set($key, $value)
{
$this->keys[ $key ] = $value;
}
public function has($key)
{
return isset($this->keys[ $key ]);
}
public function set($key, Option $value)
{
$this->keys[ $key ] = $value;
}
public function addArgument(Argument $arg)
{
$this->arguments[] = $arg;
}
public function getArguments()
{
return array_map(function ($e) { return $e->__toString(); }, $this->arguments);
}
public function offsetSet($name, $value)
{
$this->keys[ $name ] = $value;
}
public function offsetExists($name)
{
return isset($this->keys[ $name ]);
}
public function offsetGet($name)
{
return $this->keys[ $name ];
}
public function offsetUnset($name)
{
unset($this->keys[$name]);
}
public function toArray()
{
$array = array();
foreach ($this->keys as $key => $option) {
$array[ $key ] = $option->getValue();
}
return $array;
}
public static function create($specs, array $values = array(), array $arguments = null)
{
$new = new self();
foreach ($specs as $spec) {
$id = $spec->getId();
if (isset($values[$id])) {
$new->$id = $spec;
$spec->setValue($values[$id]);
}
if ($arguments) {
foreach ($arguments as $arg) {
$new->addArgument(new Argument($arg));
}
}
}
return $new;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace GetOptionKit\ValueType;
abstract class BaseType
{
/**
* Type option.
*
* @var mixed
*/
public $option;
public function __construct($option = null)
{
if ($option) {
$this->option = $option;
}
}
/**
* Test a value to see if it fit the type.
*
* @param mixed $value
*/
abstract public function test($value);
/**
* Parse a string value into it's type value.
*
* @param mixed $value
*/
abstract public function parse($value);
}

View File

@@ -0,0 +1,10 @@
<?php
namespace GetOptionKit\ValueType;
/**
* An alias class for boolean type.
*/
class BoolType extends BooleanType
{
}

View File

@@ -0,0 +1,30 @@
<?php
namespace GetOptionKit\ValueType;
class BooleanType extends BaseType
{
public function test($value)
{
if (is_string($value)) {
$value = strtolower($value);
return '0' === $value || '1' === $value
|| 'true' === $value || 'false' === $value;
}
return is_bool($value);
}
public function parse($value)
{
$value = strtolower($value);
if ($value === '0' || $value === 'false') {
return false;
}
if ($value === '1' || $value === 'true') {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace GetOptionKit\ValueType;
use DateTime;
class DateTimeType extends BaseType
{
public $option = array(
'format' => DateTime::ATOM,
);
public function test($value)
{
return DateTime::createFromFormat($this->option['format'], $value) !== false;
}
public function parse($value)
{
return DateTime::createFromFormat($this->option['format'], $value);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace GetOptionKit\ValueType;
class DateType extends BaseType
{
public function test($value)
{
$a = date_parse($value);
if ($a === false || $a['error_count'] > 0) {
return false;
}
return true;
}
public function parse($value)
{
return date_parse($value);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace GetOptionKit\ValueType;
use SplFileInfo;
class DirType extends BaseType
{
public function test($value)
{
return is_dir($value);
}
public function parse($value)
{
return new SplFileInfo($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class EmailType extends BaseType
{
public function test($value)
{
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace GetOptionKit\ValueType;
use SplFileInfo;
class FileType extends BaseType
{
public function test($value)
{
return is_file($value);
}
public function parse($value)
{
return new SplFileInfo($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class IpType extends BaseType
{
public function test($value)
{
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) !== false;
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class Ipv4Type extends BaseType
{
public function test($value)
{
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class Ipv6Type extends BaseType
{
public function test($value)
{
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class NumberType extends BaseType
{
public function test($value)
{
return is_numeric($value);
}
public function parse($value)
{
return intval($value);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace GetOptionKit\ValueType;
use SplFileInfo;
class PathType extends BaseType
{
public function test($value)
{
return file_exists($value);
}
public function parse($value)
{
return new SplFileInfo($value);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace GetOptionKit\ValueType;
class RegexType extends BaseType
{
public $matches = array();
public function __construct($option)
{
$this->option = $option;
}
public function test($value)
{
return preg_match($this->option, $value) !== 0;
}
public function parse($value)
{
preg_match($this->option, $value, $this->matches);
return strval($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class StringType extends BaseType
{
public function test($value)
{
return is_string($value);
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace GetOptionKit\ValueType;
class UrlType extends BaseType
{
public function test($value)
{
return filter_var($value, FILTER_VALIDATE_URL) !== false;
}
public function parse($value)
{
return strval($value);
}
}

View File

@@ -0,0 +1,56 @@
<?php
/*
* This file is part of the {{ }} package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
use GetOptionKit\Argument;
class ArgumentTest extends \PHPUnit\Framework\TestCase
{
function test()
{
$arg = new Argument( '--option' );
$this->assertTrue( $arg->isLongOption() );
$this->assertFalse( $arg->isShortOption() );
$this->assertEquals('option' , $arg->getOptionName());
$this->assertEquals(null, $arg->getOptionValue());
}
function test2()
{
$arg = new Argument('--option=value');
$this->assertNotNull( $arg->containsOptionValue() );
$this->assertEquals('value' , $arg->getOptionValue());
$this->assertEquals('option' , $arg->getOptionName());
}
function test3()
{
$arg = new Argument( '-abc' );
$this->assertNotNull( $arg->withExtraFlagOptions() );
$args = $arg->extractExtraFlagOptions();
$this->assertNotNull( $args );
$this->assertCount( 2, $args );
$this->assertEquals( '-b', $args[0] );
$this->assertEquals( '-c', $args[1] );
$this->assertEquals( '-a', $arg->arg);
}
function testZeroValue()
{
$arg = new Argument( '0' );
$this->assertFalse( $arg->isShortOption() );
$this->assertFalse( $arg->isLongOption() );
$this->assertFalse( $arg->isEmpty() );
}
}

View File

@@ -0,0 +1,335 @@
<?php
/*
* This file is part of the {{ }} package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace tests\GetOptionKit;
use GetOptionKit\ContinuousOptionParser;
use GetOptionKit\OptionCollection;
class ContinuousOptionParserTest extends \PHPUnit\Framework\TestCase
{
public function testOptionCollection()
{
$specs = new OptionCollection;
$specVerbose = $specs->add('v|verbose');
$specColor = $specs->add('c|color');
$specDebug = $specs->add('d|debug');
}
public function argumentProvider()
{
return [
[
['program','subcommand1', 'arg1', 'arg2', 'arg3', 'subcommand2', '-b', 1, 'subcommand3', '-b', 2],
[
'args' => ['arg1', 'arg2', 'arg3']
],
],
[
['program','-v', '-c', 'subcommand1', '--as', 99, 'arg1', 'arg2', 'arg3'],
[
'app' => ['verbose' => true ],
'args' => ['arg1', 'arg2', 'arg3']
],
],
[
['program','-v', '-c', 'subcommand1', '--as', 99, 'arg1', 'arg2', 'arg3', '--','zz','xx','vv'],
[
'app' => ['verbose' => true],
'args' => ['arg1', 'arg2', 'arg3']
],
],
];
}
/**
* @dataProvider argumentProvider
*/
public function testParseSubCommandOptions($argv, $expected)
{
$appspecs = new OptionCollection;
$appspecs->add('v|verbose');
$appspecs->add('c|color');
$appspecs->add('d|debug');
$cmdspecs = new OptionCollection;
$cmdspecs->add('as:');
$cmdspecs->add('b:');
$cmdspecs->add('c:');
$cmdspecs->add('def:')->isa('number')->defaultValue(3);
$parser = new ContinuousOptionParser( $appspecs );
$subcommands = array('subcommand1','subcommand2','subcommand3');
$subcommand_specs = array(
'subcommand1' => clone $cmdspecs,
'subcommand2' => clone $cmdspecs,
'subcommand3' => clone $cmdspecs,
);
$subcommand_options = array();
// $argv = explode(' ','program -v -c subcommand1 --as 99 arg1 arg2 arg3 -- zz xx vv');
// $argv = explode(' ','program subcommand1 -a 1 subcommand2 -a 2 subcommand3 -a 3 arg1 arg2 arg3');
$app_options = $parser->parse( $argv );
$arguments = array();
while (! $parser->isEnd()) {
if (!empty($subcommands) && $parser->getCurrentArgument() == $subcommands[0]) {
$parser->advance();
$subcommand = array_shift($subcommands);
$parser->setSpecs($subcommand_specs[$subcommand]);
$subcommand_options[$subcommand] = $parser->continueParse();
} else {
$arguments[] = $parser->advance();
}
}
$this->assertSame($expected['args'], $arguments);
if (isset($expected['app'])) {
foreach ($expected['app'] as $k => $v) {
$this->assertEquals($v, $app_options->get($k));
}
}
// $this->assertEquals(99, $subcommand_options['subcommand1']->as);
}
public function testParser3()
{
$appspecs = new OptionCollection;
$appspecs->add('v|verbose');
$appspecs->add('c|color');
$appspecs->add('d|debug');
$cmdspecs = new OptionCollection;
$cmdspecs->add('n|name:=string');
$cmdspecs->add('p|phone:=string');
$cmdspecs->add('a|address:=string');
$subcommands = array('subcommand1','subcommand2','subcommand3');
$subcommand_specs = array(
'subcommand1' => $cmdspecs,
'subcommand2' => $cmdspecs,
'subcommand3' => $cmdspecs,
);
$subcommand_options = array();
$arguments = array();
$argv = explode(' ','program -v -d -c subcommand1 --name=c9s --phone=123123123 --address=somewhere arg1 arg2 arg3');
$parser = new ContinuousOptionParser( $appspecs );
$app_options = $parser->parse( $argv );
while (! $parser->isEnd()) {
if (@$subcommands[0] && $parser->getCurrentArgument() == $subcommands[0]) {
$parser->advance();
$subcommand = array_shift( $subcommands );
$parser->setSpecs( $subcommand_specs[$subcommand] );
$subcommand_options[ $subcommand ] = $parser->continueParse();
} else {
$arguments[] = $parser->advance();
}
}
$this->assertCount(3, $arguments);
$this->assertEquals('arg1', $arguments[0]);
$this->assertEquals('arg2', $arguments[1]);
$this->assertEquals('arg3', $arguments[2]);
$this->assertNotNull($subcommand_options['subcommand1']);
$this->assertEquals('c9s', $subcommand_options['subcommand1']->name );
$this->assertEquals('123123123', $subcommand_options['subcommand1']->phone );
$this->assertEquals('somewhere', $subcommand_options['subcommand1']->address );
}
/* test parser without options */
function testParser4()
{
$appspecs = new OptionCollection;
$appspecs->add('v|verbose');
$appspecs->add('c|color');
$appspecs->add('d|debug');
$cmdspecs = new OptionCollection;
$cmdspecs->add('a:'); // required
$cmdspecs->add('b?'); // optional
$cmdspecs->add('c+'); // multiple (required)
$parser = new ContinuousOptionParser( $appspecs );
$this->assertNotNull( $parser );
$subcommands = array('subcommand1','subcommand2','subcommand3');
$subcommand_specs = array(
'subcommand1' => clone $cmdspecs,
'subcommand2' => clone $cmdspecs,
'subcommand3' => clone $cmdspecs,
);
$subcommand_options = array();
$argv = explode(' ','program subcommand1 subcommand2 subcommand3 -a a -b b -c c');
$app_options = $parser->parse( $argv );
$arguments = array();
while( ! $parser->isEnd() ) {
if( @$subcommands[0] && $parser->getCurrentArgument() == $subcommands[0] ) {
$parser->advance();
$subcommand = array_shift( $subcommands );
$parser->setSpecs( $subcommand_specs[$subcommand] );
$subcommand_options[ $subcommand ] = $parser->continueParse();
} else {
$arguments[] = $parser->advance();
}
}
$this->assertNotNull( $subcommand_options );
$this->assertNotNull( $subcommand_options['subcommand1'] );
$this->assertNotNull( $subcommand_options['subcommand2'] );
$this->assertNotNull( $subcommand_options['subcommand3'] );
$r = $subcommand_options['subcommand3'];
$this->assertNotNull( $r );
$this->assertNotNull( $r->a , 'option a' );
$this->assertNotNull( $r->b , 'option b' );
$this->assertNotNull( $r->c , 'option c' );
$this->assertEquals( 'a', $r->a );
$this->assertEquals( 'b', $r->b );
$this->assertEquals( 'c', $r->c[0] );
}
/* test parser without options */
function testParser5()
{
$appspecs = new OptionCollection;
$appspecs->add('v|verbose');
$appspecs->add('c|color');
$appspecs->add('d|debug');
$cmdspecs = new OptionCollection;
$cmdspecs->add('a:');
$cmdspecs->add('b');
$cmdspecs->add('c');
$parser = new ContinuousOptionParser( $appspecs );
$this->assertNotNull( $parser );
$subcommands = array('subcommand1','subcommand2','subcommand3');
$subcommand_specs = array(
'subcommand1' => clone $cmdspecs,
'subcommand2' => clone $cmdspecs,
'subcommand3' => clone $cmdspecs,
);
$subcommand_options = array();
$argv = explode(' ','program subcommand1 -a 1 subcommand2 -a 2 subcommand3 -a 3 arg1 arg2 arg3');
$app_options = $parser->parse( $argv );
$arguments = array();
while (! $parser->isEnd()) {
if (!empty($subcommands) && $parser->getCurrentArgument() == $subcommands[0] ) {
$parser->advance();
$subcommand = array_shift( $subcommands );
$parser->setSpecs($subcommand_specs[$subcommand]);
$subcommand_options[ $subcommand ] = $parser->continueParse();
} else {
$arguments[] = $parser->advance();
}
}
$this->assertEquals( 'arg1', $arguments[0] );
$this->assertEquals( 'arg2', $arguments[1] );
$this->assertEquals( 'arg3', $arguments[2] );
$this->assertNotNull( $subcommand_options );
$this->assertEquals(1, $subcommand_options['subcommand1']->a);
$this->assertNotNull( 2, $subcommand_options['subcommand2']->a );
$this->assertNotNull( 3, $subcommand_options['subcommand3']->a );
}
/**
* @expectedException GetOptionKit\Exception\InvalidOptionException
*/
public function testParseInvalidOptionException()
{
$parser = new ContinuousOptionParser(new OptionCollection);
$parser->parse(array('app','--foo'));
$arguments = array();
while (!$parser->isEnd())
{
$arguments[] = $parser->getCurrentArgument();
$parser->advance();
}
}
public function testMultipleShortOption()
{
$options = new OptionCollection;
$options->add("a");
$options->add("b");
$options->add("c");
$parser = new ContinuousOptionParser($options);
$result = $parser->parse(array('app', '-ab', 'foo', 'bar'));
while (!$parser->isEnd())
{
$arguments[] = $parser->getCurrentArgument();
$parser->advance();
}
$this->assertTrue($result->keys["a"]->value);
$this->assertTrue($result->keys["b"]->value);
}
public function testIncrementalValue()
{
$options = new OptionCollection;
$options->add("v|verbose")->incremental();
$parser = new ContinuousOptionParser($options);
$result = $parser->parse(array('app', '-vvv'));
$this->assertEquals(3, $result->keys["verbose"]->value);
}
/**
* @expectedException GetOptionKit\Exception\InvalidOptionException
*/
public function testUnknownOption()
{
$options = new OptionCollection;
$options->add("v|verbose");
$parser = new ContinuousOptionParser($options);
$result = $parser->parse(array('app', '-b'));
}
/**
* @expectedException LogicException
*/
public function testAdvancedOutOfBounds()
{
$options = new OptionCollection;
$options->add("v|verbose");
$parser = new ContinuousOptionParser($options);
$result = $parser->parse(array('app', '-v'));
$parser->advance();
}
}

View File

@@ -0,0 +1,46 @@
<?php
use GetOptionKit\Option;
use GetOptionKit\OptionCollection;
class OptionCollectionTest extends \PHPUnit\Framework\TestCase
{
public function testAddOption()
{
$opts = new OptionCollection;
$opts->add($o = new Option('v|verbose'));
$this->assertSame($o, $opts->getLongOption('verbose'));
$this->assertSame($o, $opts->getShortOption('v'));
}
/**
* @expectedException LogicException
*/
public function testAddInvalidOption()
{
$opts = new OptionCollection;
$opts->add(123);
}
/**
* @expectedException GetOptionKit\Exception\OptionConflictException
*/
public function testOptionConflictShort()
{
$opts = new OptionCollection;
$opts->add('r|repeat');
$opts->add('t|time');
$opts->add('r|regex');
}
/**
* @expectedException GetOptionKit\Exception\OptionConflictException
*/
public function testOptionConflictLong()
{
$opts = new OptionCollection;
$opts->add('r|repeat');
$opts->add('t|time');
$opts->add('c|repeat');
}
}

View File

@@ -0,0 +1,477 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
use GetOptionKit\InvalidOptionValue;
use GetOptionKit\OptionCollection;
use GetOptionKit\OptionParser;
use GetOptionKit\Option;
class OptionParserTest extends \PHPUnit\Framework\TestCase
{
public $parser;
public $specs;
public function setUp()
{
$this->specs = new OptionCollection;
$this->parser = new OptionParser($this->specs);
}
/**
* @expectedException Exception
*/
public function testInvalidOption()
{
$options = new OptionCollection;
$options->addOption(new Option(0));
}
public function testResultArrayAccessor()
{
$options = new OptionCollection;
$options->add('n|nice:' , 'I take negative value');
$parser = new OptionParser($options);
$result = $parser->parse(array('a', '-n', '-1', '--', '......'));
$this->assertTrue(isset($result->nice));
$this->assertTrue($result->has('nice'));
$this->assertTrue(isset($result['nice']));
$this->assertEquals(-1, $result['nice']->value);
$res = clone $result['nice'];
$res->value = 10;
$result['nice'] = $res;
$this->assertEquals(10, $result['nice']->value);
unset($result['nice']);
}
public function testCamelCaseOptionName()
{
$this->specs->add('base-dir:=dir' , 'I take path');
$result = $this->parser->parse(array('a', '--base-dir', 'src'));
$this->assertInstanceOf('SplFileInfo', $result->baseDir);
}
public function testOptionWithNegativeValue()
{
$this->specs->add('n|nice:' , 'I take negative value');
$result = $this->parser->parse(array('a', '-n', '-1'));
$this->assertEquals(-1, $result->nice);
}
public function testShortOptionName()
{
$this->specs->add('f:' , 'file');
$result = $this->parser->parse(array('a', '-f', 'aaa'));
$this->assertEquals('aaa',$result['f']->getValue());
}
public function testOptionWithShortNameAndLongName()
{
$this->specs->add( 'f|foo' , 'flag' );
$result = $this->parser->parse(array('a', '-f'));
$this->assertTrue($result->foo);
$result = $this->parser->parse(array('a', '--foo'));
$this->assertTrue($result->foo);
}
public function testSpec()
{
$options = new OptionCollection;
$options->add( 'f|foo:' , 'option require value' );
$options->add( 'b|bar+' , 'option with multiple value' );
$options->add( 'z|zoo?' , 'option with optional value' );
$options->add( 'v|verbose' , 'verbose message' );
$options->add( 'd|debug' , 'debug message' );
$this->assertEquals(5, $options->size());
$this->assertEquals(5, count($options));
$opt = $options->get('foo');
$this->assertTrue($opt->isRequired());
$opt = $options->get('bar');
$this->assertTrue( $opt->isMultiple() );
$opt = $options->get('zoo');
$this->assertTrue( $opt->isOptional() );
$opt = $options->get( 'debug' );
$this->assertNotNull( $opt );
$this->assertInstanceOf('GetOptionKit\\Option', $opt);
$this->assertEquals('debug', $opt->long);
$this->assertEquals('d', $opt->short);
$this->assertTrue($opt->isFlag());
return $options;
}
/**
* @depends testSpec
*/
public function testOptionFinder($options)
{
$this->assertNotNull($options->find('f'));
$this->assertNotNull($options->find('foo'));
$this->assertNull($options->find('xyz'));
}
public function testRequire()
{
$this->specs->add( 'f|foo:' , 'option require value' );
$this->specs->add( 'b|bar+' , 'option with multiple value' );
$this->specs->add( 'z|zoo?' , 'option with optional value' );
$this->specs->add( 'v|verbose' , 'verbose message' );
$this->specs->add( 'd|debug' , 'debug message' );
$firstExceptionRaised = false;
$secondExceptionRaised = false;
// option required a value should throw an exception
try {
$result = $this->parser->parse( array('a', '-f' , '-v' , '-d' ) );
}
catch (Exception $e) {
$firstExceptionRaised = true;
}
// even if only one option presented in args array
try {
$result = $this->parser->parse(array('a','-f'));
} catch (Exception $e) {
$secondExceptionRaised = true;
}
if ($firstExceptionRaised && $secondExceptionRaised) {
return;
}
$this->fail('An expected exception has not been raised.');
}
public function testMultiple()
{
$opt = new OptionCollection;
$opt->add( 'b|bar+' , 'option with multiple value' );
$parser = new OptionParser($opt);
$result = $parser->parse(explode(' ','app -b 1 -b 2 --bar 3'));
$this->assertNotNull($result->bar);
$this->assertCount(3,$result->bar);
}
public function testMultipleNumber()
{
$opt = new OptionCollection;
$opt->add('b|bar+=number' , 'option with multiple value');
$parser = new OptionParser($opt);
$result = $parser->parse(explode(' ','app --bar 1 --bar 2 --bar 3'));
$this->assertNotNull($result->bar);
$this->assertCount(3,$result->bar);
$this->assertSame(array(1,2,3),$result->bar);
}
public function testSimpleOptionWithDefaultValue()
{
$opts = new OptionCollection;
$opts->add('p|proc=number' , 'option with required value')
->defaultValue(10)
;
$parser = new OptionParser($opts);
$result = $parser->parse(explode(' ','app'));
$this->assertEquals(10, $result['proc']->value);
}
public function testOptionalOptionWithDefaultValue()
{
$opts = new OptionCollection;
$opts->add('p|proc?=number' , 'option with required value')
->defaultValue(10)
;
$parser = new OptionParser($opts);
$result = $parser->parse(explode(' ','app --proc'));
$this->assertEquals(10, $result['proc']->value);
}
public function testMultipleString()
{
$opts = new OptionCollection;
$opts->add('b|bar+=string' , 'option with multiple value');
$bar = $opts->get('bar');
$this->assertNotNull($bar);
$this->assertTrue($bar->isMultiple());
$this->assertTrue($bar->isType('string'));
$this->assertFalse($bar->isType('number'));
$parser = new OptionParser($opts);
$result = $parser->parse(explode(' ','app --bar lisa --bar mary --bar john a b c'));
$this->assertNotNull($result->bar);
$this->assertCount(3,$result->bar);
$this->assertSame(array('lisa', 'mary', 'john'),$result->bar);
$this->assertSame(array('a','b','c'), $result->getArguments());
}
public function testParseIncrementalOption()
{
$opts = new OptionCollection;
$opts->add('v|verbose' , 'verbose')
->isa("number")
->incremental();
$parser = new OptionParser($opts);
$result = $parser->parse(explode(' ','app -vvv arg1 arg2'));
$this->assertInstanceOf('GetOptionKit\Option',$result['verbose']);
$this->assertNotNull($result['verbose']);
$this->assertEquals(3, $result['verbose']->value);
}
/**
* @expectedException Exception
*/
public function testIntegerTypeNonNumeric()
{
$opt = new OptionCollection;
$opt->add( 'b|bar:=number' , 'option with integer type' );
$parser = new OptionParser($opt);
$spec = $opt->get('bar');
$this->assertTrue($spec->isTypeNumber());
// test non numeric
$result = $parser->parse(explode(' ','app -b test'));
$this->assertNotNull($result->bar);
}
public function testIntegerTypeNumericWithoutEqualSign()
{
$opt = new OptionCollection;
$opt->add('b|bar:=number', 'option with integer type');
$spec = $opt->get('bar');
$this->assertTrue($spec->isTypeNumber());
$parser = new OptionParser($opt);
$result = $parser->parse(explode(' ','app -b 123123'));
$this->assertNotNull($result);
$this->assertEquals(123123, $result->bar);
}
public function testIntegerTypeNumericWithEqualSign()
{
$opt = new OptionCollection;
$opt->add('b|bar:=number' , 'option with integer type');
$spec = $opt->get('bar');
$this->assertTrue($spec->isTypeNumber());
$parser = new OptionParser($opt);
$result = $parser->parse(explode(' ','app -b=123123'));
$this->assertNotNull($result);
$this->assertNotNull($result->bar);
$this->assertEquals(123123, $result->bar);
}
public function testStringType()
{
$this->specs->add( 'b|bar:=string' , 'option with type' );
$spec = $this->specs->get('bar');
$result = $this->parser->parse(explode(' ','app -b text arg1 arg2 arg3'));
$this->assertNotNull($result->bar);
$result = $this->parser->parse(explode(' ','app -b=text arg1 arg2 arg3'));
$this->assertNotNull($result->bar);
$args = $result->getArguments();
$this->assertNotEmpty($args);
$this->assertCount(3,$args);
$this->assertEquals('arg1', $args[0]);
$this->assertEquals('arg2', $args[1]);
$this->assertEquals('arg3', $args[2]);
}
public function testStringQuoteOptionValue()
{
$opts = new OptionCollection();
$opts->add('f|foo:' , 'option requires a value.');
$parser = new OptionParser($opts);
$res = $parser->parse(['app','--foo=aa bb cc']);
$this->assertEquals('aa bb cc', $res->get('foo'));
}
public function testSpec2()
{
$this->specs->add('long' , 'long option name only.');
$this->specs->add('a' , 'short option name only.');
$this->specs->add('b' , 'short option name only.');
$this->assertNotNull($this->specs->all());
$this->assertNotNull($this->specs);
$this->assertNotNull($result = $this->parser->parse(explode(' ','app -a -b --long')) );
$this->assertNotNull($result->a);
$this->assertNotNull($result->b);
}
public function testSpecCollection()
{
$this->specs->add( 'f|foo:' , 'option requires a value.' );
$this->specs->add( 'b|bar+' , 'option with multiple value.' );
$this->specs->add( 'z|zoo?' , 'option with optional value.' );
$this->specs->add( 'v|verbose' , 'verbose message.' );
$this->specs->add( 'd|debug' , 'debug message.' );
$this->specs->add( 'long' , 'long option name only.' );
$this->specs->add( 's' , 'short option name only.' );
$this->assertNotNull( $this->specs->all() );
$this->assertNotNull( $this->specs );
$this->assertCount( 7 , $array = $this->specs->toArray() );
$this->assertNotEmpty( isset($array[0]['long'] ));
$this->assertNotEmpty( isset($array[0]['short'] ));
$this->assertNotEmpty( isset($array[0]['desc'] ));
}
public function optionTestProvider()
{
return array(
array( 'foo', 'simple boolean option', 'foo', true,
[['a','--foo','a', 'b', 'c']]
),
array( 'f|foo', 'simple boolean option', 'foo', true,
[['a','--foo'], ['a','-f']]
),
array( 'f|foo:=string', 'string option', 'foo', 'xxx',
[['a','--foo','xxx'], ['a','-f', 'xxx']]
),
array( 'f|foo:=string', 'string option', 'foo', 'xxx',
[['a','b', 'c', '--foo','xxx'], ['a', 'a', 'b', 'c', '-f', 'xxx']]
),
);
}
/**
* @dataProvider optionTestProvider
*/
public function test($specString, $desc, $key, $expectedValue, array $argvList)
{
$opts = new OptionCollection();
$opts->add($specString, $desc);
$parser = new OptionParser($opts);
foreach ($argvList as $argv) {
$res = $parser->parse($argv);
$this->assertSame($expectedValue, $res->get($key));
}
}
/**
* @expectedException Exception
*/
public function testParseWithoutProgramName()
{
$parser = new OptionParser(new OptionCollection);
$parser->parse(array('--foo'));
}
/**
* @expectedException GetOptionKit\Exception\InvalidOptionException
*/
public function testParseInvalidOptionException()
{
$parser = new OptionParser(new OptionCollection);
$parser->parse(array('app','--foo'));
}
/**
* @expectedException GetOptionKit\Exception\RequireValueException
*/
public function testParseOptionRequireValueException()
{
$options = new OptionCollection;
$options->add('name:=string', 'name');
$parser = new OptionParser($options);
$parser->parse(array('app','--name'));
}
public function testMore()
{
$this->specs->add('f|foo:' , 'option require value' );
$this->specs->add('b|bar+' , 'option with multiple value' );
$this->specs->add('z|zoo?' , 'option with optional value' );
$this->specs->add('v|verbose' , 'verbose message' );
$this->specs->add('d|debug' , 'debug message' );
$result = $this->parser->parse( array('a', '-f' , 'foo value' , '-v' , '-d' ) );
$this->assertNotNull($result->foo);
$this->assertNotNull($result->verbose);
$this->assertNotNull($result->debug);
$this->assertEquals( 'foo value', $result->foo );
$this->assertNotNull( $result->verbose );
$this->assertNotNull( $result->debug );
foreach ($result as $k => $v) {
$this->assertTrue(in_array($k, ['foo','bar','zoo','verbose', 'debug']));
$this->assertInstanceOf('GetOptionKit\\Option', $v);
}
$this->assertSame([
'foo' => 'foo value',
'verbose' => true,
'debug' => true
], $result->toArray());
$result = $this->parser->parse( array('a', '-f=foo value' , '-v' , '-d' ) );
$this->assertNotNull( $result );
$this->assertNotNull( $result->foo );
$this->assertNotNull( $result->verbose );
$this->assertNotNull( $result->debug );
$this->assertEquals( 'foo value', $result->foo );
$this->assertNotNull( $result->verbose );
$this->assertNotNull( $result->debug );
$result = $this->parser->parse( array('a', '-vd' ) );
$this->assertNotNull( $result->verbose );
$this->assertNotNull( $result->debug );
}
public function testParseAcceptsValidOption()
{
$this->specs
->add('f:foo', 'test option')
->validator(function($value) {
return $value === 'valid-option';
});
$result = $this->parser->parse(array('a', '-f' , 'valid-option'));
$this->assertArrayHasKey('f', $result);
}
/**
* @expectedException GetOptionKit\Exception\InvalidOptionValueException
*/
public function testParseThrowsExceptionOnInvalidOption()
{
$this->specs
->add('f:foo', 'test option')
->validator(function($value) {
return $value === 'valid-option';
});
$this->parser->parse(array('a', '-f' , 'not-a-valid-option'));
}
}

View File

@@ -0,0 +1,32 @@
<?php
use GetOptionKit\OptionPrinter\ConsoleOptionPrinter;
use GetOptionKit\OptionCollection;
class ConsoleOptionPrinterTest extends \PHPUnit\Framework\TestCase
{
public function test()
{
$options = new OptionCollection;
$options->add('f|foo:', 'option requires a value.' )
->isa('String');
$options->add('b|bar+', 'option with multiple value.' )
->isa('Number');
$options->add('z|zoo?', 'option with optional value.' )
->isa('Boolean')
;
$options->add('n', 'n flag' );
$options->add('verbose', 'verbose');
$options->add('o|output?', 'option with optional value.' )
->isa('File')
->defaultValue('output.txt')
;
$printer = new ConsoleOptionPrinter;
$output = $printer->render($options);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the GetOptionKit package.
*
* (c) Yo-An Lin <cornelius.howl@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
class OptionResultTest extends \PHPUnit\Framework\TestCase
{
function testOption()
{
$option = new \GetOptionKit\OptionResult;
$this->assertNotNull( $option );
$specs = new \GetOptionKit\OptionCollection;
$specs->add('name:','name');
$result = \GetOptionKit\OptionResult::create($specs,array( 'name' => 'c9s' ),array( 'arg1' ));
$this->assertNotNull( $result );
$this->assertNotNull( $result->arguments );
$this->assertNotNull( $result->name );
$this->assertEquals( 'c9s', $result->name );
$this->assertEquals( $result->arguments[0] , 'arg1' );
}
}

View File

@@ -0,0 +1,227 @@
<?php
use GetOptionKit\Option;
class OptionTest extends \PHPUnit\Framework\TestCase
{
public function optionSpecDataProvider() {
return [
['i'],
['f'],
['a=number'],
// long options
['n|name'],
['e|email'],
];
}
/**
* @dataProvider optionSpecDataProvider
*/
public function testOptionSpec($spec)
{
$opt = new Option($spec);
$this->assertNotNull($opt);
}
/**
* @expectedException Exception
*/
public function testInvalidOptionSpec()
{
new Option('....');
}
public function testValueName()
{
$opt = new Option('z');
$opt->defaultValue(10);
$opt->valueName('priority');
$this->assertEquals('[=priority]', $opt->renderValueHint());
$this->assertEquals('-z[=priority]', $opt->renderReadableSpec());
}
public function testDefaultValue()
{
$opt = new Option('z');
$opt->defaultValue(10);
$this->assertEquals(10, $opt->getValue());
$this->assertEquals('-z[=10]',$opt->renderReadableSpec(true));
}
public function testBackwardCompatibleBoolean()
{
$opt = new Option('scope');
$opt->isa('bool');
$this->assertEquals('boolean', $opt->isa);
$this->assertEquals('--scope=<boolean>',$opt->renderReadableSpec(true));
}
public function validatorProvider()
{
return [
[function($a) { return in_array($a, ['public', 'private']); }],
[function($a) { return [in_array($a, ['public', 'private']), "message"]; }]
];
}
/**
* @dataProvider validatorProvider
*/
public function testValidator($cb)
{
$opt = new Option('scope');
$opt->validator($cb);
$ret = $opt->validate('public');
$this->assertTrue($ret[0]);
$ret = $opt->validate('private');
$this->assertTrue($ret[0]);
$ret = $opt->validate('foo');
$this->assertFalse($ret[0]);
$this->assertEquals('--scope', $opt->renderReadableSpec(true));
}
/**
* @expectedException Exception
*/
public function testInvalidTypeClass()
{
$opt = new Option('scope');
$opt->isa('SomethingElse');
$class = $opt->getTypeClass();
}
/**
* @expectedException InvalidArgumentException
*/
public function testValidatorReturnValue()
{
$opt = new Option('scope');
$opt->validator(function($val) {
return 123454;
});
$ret = $opt->validate('public');
}
public function testOptionWithoutValidator()
{
$opt = new Option('scope');
$ret = $opt->validate('public');
$this->assertTrue($ret[0]);
$ret = $opt->validate('private');
$this->assertTrue($ret[0]);
$ret = $opt->validate('foo');
$this->assertTrue($ret[0]);
$this->assertEquals('--scope',$opt->renderReadableSpec(true));
}
public function testSuggestionsCallback()
{
$opt = new Option('scope');
$this->assertEmpty($opt->getSuggestions());
$opt->suggestions(function() {
return ['public', 'private'];
});
$this->assertNotEmpty($opt->getSuggestions());
$this->assertSame(['public', 'private'],$opt->getSuggestions());
$opt->setValue('public');
$opt->setValue('private');
$this->assertEquals('private',$opt->value);
$this->assertEquals('--scope=[public,private]',$opt->renderReadableSpec(true));
}
public function testSuggestions()
{
$opt = new Option('scope');
$opt->suggestions(['public', 'private']);
$this->assertNotEmpty($opt->getSuggestions());
$this->assertSame(['public', 'private'],$opt->getSuggestions());
$opt->setValue('public');
$opt->setValue('private');
$this->assertEquals('private',$opt->value);
$this->assertEquals('--scope=[public,private]',$opt->renderReadableSpec(true));
}
public function testValidValuesCallback() {
$opt = new Option('scope');
$opt->validValues(function() {
return ['public', 'private'];
});
$this->assertNotNull($opt->getValidValues());
$this->assertNotEmpty($opt->getValidValues());
$opt->setValue('public');
$opt->setValue('private');
$this->assertEquals('private',$opt->value);
$this->assertEquals('--scope=(public,private)',$opt->renderReadableSpec(true));
}
public function testTrigger()
{
$opt = new Option('scope');
$opt->validValues([ 'public', 'private' ]);
$state = 0;
$opt->trigger(function($val) use(& $state) {
$state++;
});
$this->assertNotEmpty($opt->getValidValues());
$opt->setValue('public');
$this->assertEquals(1, $state);
$opt->setValue('private');
$this->assertEquals(2, $state);
}
public function testArrayValueToString()
{
$opt = new Option('uid');
$opt->setValue([1,2,3,4]);
$toString = '* key:uid spec:--uid desc:
value => 1,2,3,4
';
$this->assertEquals($toString,$opt->__toString());
}
public function testValidValues()
{
$opt = new Option('scope');
$opt->validValues([ 'public', 'private' ])
;
$this->assertNotEmpty($opt->getValidValues());
$this->assertTrue(is_array($opt->getValidValues()));
$opt->setValue('public');
$opt->setValue('private');
$this->assertEquals('private',$opt->value);
$this->assertEquals('--scope=(public,private)',$opt->renderReadableSpec(true));
$this->assertNotEmpty($opt->__toString());
}
public function testFilter() {
$opt = new Option('scope');
$opt->filter(function($val) {
return preg_replace('#a#', 'x', $val);
})
;
$opt->setValue('aa');
$this->assertEquals('xx', $opt->value);
}
}

View File

@@ -0,0 +1,26 @@
<?php
use GetOptionKit\ValueType\RegexType;
class RegexValueTypeTest extends \PHPUnit\Framework\TestCase
{
public function testOption()
{
$regex = new RegexType('#^Test$#');
$this->assertEquals($regex->option, '#^Test$#');
}
public function testValidation()
{
$regex = new RegexType('#^Test$#');
$this->assertTrue($regex->test('Test'));
$this->assertFalse($regex->test('test'));
$regex->option = '/^([a-z]+)$/';
$this->assertTrue($regex->test('barfoo'));
$this->assertFalse($regex->test('foobar234'));
$ret = $regex->parse('foobar234');
$this->assertNotNull($ret);
}
}

View File

@@ -0,0 +1,200 @@
<?php
use GetOptionKit\ValueType\BooleanType;
use GetOptionKit\ValueType\StringType;
use GetOptionKit\ValueType\FileType;
use GetOptionKit\ValueType\DirType;
use GetOptionKit\ValueType\NumberType;
use GetOptionKit\ValueType\UrlType;
use GetOptionKit\ValueType\IpType;
use GetOptionKit\ValueType\Ipv4Type;
use GetOptionKit\ValueType\Ipv6Type;
use GetOptionKit\ValueType\EmailType;
use GetOptionKit\ValueType\PathType;
use GetOptionKit\ValueType\DateType;
use GetOptionKit\ValueType\DateTimeType;
use GetOptionKit\ValueType\RegexType;
class ValueTypeTest extends \PHPUnit\Framework\TestCase
{
public function testTypeClass()
{
$this->assertNotNull( new BooleanType );
$this->assertNotNull( new StringType );
$this->assertNotNull( new FileType );
$this->assertNotNull( new DateType );
$this->assertNotNull( new DateTimeType );
$this->assertNotNull( new NumberType );
$this->assertNotNull( new UrlType );
$this->assertNotNull( new IpType );
$this->assertNotNull( new Ipv4Type );
$this->assertNotNull( new Ipv6Type );
$this->assertNotNull( new EmailType );
$this->assertNotNull( new PathType );
$this->assertNotNull( new RegexType("/[a-z]/"));
}
public function testDateTimeType()
{
$type = new DateTimeType([ 'format' => 'Y-m-d' ]);
$this->assertTrue($type->test('2016-12-30'));
$a = $type->parse('2016-12-30');
$this->assertEquals(2016, $a->format('Y'));
$this->assertEquals(12, $a->format('m'));
$this->assertEquals(30, $a->format('d'));
$this->assertFalse($type->test('foo'));
}
public function testDateType()
{
$type = new DateType;
$this->assertTrue($type->test('2016-12-30'));
$a = $type->parse('2016-12-30');
$this->assertEquals(2016, $a['year']);
$this->assertEquals(12, $a['month']);
$this->assertEquals(30, $a['day']);
$this->assertFalse($type->test('foo'));
}
public function booleanTestProvider()
{
return [
[true , true, true],
[false , true, false],
['true' , true, true],
['false' , true, false],
['0' , true, false],
['1' , true, true],
['foo' , false, null],
['123' , false, null],
];
}
/**
* @dataProvider booleanTestProvider
*/
public function testBooleanType($a, $test, $expected)
{
$bool = new BooleanType;
$this->assertEquals($test, $bool->test($a));
if ($bool->test($a)) {
$this->assertEquals($expected, $bool->parse($a));
}
}
public function testDirType()
{
$type = new DirType;
$this->assertTrue($type->test('tests'));
$this->assertFalse($type->test('composer.json'));
$this->assertFalse($type->test('foo/bar'));
$this->assertInstanceOf('SplFileInfo',$type->parse('tests'));
}
public function testFileType()
{
$type = new FileType;
$this->assertFalse($type->test('tests'));
$this->assertTrue($type->test('composer.json'));
$this->assertFalse($type->test('foo/bar'));
$this->assertInstanceOf('SplFileInfo', $type->parse('composer.json'));
}
public function testPathType()
{
$type = new PathType;
$this->assertTrue($type->test('tests'));
$this->assertTrue($type->test('composer.json'));
$this->assertFalse($type->test('foo/bar'));
$this->assertInstanceOf('SplFileInfo', $type->parse('composer.json'));
}
public function testUrlType()
{
$url = new UrlType;
$this->assertTrue($url->test('http://t'));
$this->assertTrue($url->test('http://t.c'));
$this->assertFalse($url->test('t.c'));
$this->assertEquals('http://t.c', $url->parse('http://t.c'));
}
public function ipV4Provider()
{
return [
['192.168.25.58', true],
['8.8.8.8', true],
['github.com', false],
];
}
public function ipV6Provider()
{
return [
['192.168.25.58', false],
['2607:f0d0:1002:51::4', true],
['2607:f0d0:1002:0051:0000:0000:0000:0004', true],
['::1', true],
['10.10.15.10/16', false],
['github.com', false],
];
}
public function ipProvider()
{
return [
['192.168.25.58', true],
['2607:f0d0:1002:51::4', true],
['::1', true],
['10.10.15.10/16', false],
['github.com', false],
];
}
/**
* @dataProvider ipProvider
*/
public function testIpType($ipstr, $pass = true)
{
$ip = new IpType;
$this->assertEquals($pass, $ip->test($ipstr));
if ($pass) {
$this->assertNotNull($ip->parse($ipstr));
}
}
/**
* @dataProvider ipV4Provider
*/
public function testIpv4Type($ipstr, $pass = true)
{
$ipv4 = new Ipv4Type;
$this->assertEquals($pass, $ipv4->test($ipstr));
if ($pass) {
$this->assertNotNull($ipv4->parse($ipstr));
}
}
/**
* @dataProvider ipV6Provider
*/
public function testIpv6Type($ipstr, $pass = true)
{
$ipv6 = new Ipv6Type;
$this->assertEquals($pass, $ipv6->test($ipstr));
if ($pass) {
$this->assertNotNull($ipv6->parse($ipstr));
}
}
public function testEmailType()
{
$email = new EmailType;
$this->assertTrue($email->test('test@gmail.com'));
$this->assertFalse($email->test('test@test'));
$email->parse('test@gmail.com');
}
}