/** * Parse command line arguments. * * Arguments may be provided as an array similar to the PHP global * variable "$_SERVER['argv']", as a string or as null in which case * it will default to "$_SERVER['argv']". * * @param mixed (array, string or null) $arguments [optional] Arguments to extract * @param array $options [optional] Optional configuration * @return array Arguments array */ public static function toArray($arguments=null,$options=array()){ switch(gettype($arguments)){ case 'array': // ok break; case 'string': // Note about php parsing // - include script name // eg: php pur.php will have "pur.php" as first element // - same behavior between single and double quotes // eg: 'my test' is identical to "my test" // - two following quotes will be merge as a single element // eg: "'my '' test'" convert to "my test" // - quoted text following word will be merged as a single element // eg: "'my 'test" convert to "my test" // - quoted text covering a section of the word is interpreted as well // eg: "my'quoted test'" convert to "myquoted text" // Lexer implementation // $arguments = explode(' ',$arguments); // break; $a = $arguments.' '; $arguments = array(); $w = ''; $l = strlen($a); $i = 0; $q = false; for($i;$i<$l;$i++){ $c = $a[$i]; if($c===$q){ $q = false; }else if($c==='"'||$c==="'"){ $q = $c; }else if((!$q&&$c===' ')){ if($w!==''){ $arguments[] = $w; $w = ''; } }else{ $w .= $c; } } break; case 'NULL': // Note about php parsing // - equal sign is treated as a regular sign $arguments = $_SERVER['argv']; break; default: throw new InvalidArgumentException('First argument "arguments" is expected to be a string, an array or null'); } $return = array(); $previousKey = null; $currentKey = null; $index = 0; while(($argument = array_shift($arguments))!==null){ //$quoted = is_int(strpbrk($argument,' "\'')); $flush = false; $value = null; // Named param key if(substr($argument,0,2)=='--'){ // boolean don't have value and are treated instantly $currentKey = substr($argument,2); if(substr($currentKey,-1)=='='){ $currentKey = substr($currentKey,0,-1); } // Deal with alias if(isset($options['map'][$currentKey])&&is_string($options['map'][$currentKey])){ $currentKey = $options['map'][$currentKey]; } if(isset($options['map'][$currentKey]['type'])&&$options['map'][$currentKey]['type']=='boolean'){ $previousKey = null; $value = true; }else{ $previousKey = $currentKey; $currentKey = null; } // Shortcut param key }else if(substr($argument,0,1)=='-'){ // Deal with shortcut not associated to named param $k = substr($argument,1); if(strlen($k)>1){ if($k[1]=='='){ $value = trim(substr($k,2)); if(empty($value)&&!empty($arguments[0])&&substr($arguments[0],0,1)!='-'){ $value = array_shift($arguments); } }else{ array_unshift($arguments,'-'.substr($k,1)); } $k = $k[0]; // for($i=1;$i<strlen($k);$i++){ // array_unshift($arguments,'-'.$k[$i]); // } } if(!isset($options['map'][$k])||!is_string($options['map'][$k])){ switch(isset($options['strict'])){ case true: throw new UnexpectedValueException('Shortcut "'.$k.'" not associated to a named parameter'); case false: $currentKey = null; } }else{ $currentKey = $options['map'][$k]; // value may be set earlier like in -ab=c where b has the value c if($value===null){ $value = true; }else if(is_string($value)){ // Make sure their is no confict type is string value if(isset($options['map'][$currentKey]['type'])&&$options['map'][$currentKey]['type']!='string'){ switch(isset($options['strict'])){ case true: throw new UnexpectedValueException('Shortcut "'.$k.'" for "'.$currentKey.'" associated to a named parameter of type "'.$options['map'][$currentKey]['type'].'" instead of "string"'); case false: $currentKey = null; $value = false; } } } } // Indexed param key }else if($previousKey===null){ // Index is mapped to named param if(($pos = strpos($argument,'='))!==false){ $currentKey = substr($argument,0,$pos); $value = substr($argument,$pos+1); if($value==''){ $value = true; } }else{ if(isset($options['map'][$index])){ $currentKey = $options['map'][$index]; }else{ $currentKey = $index; } $index++; $value = $argument; } // A value }else{ $currentKey = $previousKey; $previousKey = null; $value = $argument; } if(!is_null($currentKey)){ if(isset($options['map'][$currentKey]['type'])){ switch($options['map'][$currentKey]['type']){ case 'boolean': $value = (boolean) $value; break; case 'double': $value = (double) $value; break; case 'int': $value = (int) $value; break; case 'float': $value = (float) $value; break; case 'string': break; default: throw new InvalidArgumentException('Invalid option type for mapped key "'.$currentKey.'"'); } } $return[$currentKey] = $value; $previousKey = $currentKey = null; }else{ //echo 'yo'; //$previousKey = $currentKey; } } return empty($options['flatten'])?PurProperties::propertiesToArray($return):$return; }
/** * Retrieve functions arguments with complex and multiple combinations. * * The first argument are the arguments to retrieve. For exemple, they * may be obtained with the "func_get_args" function or through the second * argument of the PHP magick "__call" method. * * The second argument is a list of all the possible func_get_args. Each * combination is structure as an associative array where keys represent * the PHP type of argument (using "" or "mixed" for all) and the value is the key name * used in the returned array to access the matching argument. * * If no match are found, an exception of type "InvalidArgumentException" is thrown. * * PurLang::args( * func_get_args(), * array( * array("my_param_1"=>array("string","array")), * array("my_param_1"=>"mixed","my_param_array.my_param_key"=>"string", * array("my_param_1"=>"my_param_1","my_param_array"=>"array")); * * @param array $args Arguments to retrieve * @param array $structure List of combinations * @return array Associative array of arguemnts */ public static function args(array $args,array $structure){ $count = count($args); foreach($structure as $combination){ if($count!==count($combination)){ continue; } if($count===0){ return array(); } $combination = array_reverse($combination); $i = $count-1; foreach($combination as $key=>$type){ if($type!=''&&$type!='mixed'&& ((is_string($type)&&gettype($args[$i])!=$type) || ((is_array($type)&&!in_array(gettype($args[$i]),$type))))){ continue 2; } if(empty($key)){ } $i--; } $keys = array(); foreach($combination as $key=>$type){ if(empty($key)){ $keys[] = '_'; }else{ $keys[] = '_.'.$key; } } $result = PurProperties::propertiesToArray(array_combine($keys,array_reverse($args))); return array_reverse($result['_']); } throw new InvalidArgumentException('Unexpected arguments: "'.self::toString($args).'"'); }