<?php /** * Get Options Class * Pure PHP OOP implementation of getopt * @author chris@fuelforthefire.ca * @copyright Fuel for the Fire * @version 0.2 * @date 2013-06-17 */ /** * Get Options * Recieves array of arguments and evaluates them * @name GetOpts * @package cli */ class GetOpts { /** * Arguments * internal storage of the arguments to parse * @var array * @access private */ private $aArgs; /** * Return Unknown Flag * If set unknown options will be returned as '?' * @var bool * @access private */ private $bShowUnknown; /** * Argument Count * The number of arguments passed to the class * @var integer * @access private */ private $iArgCnt; /** * Argument Index * last index in the argument array we looked at * @var int * @access private */ private $iArgIndex; /** * Options * an array of acceptable short options (-o) * @var array * @access private */ private $aOptions; /** * Long Options * an array of acceptable long options (--option) * @var mixed */ private $aLongOpts; /** * Constructor * Sets up the arguments to be evaluated * @name GetOpts * @param array $in_arguments Arguments to evaluate * @param string $in_options Options to look for * @param string $in_longopts Long options to look for * @param bool $in_return_unknown Should we return unknown arguments? * @return GetOpts */ public function __construct(array $in_arguments, /*string*/ $in_options, array $in_longopts = array(), /*bool*/ $in_return_unknown = false) { // Store and count arguments $this->aArgs = $in_arguments; $this->iArgCnt = count($this->aArgs); // Init last index $this->iArgIndex = null; // Store short and long options $this->aOptions = array(); $this->aLongOpts = array(); $this->parseOptions($in_options, $in_longopts); // Check for unknown arguments? $this->bShowUnknown = $in_return_unknown; } /** * Next Option * returns the next option in the list of arguments * @name next * @access public * @return array|false 0 => option, 1 => value */ public function next() { // Check if we've run before if(is_null($this->iArgIndex)) { // Skip the first argument if it's the name of the current script $this->iArgIndex = (isset($_SERVER['argv'][0]) && $_SERVER['argv'][0] == $_SERVER['SCRIPT_NAME']) ? 0 : -1; } // Check if we're done if(++$this->iArgIndex >= $this->iArgCnt) { return null; } // Check if it's a long option if($this->aArgs[$this->iArgIndex]{0} == '-' && $this->aArgs[$this->iArgIndex]{1} == '-') { // If there's an equal sign in the argument if($iPos = strpos($this->aArgs[$this->iArgIndex], '=')) { $sArg = substr($this->aArgs[$this->iArgIndex], 2, ($iPos-2)); $sVal = substr($this->aArgs[$this->iArgIndex], $iPos+1); } else { $sArg = substr($this->aArgs[$this->iArgIndex], 2); $sVal = null; } // Is it in the approved list if(isset($this->aLongOpts[$sArg])) { // Does the option have an optional parameter? if($this->aLongOpts[$sArg]) { // If we already have it if(!is_null($sVal)) { return array($sArg, $sVal); } else { return array($sArg, $this->aArgs[++$this->iArgIndex]); } } else { return array($sArg, false); } } else { // If we're allowed to show unknowns if($this->bShowUnknown) { return array('?', $this->aArgs[$this->iArgIndex]); } // Else try to get the next option else { return $this->next(); } } } // Check that the first character of the argument is '-' or '/' else if(in_array($this->aArgs[$this->iArgIndex]{0}, array('-', '/'))) { // Store the argument $sArg = $this->aArgs[$this->iArgIndex]{1}; // We have an option, is it in the approved list? if(isset($this->aOptions[$sArg])) { // Does the option have an optional parameter? if($this->aOptions[$sArg]) { // The argument does not contain the value, so get it from the next argument if(strlen($this->aArgs[$this->iArgIndex]) == 2) { return array($sArg, $this->aArgs[++$this->iArgIndex]); } // Else, pull out the value from the argument else { return array($sArg, substr($this->aArgs[$this->iArgIndex], 2)); } } // Else it's set or not set else { return array($sArg, false); } } else { // If we're allowed to show unknowns if($this->bShowUnknown) { return array('?', $this->aArgs[$this->iArgIndex]); } // Else try to get the next option else { return $this->next(); } } } else { // If we're allowed to show unknowns if($this->bShowUnknown) { return array('?', $this->aArgs[$this->iArgIndex]); } // Else try to get the next option else { return $this->next(); } } } /** * Parse Options * parses the options passed to the class into an array and stores them locally * @name parseOptions * @access private * @param string $in_options The options passed to the class * @param array $in_longopts The long options passed to the class * @return void */ private function parseOptions(/*string*/ $in_options, array $in_longopts) { // Parse the short options $aOpts = str_split($in_options); $iCnt = count($aOpts); for($i = 0; $i < $iCnt; ++$i) { // If the option needs an argument if($aOpts[$i+1] == ':') { $this->aOptions[$aOpts[$i]] = true; ++$i; } else { $this->aOptions[$aOpts[$i]] = false; } } // Parse the long options foreach($in_longopts as $sOpt) { // Get the length of the string $iLen = strlen($sOpt); // If the option needs an argument if(':' == $sOpt[$iLen-1]) { $this->aLongOpts[substr($sOpt, 0, -1)] = true; } else{ $this->aLongOpts[$sOpt] = false; } } } }