Skip to content

Commit

Permalink
Initial load of rev 1354 into git
Browse files Browse the repository at this point in the history
Code copied from Web2All svn rev 1354 (modified)
  • Loading branch information
merijnvdk committed Dec 15, 2017
0 parents commit 6e979ac
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2007-2017 Web2All B.V.

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.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Web2All shell

This `web2all/shell` package requires the `web2all/framework` ([https://github.com/web2all/framework](https://github.com/web2all/framework)). It used to be proprietary software but now it has been released to the public domain under a MIT license.

This pacckage is no longer actively maintained. Most likely it is only of interest if you own software created by Web2All B.V. which was built using these classes.

## What does it do ##

This package contains a (shell) commandline argument and switches parsing class. Poor mans implementation of something like perls `Getopt::Long`.

## License ##

Web2All framework is open-sourced software licensed under the MIT license ([https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT "license")).
25 changes: 25 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "web2all/shell",
"description": "Web2All shell tooling (argument parsing)",
"keywords": ["web2all","shell","arg"],
"license": "MIT",
"authors": [
{
"name": "Merijn van den Kroonenberg",
"homepage": "https://github.com/merijnvdk",
"role": "Developer"
}
],
"require": {
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"autoload": {
"classmap": [
"src/"
]
}
}

169 changes: 169 additions & 0 deletions src/Web2All/Shell/Args.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php
/**
* Shell arguments handling
*
* This class manages arguments passed to a shell script
* Its behavior is a littlebit vague where script arguments are concerned, so
* everything not being an option.
* This because this class doesn't know anything about the *expected* options
* and params. So it doesn't know if something is an argument or a value for the last
* option.
* Todo: add option hinting, so this class knows what to expect
*
* @author Merijn van den Kroonenberg
* @copyright (c) Copyright 2007-2015 Web2All B.V.
* @since 2007-07-20
*/
class Web2All_Shell_Args {

/**
* The parsed arguments, array with key the argument name and value
* a string or true if valueless.
*
* These are actually (long)options/switches and not arguments
*
* @var array
*/
public $args=array();

/**
* These are the script params folowing the (optional) options
*
* @var array
*/
protected $params=array();

/**
* The scriptname (as it was called)
*
* @var string
*/
protected $scriptname;

public function __construct($web2all=null) {
// does not implement Plugin because this needs to be used before
// Web2All_Manager object is constructed.
if(array_key_exists('argv',$_SERVER)){
$this->parseArguments($_SERVER['argv']);
}
}

/**
* Parse argv into an array with key-value pairs
*
* @param array $argv
* @return array
*/
public function parseArguments($argv) {
$this->args = array();
$this->params=array();
$prev_arg='';
$first=true;
foreach ($argv as $arg) {
// the first arg is the scriptname
if ($first){
$first=false;
$this->scriptname=$arg;
} elseif (preg_match('/^--?([^=]+)=([^\s]*)$/',$arg,$reg)) {
// ok, we have something like --option=value
if($prev_arg && count($this->params)>0){
// if we have params, append them to the last (previous) option
if($this->args[$prev_arg]===true){
$this->args[$prev_arg]=implode(' ', $this->params);
}else{
$this->args[$prev_arg].=' '.implode(' ', $this->params);
}
}
$this->args[$reg[1]] = $reg[2];
$prev_arg=$reg[1];
// as we still have options, reset the params as we expect them to be after the options
$this->params=array();
} elseif(preg_match('/^--?([a-zA-Z0-9_+-]+)$/',$arg,$reg)) {
// we have something like --option or -option or --opt-ion+more
if($prev_arg && count($this->params)>0){
// if we have params, append them to the last (previous) option
if($this->args[$prev_arg]===true){
$this->args[$prev_arg]=implode(' ', $this->params);
}else{
$this->args[$prev_arg].=' '.implode(' ', $this->params);
}
}
$this->args[$reg[1]] = true;
$prev_arg=$reg[1];
// as we still have options, reset the params as we expect them to be after the options
$this->params=array();
} else {
// not a param, so its a value (belonging to the last param) or an argument
if($prev_arg && $this->args[$prev_arg]===true){
// okay, we had a previous option, and it was true, so it didn't have a value yet,
// so this value might be for that option
// But we will delay adding it, if another option follows, we will add this (and
// possibly more) as value to this option. Or we will do so when parsing ends.

// because we do not know for sure if the option actually accepts values, this could also
// be a script param. So add it.
$this->params[]=$arg;
} elseif($prev_arg) {
// okay, we had a previous option, but it was not true...this means it already
// has a value.
// if there are no more other options, then the chance is high this is actually a script
// param, so add it there. It will be reset if we find another option.
$this->params[]=$arg;
}else{
// there was no previous option, so it must be a script param
// if we get an option after this then thats weird and this param will be dropped.
$this->params[]=$arg;
}
}

}
// ok we parsed all arguments, lets finish up
if($prev_arg && count($this->params)>0 && $this->args[$prev_arg]===true){
// if we have params and options and the last option doesn't have a value yet,
// set its value to the first argument. But keep the first argument because we do not
// actually know if its an argument or belongs to the last option.
$this->args[$prev_arg]=$this->params[0];
}

return $this->args;
}

/**
* Get a longopt value by name
*
* It would be better if this method was named getOpt, but its too late to change that
*
* @param string $name longopt name
* @return mixed false if the param is not present, true or string if it is present
*/
public function getArg($name) {
if(array_key_exists($name,$this->args)){
return $this->args[$name];
}else{
return false;
}
}

/**
* Get all script arguments/params
*
* Basically this are all params which appear after the last option.
* Possibly it includes the value of the last option.
*
* @return string[]
*/
public function getParams() {
return $this->params;
}

/**
* Get the scriptname
*
* @return string
*/
public function getScriptname() {
return $this->scriptname;
}

}
?>
70 changes: 70 additions & 0 deletions tests/Web2All/Shell/ArgsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
use PHPUnit\Framework\TestCase;

class Web2All_Shell_ArgsTest extends TestCase
{
/**
* Web2All framework
*
* @var Web2All_Manager_Main
*/
protected static $Web2All;

public static function setUpBeforeClass()
{
self::$Web2All = new Web2All_Manager_Main();
}

/**
* Test con storage loading
*
* @param array $argv
* @param array $expected_opts
* @param array $expected_args
* @dataProvider argumentProvider
*/
public function testArgs($argv,$expected_opts,$expected_args)
{
$args = self::$Web2All->Factory->Web2All_Shell_Args();
$opts = $args->parseArguments($argv);
$this->assertEquals($expected_opts, $opts, 'parsed options and switches');
$params=$args->getParams();
$this->assertEquals($expected_args, $params, 'parsed arguments');
}

/**
* Provide tasks
*
* @return array
*/
public function argumentProvider()
{
return array(
// test.php --test
array ( array ( 'test.php', '--test' ), array ( 'test' => true ), array ( ) ),
// test.php -t
array ( array ( 'test.php', '-t' ), array ( 't' => true ), array ( ) ),
// test.php -tp
array ( array ( 'test.php', '-tp' ), array ( 'tp' => true ), array ( ) ),
// test.php -t --test
array ( array ( 'test.php', '-t', '--test' ), array ( 't' => true, 'test' => true ), array ( ) ),
// test.php -a b
array ( array ( 'test.php', '-a', 'b' ), array ( 'a' => 'b' ), array ( 'b' ) ),
// test.php -a=b
array ( array ( 'test.php', '-a=b' ), array ( 'a' => 'b' ), array ( ) ),
// test.php -a "a b c"
array ( array ( 'test.php', '-a', 'a b c' ), array ( 'a' => 'a b c' ), array ( 'a b c' ) ),
// test.php --anoption "a b c"
array ( array ( 'test.php', '--anoption', 'a b c' ), array ( 'anoption' => 'a b c' ), array ( 'a b c' ) ),
// test.php arg1
array ( array ( 'test.php', 'arg1' ), array ( ), array ( 'arg1' ) ),
// test.php arg1 arg2
array ( array ( 'test.php', 'arg1', 'arg2' ), array ( ), array ( 'arg1', 'arg2' ) ),
// test.php arg1 arg2 arg3
array ( array ( 'test.php', 'arg1', 'arg2', 'arg3' ), array ( ), array ( 'arg1', 'arg2', 'arg3' ) ),
// test.php --bool-opt1 --bool-opt2 --str-opt test --int-opt=1 arg1 arg2 arg3
array ( array ( 'test.php', '--bool-opt1', '--bool-opt2', '--str-opt', 'test', '--int-opt=1', 'arg1', 'arg2', 'arg3' ), array ( 'bool-opt1' => true, 'bool-opt2' => true, 'str-opt' => 'test', 'int-opt' => '1' ), array ( 'arg1', 'arg2', 'arg3' ) )
);
}
}
?>

0 comments on commit 6e979ac

Please sign in to comment.