Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor (Option::type) More consistant constants #94

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
],
"require": {
"php": ">=5.4",
"kevinlebrun/colors.php": "~0.2"
"kevinlebrun/colors.php": "~0.2",
"ducks-project/spl-types": "^1.0"

},
"version": "0.3.0",
Expand Down
33 changes: 13 additions & 20 deletions src/Commando/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

namespace Commando;

use Commando\Option\TypeEnum;

/**
* Here are all the methods available through __call. For accurate method documentation, see the actual method.
*
Expand Down Expand Up @@ -55,9 +57,9 @@

class Command implements \ArrayAccess, \Iterator
{
const OPTION_TYPE_ARGUMENT = 1; // e.g. foo
const OPTION_TYPE_SHORT = 2; // e.g. -u
const OPTION_TYPE_VERBOSE = 4; // e.g. --username
const OPTION_TYPE_ARGUMENT = TypeEnum::ARGUMENT; // e.g. foo
const OPTION_TYPE_SHORT = TypeEnum::SHORT; // e.g. -u
const OPTION_TYPE_VERBOSE = TypeEnum::LONG; // e.g. --username

private
$current_option = null,
Expand Down Expand Up @@ -427,7 +429,7 @@ public function parse()
list($name, $type) = $this->_parseOption($token);

// We allow short groups
if (strlen($name) > 1 && $type === self::OPTION_TYPE_SHORT) {
if (strlen($name) > 1 && $type === TypeEnum::SHORT) {

$group = str_split($name);
// correct option name
Expand All @@ -441,7 +443,7 @@ public function parse()
}
}

if ($type === self::OPTION_TYPE_ARGUMENT) {
if ($type === TypeEnum::ARGUMENT) {
// its an argument, use an int as the index
$keyvals[$count] = $name;

Expand Down Expand Up @@ -473,7 +475,7 @@ public function parse()
// the next token MUST be an "argument" and not another flag/option
$token = array_shift($tokens);
list($val, $type) = $this->_parseOption($token);
if ($type !== self::OPTION_TYPE_ARGUMENT)
if ($type !== TypeEnum::ARGUMENT)
throw new \Exception(sprintf('Unable to parse option %s: Expected an argument', $token));
$keyvals[$name] = $val;
}
Expand All @@ -490,8 +492,8 @@ public function parse()
foreach ($this->options as $option) {
if (is_null($option->getValue()) && $option->isRequired()) {
throw new \Exception(sprintf('Required %s %s must be specified',
$option->getType() & Option::TYPE_NAMED ?
'option' : 'argument', $option->getName()));
$option->getType() === TypeEnum::ARGUMENT ?
'argument' : 'option', $option->getName()));
}
}

Expand Down Expand Up @@ -521,15 +523,6 @@ public function parse()
$this->sorted_keys = array_keys($this->options);
natsort($this->sorted_keys);

// // See if our options have what they require
// foreach ($this->options as $option) {
// $needs = $option->hasNeeds($keyvals);
// if ($needs !== true) {
// throw new \InvalidArgumentException(
// 'Option "'.$option->getName().'" does not have required option(s): '.implode(', ', $needs)
// );
// }
// }
} catch(\Exception $e) {
$this->error($e);
}
Expand Down Expand Up @@ -581,12 +574,12 @@ private function _parseOption($token)

if (!empty($matches['hyphen'])) {
$type = (strlen($matches['hyphen']) === 1) ?
self::OPTION_TYPE_SHORT:
self::OPTION_TYPE_VERBOSE;
TypeEnum::SHORT:
TypeEnum::LONG;
return array($matches['name'], $type);
}

return array($token, self::OPTION_TYPE_ARGUMENT);
return array($token, TypeEnum::ARGUMENT);
}


Expand Down
24 changes: 11 additions & 13 deletions src/Commando/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Commando;
use \Commando\Util\Terminal;
use \Commando\Option\TypeEnum;

/**
* Here are all the methods available through __call. For accurate method documentation, see the actual method.
Expand Down Expand Up @@ -48,7 +49,7 @@ class Option
$required = false, /* bool */
$needs = array(), /* set of other required options for this option */
$boolean = false, /* bool */
$type = 0, /* int see constants */
$type = 0, /* TypeEnum(int) */
$rule, /* closure */
$map, /* closure */
$increment = false, /* bool */
Expand All @@ -58,10 +59,10 @@ class Option
$file_require_exists, /* bool require that the file path is valid */
$file_allow_globbing; /* bool allow globbing for files */

