diff --git a/src/Commando/Command.php b/src/Commando/Command.php index 40a5829..21fafcc 100755 --- a/src/Commando/Command.php +++ b/src/Commando/Command.php @@ -70,6 +70,7 @@ class Command implements \ArrayAccess, \Iterator // mustBeNumeric // mustBeInt // mustBeFloat + 'needs' => 'needs', 'file' => 'file', 'expectsFile' => 'file', @@ -205,6 +206,18 @@ private function _require(Option $option, $require = true) return $option->setRequired($require); } + /** + * Set a requirement on an option + * + * @param \Commando\Option $option Current option + * @param string $name Name of option + * @return \Commando\Option instance + */ + private function _needs(Option $option, $name) + { + return $option->setNeeds($name); + } + /** * @param Option $option * @param string $alias @@ -353,6 +366,17 @@ public function parse() } } } + + // See if our options have what they require + foreach ($this->options as $option) { + $needs = $option->hasNeeds($this->options); + if ($needs !== true) { + throw new \InvalidArgumentException( + 'Option "'.$option->getName().'" does not have required option(s): '.implode(', ', $needs) + ); + } + } + // Set values (validates and performs map when applicable) foreach ($keyvals as $key => $value) { diff --git a/src/Commando/Option.php b/src/Commando/Option.php index 9832226..5c1baa5 100755 --- a/src/Commando/Option.php +++ b/src/Commando/Option.php @@ -11,6 +11,7 @@ class Option $value = null, /* mixed */ $description, /* string */ $required = false, /* bool */ + $needs = array(), /* set of other required options for this option */ $boolean = false, /* bool */ $type = 0, /* int see constants */ $rule, /* closure */ @@ -119,6 +120,22 @@ public function setRequired($bool = true) return $this; } + /** + * Set an option as required + * + * @param string $option Option name + */ + public function setNeeds($option) + { + if (!is_array($option)) { + $option = array($option); + } + foreach ($option as $opt) { + $this->needs[] = $opt; + } + return $this; + } + /** * @param mixed $value default value * @return Option @@ -241,6 +258,15 @@ public function getAliases() return $this->aliases; } + /** + * Get the current set of this option's requirements + * @return array List of required options + */ + public function getNeeds() + { + return $this->needs; + } + /** * @return bool is this option a boolean */ @@ -266,6 +292,27 @@ public function isRequired() return $this->required; } + /** + * Check to see if requirements list for option are met + * + * @param array $optionsList Set of current options defined + * @return boolean|array True if requirements met, array if not found + */ + public function hasNeeds($optionsList) + { + $needs = $this->getNeeds(); + + $definedOptions = array_keys($optionsList); + $notFound = array(); + foreach ($needs as $need) { + if (!in_array($need, $definedOptions)) { + $notFound[] = $need; + } + } + return (empty($notFound)) ? true : $notFound; + + } + /** * @param mixed value for this option (set on the command line) */ diff --git a/tests/Commando/CommandTest.php b/tests/Commando/CommandTest.php index 0ab15db..08851ce 100755 --- a/tests/Commando/CommandTest.php +++ b/tests/Commando/CommandTest.php @@ -152,4 +152,34 @@ public function testGetValues() $this->assertEquals(array('a' => 'v1', 'b' => 'v2'), $cmd->getFlagValues()); } + /** + * Ensure that requirements are resolved correctly + */ + public function testRequirementsOnOptionsValid() + { + $tokens = array('filename', '-a', 'v1', '-b', 'v2'); + $cmd = new Command($tokens); + + $cmd->option('b'); + $cmd->option('a') + ->needs('b'); + + $this->assertEquals($cmd['a'], 'v1'); + } + + /** + * Test that an exception is thrown when an option isn't set + * @expectedException \InvalidArgumentException + */ + public function testRequirementsOnOptionsMissing() + { + $tokens = array('filename', '-a', 'v1'); + $cmd = new Command($tokens); + + $cmd->trapErrors(false) + ->beepOnError(false); + $cmd->option('a') + ->needs('b'); + } + } \ No newline at end of file diff --git a/tests/Commando/OptionTest.php b/tests/Commando/OptionTest.php index 8eddb47..a04b9e3 100644 --- a/tests/Commando/OptionTest.php +++ b/tests/Commando/OptionTest.php @@ -131,6 +131,31 @@ public function testDefault($val) $this->assertEquals($val, $option->getValue()); } + /** + * Test that requires options are set correctly + */ + public function testSetRequired() + { + $option = new Option('f'); + $option->setNeeds('foo'); + + $this->assertTrue(in_array('foo', $option->getNeeds())); + } + + /** + * Test that the needed requirements are met + */ + public function testOptionRequirementsMet() + { + $option = new Option('f'); + $option->setNeeds('foo'); + $optionSet = array( + 'foo' => new Option('foo') + ); + + $this->assertTrue($option->hasNeeds($optionSet)); + } + // Providers public function values()