0) { list($key, $value) = $this->parseArgument($arguments); $this->assign($key, $value); } } /** * Sets the value in the argments object. If multiple * values are added under the same key, the key will * give an array value in the order they were added. * @param string $key The variable to assign to. * @param string value The value that would norally * be colected on the command line. */ function assign($key, $value) { if ($this->$key === false) { $this->all[$key] = $value; } elseif (! is_array($this->$key)) { $this->all[$key] = array($this->$key, $value); } else { $this->all[$key][] = $value; } } /** * Extracts the next key and value from the argument list. * @param array $arguments The remaining arguments to be parsed. * The argument list will be reduced. * @return array Two item array of key and value. * If no value can be found it will * have the value true assigned instead. */ private function parseArgument(&$arguments) { $argument = array_shift($arguments); if (preg_match('/^-(\w)=(.+)$/', $argument, $matches)) { return array($matches[1], $matches[2]); } elseif (preg_match('/^-(\w)$/', $argument, $matches)) { return array($matches[1], $this->nextNonFlagElseTrue($arguments)); } elseif (preg_match('/^--(\w+)=(.+)$/', $argument, $matches)) { return array($matches[1], $matches[2]); } elseif (preg_match('/^--(\w+)$/', $argument, $matches)) { return array($matches[1], $this->nextNonFlagElseTrue($arguments)); } } /** * Attempts to use the next argument as a value. It * won't use what it thinks is a flag. * @param array $arguments Remaining arguments to be parsed. * This variable is modified if there * is a value to be extracted. * @return string/boolean The next value unless it's a flag. */ private function nextNonFlagElseTrue(&$arguments) { return $this->valueIsNext($arguments) ? array_shift($arguments) : true; } /** * Test to see if the next available argument is a valid value. * If it starts with "-" or "--" it's a flag and doesn't count. * @param array $arguments Remaining arguments to be parsed. * Not affected by this call. * boolean True if valid value. */ function valueIsNext($arguments) { return isset($arguments[0]) && ! $this->isFlag($arguments[0]); } /** * It's a flag if it starts with "-" or "--". * @param string $argument Value to be tested. * @return boolean True if it's a flag. */ function isFlag($argument) { return strncmp($argument, '-', 1) == 0; } /** * The arguments are available as individual member * variables on the object. * @param string $key Argument name. * @return string/array/boolean Either false for no value, * the value as a string or * a list of multiple values if * the flag had been specified more * than once. */ function __get($key) { if (isset($this->all[$key])) { return $this->all[$key]; } return false; } /** * The entire argument set as a hash. * @return hash Each argument and it's value(s). */ function all() { return $this->all; } } /** * Renders the help for the command line arguments. * @package SimpleTest * @subpackage UnitTester */ class SimpleHelp { private $overview; private $flag_sets = array(); private $explanations = array(); /** * Sets up the top level explanation for the program. * @param string $overview Summary of program. */ function __construct($overview = '') { $this->overview = $overview; } /** * Adds the explanation for a group of flags that all * have the same function. * @param string/array $flags Flag and alternates. Don't * worry about leading dashes * as these are inserted automatically. * @param string $explanation What that flag group does. */ function explainFlag($flags, $explanation) { $flags = is_array($flags) ? $flags : array($flags); $this->flag_sets[] = $flags; $this->explanations[] = $explanation; } /** * Generates the help text. * @returns string The complete formatted text. */ function render() { $tab_stop = $this->longestFlag($this->flag_sets) + 4; $text = $this->overview . "\n"; for ($i = 0; $i < count($this->flag_sets); $i++) { $text .= $this->renderFlagSet($this->flag_sets[$i], $this->explanations[$i], $tab_stop); } return $this->noDuplicateNewLines($text); } /** * Works out the longest flag for formatting purposes. * @param array $flag_sets The internal flag set list. */ private function longestFlag($flag_sets) { $longest = 0; foreach ($flag_sets as $flags) { foreach ($flags as $flag) { $longest = max($longest, strlen($this->renderFlag($flag))); } } return $longest; } /** * Generates the text for a single flag and it's alternate flags. * @returns string Help text for that flag group. */ private function renderFlagSet($flags, $explanation, $tab_stop) { $flag = array_shift($flags); $text = str_pad($this->renderFlag($flag), $tab_stop, ' ') . $explanation . "\n"; foreach ($flags as $flag) { $text .= ' ' . $this->renderFlag($flag) . "\n"; } return $text; } /** * Generates the flag name including leading dashes. * @param string $flag Just the name. * @returns Fag with apropriate dashes. */ private function renderFlag($flag) { return (strlen($flag) == 1 ? '-' : '--') . $flag; } /** * Converts multiple new lines into a single new line. * Just there to trap accidental duplicate new lines. * @param string $text Text to clean up. * @returns string Text with no blank lines. */ private function noDuplicateNewLines($text) { return preg_replace('/(\n+)/', "\n", $text); } } ?>