const TYPE_SHORT = 1;
const TYPE_VERBOSE = 2;
const TYPE_SHORT = TypeEnum::SHORT;
const TYPE_VERBOSE = TypeEnum::LONG;
const TYPE_NAMED = 3; // 1|2
const TYPE_ANONYMOUS = 4;
const TYPE_ANONYMOUS = TypeEnum::ARGUMENT;

/**
* @param string|int $name single char name or int index for this option
Expand All @@ -75,10 +76,9 @@ public function __construct($name)
}

if (!is_int($name)) {
$this->type = mb_strlen($name, 'UTF-8') === 1 ?
self::TYPE_SHORT : self::TYPE_VERBOSE;
$this->type = new TypeEnum(mb_strlen($name, 'UTF-8') > 1 ? TypeEnum::LONG : TypeEnum::SHORT);
} else {
$this->type = self::TYPE_ANONYMOUS;
$this->type = new TypeEnum(TypeEnum::ARGUMENT);
}

$this->name = $name;
Expand Down Expand Up @@ -301,7 +301,7 @@ public function getDescription()
*/
public function getType()
{
return $this->type;
return $this->type->value;
}

/**
Expand Down Expand Up @@ -429,15 +429,13 @@ public function getHelp()
$color = new \Colors\Color();
$help = '';

$isNamed = ($this->type & self::TYPE_NAMED);
$isNamed = $this->type->isNamed();

if ($isNamed) {
$help .= PHP_EOL . (mb_strlen($this->name, 'UTF-8') === 1 ?
'-' : '--') . $this->name;
$help .= PHP_EOL . ($this->type->isType(TypeEnum::SHORT) ? '-' : '--') . $this->name;
if (!empty($this->aliases)) {
foreach($this->aliases as $alias) {
$help .= (mb_strlen($alias, 'UTF-8') === 1 ?
'/-' : '/--') . $alias;
$help .= (mb_strlen($alias, 'UTF-8') === 1 ? '/-' : '/--') . $alias;
}
}
if (!$this->isBoolean()) {
Expand Down
48 changes: 48 additions & 0 deletions src/Commando/Option/TypeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* TypeEnum Definition
*
* @package nategood/commando
* @source src/Commando/Option/TypeEnum.php
*/

namespace Commando\Option;

use Commando\Util\Enum;

/**
* Class TypeEnum
*
* Extend dynamic Enum
*/
class TypeEnum extends Enum
{

const SHORT = 1;
const LONG = 2;
const ARGUMENT = 4;

/**
* Convenience method
*
* Check if the instance value is LONG or SHORT
*
* @return boolean
*/
public function isNamed()
{
return static::isValueNamed($this);
}

/**
* Check if the $value is one of LONG or SHORT
*
* @param mixed $value
* @return boolean
*/
public static function isValueNamed($value)
{
return static::isValueType($value, (static::SHORT | static::LONG));
}

}
83 changes: 83 additions & 0 deletions src/Commando/Util/Enum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/**
* Generate base Enum class
*
* @package nategood/commando
* @source src/Commando/Util/Enum.php
*/

namespace Commando\Util;

/**
* Trait EnumUtilitiesTrait
*
* Prevent code duplication when defining our base Enum.
*/
trait EnumUtilitiesTrait
{
/**
* Get value with magic
*
* @method __get
* @param string $name
* @return void
*/
public function __get($name) {
if ($name === 'value') {
return $this->__default;
}
}

/**
* Is the instance value equal to $type?
*
* @param mixed $type
* @return boolean
*/
public function isType($type)
{
return static::isValueType($this, $type);
}

/**
* Is the $value equal to $type?
*
* @param mixed $value
* @param mixed $type
* @return boolean
*/
public static function isValueType($value, $type)
{
$realValue = (int) is_subclass_of($value, "\\Commando\\Util\\Enum") ? static::extractValueFrom($value) : $value;
$realType = (int) is_subclass_of($type, "\\Commando\\Util\\Enum") ? static::extractValueFrom($type) : $type;

return (bool) ($realValue & $realType);
}

/**
* Get value of Enum
*
* @param Enum $value
* @return int
*/
public static function extractValueFrom(Enum $value)
{
return $value->value;
}
}

if (class_exists("\\SplEnum")) {
/**
* Enum extending SPL_TYPES SplEnum
*/
class Enum extends \SplEnum {
use EnumUtilitiesTrait;
}
} else {
/**
* Enum extending ducks-project/spl-types SplEnum
*/
class Enum extends \Ducks\Component\SplTypes\SplEnum {
use EnumUtilitiesTrait;
}
}
63 changes: 63 additions & 0 deletions tests/Commando/TypeEnumTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Commando\Test;

require dirname(dirname(__DIR__)) . '/vendor/autoload.php';

// PHPUnit version hack https://stackoverflow.com/questions/6065730/why-fatal-error-class-phpunit-framework-testcase-not-found-in
if (!class_exists('\PHPUnit_Framework_TestCase') && class_exists('\PHPUnit\Framework\TestCase'))
class_alias('\PHPUnit\Framework\TestCase', '\PHPUnit_Framework_TestCase');

use Commando\Option\TypeEnum;

function errorHandlerFactory(&$caught) {
return function () use (&$caught) {
$caught = true;
return $caught;
};
}

class TypeEnumTest extends \PHPUnit_Framework_TestCase {

function testExtractValueFrom() {
$type = new TypeEnum(TypeEnum::SHORT);
$this->assertEquals(TypeEnum::extractValueFrom($type), TypeEnum::SHORT);
}

function testIsValueType() {
$type1 = new TypeEnum(TypeEnum::SHORT);
$type2 = new TypeEnum(TypeEnum::LONG);
$this->assertFalse(TypeEnum::isValueType(TypeEnum::SHORT, TypeEnum::LONG));
$this->assertFalse(TypeEnum::isValueType($type1, $type2));
$this->assertTrue(TypeEnum::isValueType($type1, TypeEnum::SHORT));
$this->assertTrue(TypeEnum::isValueType(TypeEnum::LONG, $type2));
}

function test__getValue() {
$type = new TypeEnum(TypeEnum::SHORT);
$this->assertEquals($type->value, TypeEnum::SHORT);
}

function testIsType() {
$type = new TypeEnum(TypeEnum::SHORT);
$this->assertTrue($type->isType(TypeEnum::SHORT));
$this->assertFalse($type->isType(new TypeEnum(2))); // TypeEnum::LONG
}

function testIsValueNamed() {
$type = new TypeEnum(TypeEnum::SHORT);
$this->assertTrue(TypeEnum::isValueNamed($type));
$this->assertTrue(TypeEnum::isValueNamed(TypeEnum::LONG));
$this->assertFalse(TypeEnum::isValueNamed(4)); // TypeEnum::ARGUMENT
}

function testIsNamed() {
$type1 = new TypeEnum(TypeEnum::SHORT);
$type2 = new TypeEnum(TypeEnum::LONG);
$type3 = new TypeEnum(TypeEnum::ARGUMENT);
$this->assertTrue($type1->isNamed());
$this->assertTrue($type2->isNamed());
$this->assertFalse($type3->isNamed());
}

}