mambax7 /
extgallery
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
|||||||||||
| 2 | ||||||||||||
| 3 | /** |
|||||||||||
| 4 | * Console Getopt |
|||||||||||
| 5 | * |
|||||||||||
| 6 | * All rights reserved. |
|||||||||||
| 7 | * Redistribution and use in source and binary forms, with or without modification, |
|||||||||||
| 8 | * are permitted provided that the following conditions are met: |
|||||||||||
| 9 | * + Redistributions of source code must retain the above copyright notice, |
|||||||||||
| 10 | * this list of conditions and the following disclaimer. |
|||||||||||
| 11 | * + Redistributions in binary form must reproduce the above copyright notice, |
|||||||||||
| 12 | * this list of conditions and the following disclaimer in the documentation and/or |
|||||||||||
| 13 | * other materials provided with the distribution. |
|||||||||||
| 14 | * + The names of its contributors may not be used to endorse or promote |
|||||||||||
| 15 | * products derived from this software without specific prior written permission. |
|||||||||||
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||||||||||
| 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||||||||||
| 18 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||||||||||
| 19 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|||||||||||
| 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|||||||||||
| 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|||||||||||
| 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|||||||||||
| 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|||||||||||
| 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|||||||||||
| 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||||||||||
| 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||||||||||
| 27 | * |
|||||||||||
| 28 | * @category Console |
|||||||||||
| 29 | * @package Console_GetoptPlus |
|||||||||||
| 30 | * @author Michel Corne <[email protected]> |
|||||||||||
| 31 | * @copyright 2008 Michel Corne |
|||||||||||
| 32 | * @license http://www.opensource.org/licenses/bsd-license.php The BSD License |
|||||||||||
| 33 | * @version SVN: $Id: Getopt.php 48 2008-01-10 15:32:56Z mcorne $ |
|||||||||||
| 34 | * @link http://pear.php.net/package/Console_GetoptPlus |
|||||||||||
| 35 | */ |
|||||||||||
| 36 | ||||||||||||
| 37 | require_once 'Console/GetoptPlus/Exception.php'; |
|||||||||||
| 38 | require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/PEAR.php'; |
|||||||||||
| 39 | ||||||||||||
| 40 | /** |
|||||||||||
| 41 | * Parsing of a command line. |
|||||||||||
| 42 | * |
|||||||||||
| 43 | * See more examples in docs/examples. |
|||||||||||
| 44 | * |
|||||||||||
| 45 | * Code Example 1: |
|||||||||||
| 46 | * <code> |
|||||||||||
| 47 | * require_once 'Console/GetoptPlus.php'; |
|||||||||||
| 48 | * |
|||||||||||
| 49 | * try { |
|||||||||||
| 50 | * $shortOptions = "b:c::"; |
|||||||||||
| 51 | * $longOptions = array("foo", "bar="); |
|||||||||||
| 52 | * $options = Console_Getoptplus::getopt($config, $shortOptions, $longOptions); |
|||||||||||
| 53 | * // some processing here... |
|||||||||||
| 54 | * print_r($options); |
|||||||||||
| 55 | * } |
|||||||||||
| 56 | * catch(Console_GetoptPlus_Exception $e) { |
|||||||||||
| 57 | * $error = array($e->getCode(), $e->getMessage()); |
|||||||||||
| 58 | * print_r($error); |
|||||||||||
| 59 | * } |
|||||||||||
| 60 | * </code> |
|||||||||||
| 61 | * |
|||||||||||
| 62 | * Code Example 2: |
|||||||||||
| 63 | * <code> |
|||||||||||
| 64 | * require_once 'Console/GetoptPlus/Getopt.php'; |
|||||||||||
| 65 | * |
|||||||||||
| 66 | * try { |
|||||||||||
| 67 | * $shortOptions = "b:c::"; |
|||||||||||
| 68 | * $longOptions = array("foo", "bar="); |
|||||||||||
| 69 | * $options = Console_GetoptPlus_Getopt::getopt($config, $shortOptions, $longOptions); |
|||||||||||
| 70 | * // some processing here... |
|||||||||||
| 71 | * print_r($options); |
|||||||||||
| 72 | * } |
|||||||||||
| 73 | * catch(Console_GetoptPlus_Exception $e) { |
|||||||||||
| 74 | * $error = array($e->getCode(), $e->getMessage()); |
|||||||||||
| 75 | * print_r($error); |
|||||||||||
| 76 | * } |
|||||||||||
| 77 | * </code> |
|||||||||||
| 78 | * |
|||||||||||
| 79 | * Run: |
|||||||||||
| 80 | * <pre> |
|||||||||||
| 81 | * #xyz --foo -b car -c |
|||||||||||
| 82 | * #xyz --foo -b car -c param1 |
|||||||||||
| 83 | * #xyz --foo -b car -cbus param1 |
|||||||||||
| 84 | * #xyz --foo -b car -c=bus param1 |
|||||||||||
| 85 | * #xyz --bar car param1 param2 |
|||||||||||
| 86 | * #xyz --bar car -- param1 param2 |
|||||||||||
| 87 | * #xyz --bar=car param1 param2 |
|||||||||||
| 88 | * </pre> |
|||||||||||
| 89 | * |
|||||||||||
| 90 | * @category Console |
|||||||||||
| 91 | * @package Console_GetoptPlus |
|||||||||||
| 92 | * @author Michel Corne <[email protected]> |
|||||||||||
| 93 | * @copyright 2008 Michel Corne |
|||||||||||
| 94 | * @license http://www.opensource.org/licenses/bsd-license.php The BSD License |
|||||||||||
| 95 | * @version Release: |
|||||||||||
| 96 | * @package _version@ |
|||||||||||
| 97 | * @link http://pear.php.net/package/Console_GetoptPlus |
|||||||||||
| 98 | * @see Console_Getopt |
|||||||||||
| 99 | */ |
|||||||||||
| 100 | class Console_GetoptPlus_Getopt |
|||||||||||
| 101 | { |
|||||||||||
| 102 | /** |
|||||||||||
| 103 | * The list of ambigous option names |
|||||||||||
| 104 | * |
|||||||||||
| 105 | * @var array |
|||||||||||
| 106 | * @access private |
|||||||||||
| 107 | */ |
|||||||||||
| 108 | private $ambigous; |
|||||||||||
| 109 | ||||||||||||
| 110 | /** |
|||||||||||
| 111 | * The command arguments |
|||||||||||
| 112 | * |
|||||||||||
| 113 | * @var array |
|||||||||||
| 114 | * @access private |
|||||||||||
| 115 | */ |
|||||||||||
| 116 | private $args; |
|||||||||||
| 117 | ||||||||||||
| 118 | /** |
|||||||||||
| 119 | * The long option names |
|||||||||||
| 120 | * |
|||||||||||
| 121 | * @var array |
|||||||||||
| 122 | * @access private |
|||||||||||
| 123 | */ |
|||||||||||
| 124 | private $longOptionsDef; |
|||||||||||
| 125 | ||||||||||||
| 126 | /** |
|||||||||||
| 127 | * The parsed options |
|||||||||||
| 128 | * |
|||||||||||
| 129 | * @var array |
|||||||||||
| 130 | * @access private |
|||||||||||
| 131 | */ |
|||||||||||
| 132 | private $options; |
|||||||||||
| 133 | ||||||||||||
| 134 | /** |
|||||||||||
| 135 | * The option shortcut names |
|||||||||||
| 136 | * |
|||||||||||
| 137 | * @var array |
|||||||||||
| 138 | * @access private |
|||||||||||
| 139 | */ |
|||||||||||
| 140 | private $shortcuts; |
|||||||||||
| 141 | ||||||||||||
| 142 | /** |
|||||||||||
| 143 | * The short option names and their definition |
|||||||||||
| 144 | * |
|||||||||||
| 145 | * @var array |
|||||||||||
| 146 | * @access private |
|||||||||||
| 147 | */ |
|||||||||||
| 148 | private $shortOptionsDef; |
|||||||||||
| 149 | ||||||||||||
| 150 | /** |
|||||||||||
| 151 | * The option types |
|||||||||||
| 152 | * |
|||||||||||
| 153 | * @var array |
|||||||||||
| 154 | * @access private |
|||||||||||
| 155 | */ |
|||||||||||
| 156 | private $type = array(// / |
|||||||||||
| 157 | false => 'noarg', |
|||||||||||
| 158 | '=' => 'mandatory', |
|||||||||||
| 159 | ':' => 'mandatory', |
|||||||||||
| 160 | '==' => 'optional', |
|||||||||||
| 161 | '::' => 'optional', |
|||||||||||
| 162 | ); |
|||||||||||
| 163 | ||||||||||||
| 164 | /** |
|||||||||||
| 165 | * Creates the option shorcut names |
|||||||||||
| 166 | * |
|||||||||||
| 167 | * @param array $longOptionsDef the long option names |
|||||||||||
| 168 | * @param string $ambiguity directive to handle option names ambiguity |
|||||||||||
| 169 | * @return array the option shorcuts and the ambigous options |
|||||||||||
| 170 | * @access public |
|||||||||||
| 171 | */ |
|||||||||||
| 172 | public function createShorcuts($longOptionsDef, $ambiguity) |
|||||||||||
| 173 | { |
|||||||||||
| 174 | $shortcuts = array(); |
|||||||||||
| 175 | $ambigous = array(); |
|||||||||||
| 176 | ||||||||||||
| 177 | if ('shortcuts' == $ambiguity) { |
|||||||||||
| 178 | foreach (array_keys($longOptionsDef) as $name) { |
|||||||||||
| 179 | // splits the option name in characters to build the name |
|||||||||||
| 180 | // substring combinations, e.g. foo => f, fo, foo |
|||||||||||
| 181 | $subName = ''; |
|||||||||||
| 182 | foreach (str_split($name) as $char) { |
|||||||||||
| 183 | $subName .= $char; |
|||||||||||
| 184 | ||||||||||||
| 185 | if (isset($ambigous[$subName])) { |
|||||||||||
| 186 | // adds the shortcut to the list of ambigous shortcuts |
|||||||||||
| 187 | $ambigous[$subName][] = $name; |
|||||||||||
| 188 | } elseif (isset($shortcuts[$subName])) { |
|||||||||||
| 189 | // there is already a shortcut, adds the previous one |
|||||||||||
| 190 | // and the current one in the list of ambigous shortcuts |
|||||||||||
| 191 | $ambigous[$subName] = array($shortcuts[$subName], $name); |
|||||||||||
| 192 | unset($shortcuts[$subName]); |
|||||||||||
| 193 | } else { |
|||||||||||
| 194 | // creates the shorcut entry |
|||||||||||
| 195 | $shortcuts[$subName] = $name; |
|||||||||||
| 196 | } |
|||||||||||
| 197 | } |
|||||||||||
| 198 | } |
|||||||||||
| 199 | // checks if some options are ambigous, e.g. --foo --foobar |
|||||||||||
| 200 | $names = array_intersect_key($longOptionsDef, $ambigous) and self::exception('ambigous', key($names)); |
|||||||||||
| 201 | } |
|||||||||||
| 202 | ||||||||||||
| 203 | return array($shortcuts, $ambigous); |
|||||||||||
| 204 | } |
|||||||||||
| 205 | ||||||||||||
| 206 | /** |
|||||||||||
| 207 | * Parses the command line |
|||||||||||
| 208 | * |
|||||||||||
| 209 | * See getopt() for a complete description. |
|||||||||||
| 210 | * |
|||||||||||
| 211 | * @param numeric $version the getopt version: 1 or 2 |
|||||||||||
| 212 | * @param array $args the arguments |
|||||||||||
| 213 | * @param string $shortOptions the short options definition, e.g. "ab:c::" |
|||||||||||
| 214 | * @param array $longOptions the long options definition |
|||||||||||
| 215 | * @param string $ambiguity directive to handle option names ambiguity |
|||||||||||
| 216 | * @return array the parsed options, their arguments and parameters |
|||||||||||
| 217 | * @access public |
|||||||||||
| 218 | * @static |
|||||||||||
| 219 | */ |
|||||||||||
| 220 | public static function doGetopt( |
|||||||||||
| 221 | $version = null, |
|||||||||||
| 222 | $args = array(), |
|||||||||||
| 223 | $shortOptions = '', |
|||||||||||
| 224 | $longOptions = array(), |
|||||||||||
| 225 | $ambiguity = '' |
|||||||||||
| 226 | ) { |
|||||||||||
| 227 | $getopt = new self; |
|||||||||||
| 228 | ||||||||||||
| 229 | return $getopt->process($args, $shortOptions, $longOptions, $ambiguity, $version); |
|||||||||||
| 230 | } |
|||||||||||
| 231 | ||||||||||||
| 232 | /** |
|||||||||||
| 233 | * Wraps the exception call |
|||||||||||
| 234 | * |
|||||||||||
| 235 | * @return void |
|||||||||||
| 236 | * @access private |
|||||||||||
| 237 | * @throws Console_GetoptPlus_Exception Exception |
|||||||||||
| 238 | * @static |
|||||||||||
| 239 | */ |
|||||||||||
| 240 | private static function exception() |
|||||||||||
| 241 | { |
|||||||||||
| 242 | $error = func_get_args(); |
|||||||||||
| 243 | throw new Console_GetoptPlus_Exception($error); |
|||||||||||
| 244 | } |
|||||||||||
| 245 | ||||||||||||
| 246 | /** |
|||||||||||
| 247 | * Parses the command line |
|||||||||||
| 248 | * |
|||||||||||
| 249 | * See the definition/example in the class Doc Block. |
|||||||||||
| 250 | * |
|||||||||||
| 251 | * Example: returning an index array |
|||||||||||
| 252 | * <code> |
|||||||||||
| 253 | * array( |
|||||||||||
| 254 | * [0] => array("foo" => null, "bar" => "car", "c" => null), |
|||||||||||
| 255 | * [1] => array([0] => "param1", [1] => "param2") |
|||||||||||
| 256 | * ); |
|||||||||||
| 257 | * </code> |
|||||||||||
| 258 | * |
|||||||||||
| 259 | * @param array $args the arguments |
|||||||||||
| 260 | * @param string $shortOptions the short options definition, e.g. "ab:c::" |
|||||||||||
| 261 | * <ul> |
|||||||||||
| 262 | * <li>":" : the option requires an argument</li> |
|||||||||||
| 263 | * <li>"::" : the option accepts an optional argument</li> |
|||||||||||
| 264 | * <li>otherwise the option accepts no argument</li> |
|||||||||||
| 265 | * </ul> |
|||||||||||
| 266 | * @param array $longOptions the long options definition, |
|||||||||||
| 267 | * e.g. array("art", "bar=", "car==) |
|||||||||||
| 268 | * <ul> |
|||||||||||
| 269 | * <li>"=" : the option requires an argument</li> |
|||||||||||
| 270 | * <li>"==" : the option accepts an optional argument</li> |
|||||||||||
| 271 | * <li>otherwise the option accepts no argument</li> |
|||||||||||
| 272 | * </ul> |
|||||||||||
| 273 | * @param string $ambiguity directive to handle option names ambiguity, |
|||||||||||
| 274 | * e.g. "--foo" and "--foobar": |
|||||||||||
| 275 | * <ul> |
|||||||||||
| 276 | * <li>"loose": allowed if "--foo" does not |
|||||||||||
| 277 | * accept an argument, this is the default |
|||||||||||
| 278 | * behaviour</li> |
|||||||||||
| 279 | * <li>"strict": no ambiguity allowed</li> |
|||||||||||
| 280 | * <li>"shortcuts": implies "strict", the use of |
|||||||||||
| 281 | * partial option names is allowed, |
|||||||||||
| 282 | * e.g. "--f" or "--fo" instead of "--foo"</li> |
|||||||||||
| 283 | * </ul> |
|||||||||||
| 284 | * @return array the parsed options, their arguments and parameters |
|||||||||||
| 285 | * @access public |
|||||||||||
| 286 | * @static |
|||||||||||
| 287 | */ |
|||||||||||
| 288 | public static function getopt( |
|||||||||||
| 289 | $args = array(), |
|||||||||||
| 290 | $shortOptions = '', |
|||||||||||
| 291 | $longOptions = array(), |
|||||||||||
| 292 | $ambiguity = '' |
|||||||||||
| 293 | ) { |
|||||||||||
| 294 | return self::doGetopt(1, $args, $shortOptions, $longOptions, $ambiguity); |
|||||||||||
| 295 | } |
|||||||||||
| 296 | ||||||||||||
| 297 | /** |
|||||||||||
| 298 | * Parses the command line |
|||||||||||
| 299 | * |
|||||||||||
| 300 | * See getopt() for a complete description. |
|||||||||||
| 301 | * |
|||||||||||
| 302 | * @param array $args the arguments |
|||||||||||
| 303 | * @param string $shortOptions the short options definition, e.g. "ab:c::" |
|||||||||||
| 304 | * @param array $longOptions the long options definition |
|||||||||||
| 305 | * @param string $ambiguity directive to handle option names ambiguity |
|||||||||||
| 306 | * @return array the parsed options, their arguments and parameters |
|||||||||||
| 307 | * @access public |
|||||||||||
| 308 | * @static |
|||||||||||
| 309 | */ |
|||||||||||
| 310 | public static function getopt2( |
|||||||||||
| 311 | $args = array(), |
|||||||||||
| 312 | $shortOptions = '', |
|||||||||||
| 313 | $longOptions = array(), |
|||||||||||
| 314 | $ambiguity = '' |
|||||||||||
| 315 | ) { |
|||||||||||
| 316 | return self::doGetopt(2, $args, $shortOptions, $longOptions, $ambiguity); |
|||||||||||
| 317 | } |
|||||||||||
| 318 | ||||||||||||
| 319 | /** |
|||||||||||
| 320 | * Checks if the argument is an option |
|||||||||||
| 321 | * |
|||||||||||
| 322 | * @param string $argument the argument, e.g. "-f" or "--foo" |
|||||||||||
| 323 | * @return boolean true if an option, false otherwise |
|||||||||||
| 324 | * @access public |
|||||||||||
| 325 | */ |
|||||||||||
| 326 | public function isOption($argument) |
|||||||||||
| 327 | { |
|||||||||||
| 328 | return (bool)preg_match('~^(-\w|--\w+)$~', $argument); |
|||||||||||
| 329 | } |
|||||||||||
| 330 | ||||||||||||
| 331 | /** |
|||||||||||
| 332 | * Parses a long option |
|||||||||||
| 333 | * |
|||||||||||
| 334 | * @param string $argument the option and argument (excluding the "--" prefix), |
|||||||||||
| 335 | * e.g. "file=foo.php", "file foo.php", "bar" |
|||||||||||
| 336 | * @return void |
|||||||||||
| 337 | * @access public |
|||||||||||
| 338 | */ |
|||||||||||
| 339 | public function parseLongOption($argument) |
|||||||||||
| 340 | { |
|||||||||||
| 341 | $option = explode('=', $argument, 2); |
|||||||||||
| 342 | $name = current($option); |
|||||||||||
| 343 | $arg = next($option) or $arg = null; |
|||||||||||
| 344 | // verifies the option is valid |
|||||||||||
| 345 | isset($this->ambigous[$name]) and self::exception('ambigous', $name); |
|||||||||||
| 346 | isset($this->shortcuts[$name]) and $name = $this->shortcuts[$name] or isset($this->longOptionsDef[$name]) or self::exception('unrecognized', $name); |
|||||||||||
| 347 | ||||||||||||
| 348 | if ('mandatory' == $this->longOptionsDef[$name]) { |
|||||||||||
| 349 | // the option requires an argument, e.g. --file=foo.php |
|||||||||||
| 350 | // tries the next argument if necessary, e.g. --file foo.php |
|||||||||||
| 351 | is_null($arg) and list(, $arg) = each($this->args); |
|||||||||||
| 352 | is_null($arg) and self::exception('mandatory', $name); |
|||||||||||
| 353 | // verifies the argument is not an option itself |
|||||||||||
| 354 | $this->isOption($arg) and self::exception('mandatory', $name); |
|||||||||||
| 355 | } elseif ('noarg' == $this->longOptionsDef[$name] and !is_null($arg)) { |
|||||||||||
|
0 ignored issues
–
show
|
||||||||||||
| 356 | // the option may not take an optional argument |
|||||||||||
| 357 | self::exception('noargument', $name); |
|||||||||||
| 358 | } |
|||||||||||
| 359 | // capture the option and its argument |
|||||||||||
| 360 | $this->options[] = array('--' . $name, $arg); |
|||||||||||
| 361 | } |
|||||||||||
| 362 | ||||||||||||
| 363 | /** |
|||||||||||
| 364 | * Parses the long option names and types |
|||||||||||
| 365 | * |
|||||||||||
| 366 | * @param array $options the long options, e.g. array("foo", "bar=") |
|||||||||||
| 367 | * @return array the options name and type, |
|||||||||||
| 368 | * e.g. array("foo"=>"noarg", "bar"=>"mandatory") |
|||||||||||
| 369 | * @access public |
|||||||||||
| 370 | */ |
|||||||||||
| 371 | public function parseLongOptionsDef($options) |
|||||||||||
| 372 | { |
|||||||||||
| 373 | // converts to an array if there is only one option |
|||||||||||
| 374 | settype($options, 'array'); |
|||||||||||
| 375 | ||||||||||||
| 376 | $longOptionsDef = array(); |
|||||||||||
| 377 | foreach ($options as $option) { |
|||||||||||
| 378 | if ($option = trim($option)) { |
|||||||||||
| 379 | // extracts the option name and type: |
|||||||||||
| 380 | // optional argument (==), mandatory (=), or none (null) |
|||||||||||
| 381 | // verifies the option syntax is correct |
|||||||||||
| 382 | preg_match("~^(\w+)(==|=)?$~", $option, $match) or self::exception('invalid', $option); |
|||||||||||
| 383 | $name = next($match); |
|||||||||||
| 384 | $type = next($match); |
|||||||||||
| 385 | // verifies the option is not a duplicate |
|||||||||||
| 386 | isset($longOptionsDef[$name]) and self::exception('duplicate', $name); |
|||||||||||
| 387 | // captures the option name and type |
|||||||||||
| 388 | $longOptionsDef[$name] = $this->type[$type]; |
|||||||||||
| 389 | } |
|||||||||||
| 390 | } |
|||||||||||
| 391 | ||||||||||||
| 392 | return $longOptionsDef; |
|||||||||||
| 393 | } |
|||||||||||
| 394 | ||||||||||||
| 395 | /** |
|||||||||||
| 396 | * Parses a short option |
|||||||||||
| 397 | * |
|||||||||||
| 398 | * @param string $argument the option and argument (excluding the "-" prefix), |
|||||||||||
| 399 | * e.g. "zfoo.php", "z foo.php", "z". |
|||||||||||
| 400 | * @return void |
|||||||||||
| 401 | * @access public |
|||||||||||
| 402 | */ |
|||||||||||
| 403 | public function parseShortOption($argument) |
|||||||||||
| 404 | { |
|||||||||||
| 405 | for ($i = 0; $i < strlen($argument); $i++) { |
|||||||||||
| 406 | $name = $argument{$i}; |
|||||||||||
| 407 | $arg = null; |
|||||||||||
| 408 | // verifies the option is valid |
|||||||||||
| 409 | isset($this->shortOptionsDef[$name]) or self::exception('unrecognized', $name); |
|||||||||||
| 410 | ||||||||||||
| 411 | if ('optional' == $this->shortOptionsDef[$name]) { |
|||||||||||
| 412 | // the option may take an optional argument, e.g. -zfoo.php or -z |
|||||||||||
| 413 | if (false !== ($arg = substr($argument, $i + 1))) { |
|||||||||||
| 414 | // the remainder of the string is the option argument |
|||||||||||
| 415 | $this->options[] = array($name, $arg); |
|||||||||||
| 416 | ||||||||||||
| 417 | return; |
|||||||||||
| 418 | } |
|||||||||||
| 419 | } elseif ('mandatory' == $this->shortOptionsDef[$name]) { |
|||||||||||
| 420 | // the option requires an argument, -zfoo.php or -z foo.php |
|||||||||||
| 421 | if (false === ($arg = substr($argument, $i + 1))) { |
|||||||||||
| 422 | // nothing left to use as the option argument |
|||||||||||
| 423 | // the next argument is expected to be the option argument |
|||||||||||
| 424 | // verifies there is one and it is not an option itself |
|||||||||||
| 425 | list(, $arg) = each($this->args); |
|||||||||||
| 426 | (is_null($arg) or $this->isOption($arg)) and self::exception('mandatory', $name); |
|||||||||||
| 427 | } |
|||||||||||
| 428 | $this->options[] = array($name, $arg); |
|||||||||||
| 429 | ||||||||||||
| 430 | return; |
|||||||||||
| 431 | } |
|||||||||||
| 432 | // else: the option is not expecting an argument, e.g. -h |
|||||||||||
| 433 | // TODO: verify that if followed by a non option which is interpreted |
|||||||||||
| 434 | // as the end of options, there is indeed no option after until |
|||||||||||
| 435 | // possibly -- or - |
|||||||||||
| 436 | // capture the option and its argument |
|||||||||||
| 437 | $this->options[] = array($name, $arg); |
|||||||||||
| 438 | } |
|||||||||||
| 439 | } |
|||||||||||
| 440 | ||||||||||||
| 441 | /** |
|||||||||||
| 442 | * Parses the short option names and types |
|||||||||||
| 443 | * |
|||||||||||
| 444 | * @param string $options the short options, e.g. array("ab:c::) |
|||||||||||
| 445 | * @return array the options name and type, |
|||||||||||
| 446 | * e.g. array("a"=>"noarg", "b"=>"mandatory", "c"=>"optional") |
|||||||||||
| 447 | * @access public |
|||||||||||
| 448 | */ |
|||||||||||
| 449 | public function parseShortOptionsDef($options) |
|||||||||||
| 450 | { |
|||||||||||
| 451 | // expecting a string for a the short options definition |
|||||||||||
| 452 | is_array($options) and self::exception('string'); |
|||||||||||
| 453 | // trims and extracts the options name and type |
|||||||||||
| 454 | // optional argument (::), mandatory (:), or none (null) |
|||||||||||
| 455 | $options = trim($options); |
|||||||||||
| 456 | preg_match_all("~(\w)(::|:)?~", $options, $matches, PREG_SET_ORDER); |
|||||||||||
| 457 | ||||||||||||
| 458 | $check = ''; |
|||||||||||
| 459 | $shortOptionsDef = array(); |
|||||||||||
| 460 | foreach ($matches as $match) { |
|||||||||||
| 461 | $check .= current($match); |
|||||||||||
| 462 | $name = next($match); |
|||||||||||
| 463 | $type = next($match); |
|||||||||||
| 464 | // verifies the option is not a duplicate |
|||||||||||
| 465 | isset($shortOptionsDef[$name]) and self::exception('duplicate', $name); |
|||||||||||
| 466 | // captures the option name and type |
|||||||||||
| 467 | $shortOptionsDef[$name] = $this->type[$type]; |
|||||||||||
| 468 | } |
|||||||||||
| 469 | // checks there is no syntax error the short options definition |
|||||||||||
| 470 | $check == $options or self::exception('syntax', $name); |
|||||||||||
| 471 | ||||||||||||
| 472 | return $shortOptionsDef; |
|||||||||||
| 473 | } |
|||||||||||
| 474 | ||||||||||||
| 475 | /** |
|||||||||||
| 476 | * Parses the command line |
|||||||||||
| 477 | * |
|||||||||||
| 478 | * See getopt() for a complete description. |
|||||||||||
| 479 | * |
|||||||||||
| 480 | * @param array $args the arguments |
|||||||||||
| 481 | * @param string $shortOptions the short options definition, e.g. "ab:c::" |
|||||||||||
| 482 | * @param array $longOptions the long options definition, e.g. array("foo", "bar=") |
|||||||||||
| 483 | * @param string $ambiguity directive to handle option names ambiguity |
|||||||||||
| 484 | * @param numeric $version the getopt version: 1 or 2 |
|||||||||||
| 485 | * @return array the parsed options, their arguments and parameters |
|||||||||||
| 486 | * @access public |
|||||||||||
| 487 | */ |
|||||||||||
| 488 | public function process( |
|||||||||||
| 489 | $args = array(), |
|||||||||||
| 490 | $shortOptions, |
|||||||||||
| 491 | $longOptions, |
|||||||||||
| 492 | $ambiguity = '', |
|||||||||||
| 493 | $version = 2 |
|||||||||||
| 494 | ) { |
|||||||||||
| 495 | settype($args, 'array'); |
|||||||||||
| 496 | in_array($ambiguity, array('loose', 'strict', 'shortcuts')) or $ambiguity = 'loose'; |
|||||||||||
| 497 | ||||||||||||
| 498 | if ($version < 2) { |
|||||||||||
| 499 | // preserve backwards compatibility with callers |
|||||||||||
| 500 | // that relied on erroneous POSIX fix |
|||||||||||
| 501 | // note: ported from Console/Getopt |
|||||||||||
| 502 | isset($args[0]) and '-' != substr($args[0], 0, 1) and array_shift($args); |
|||||||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. Loading history...
|
||||||||||||
| 503 | settype($args, 'array'); |
|||||||||||
| 504 | } |
|||||||||||
| 505 | $this->args = $args; |
|||||||||||
| 506 | // parses the options definitions, create shorcuts or check ambiguities |
|||||||||||
| 507 | $this->shortOptionsDef = $this->parseShortOptionsDef($shortOptions); |
|||||||||||
| 508 | $this->longOptionsDef = $this->parseLongOptionsDef($longOptions); |
|||||||||||
| 509 | list($this->shortcuts, $this->ambigous) = $this->createShorcuts($this->longOptionsDef, $ambiguity); |
|||||||||||
| 510 | $this->verifyNoAmbiguity($this->longOptionsDef, $ambiguity); |
|||||||||||
| 511 | ||||||||||||
| 512 | $this->options = array(); |
|||||||||||
| 513 | $parameters = array(); |
|||||||||||
| 514 | while (list($i, $arg) = each($this->args)) { |
|||||||||||
| 515 | if ('--' == $arg) { |
|||||||||||
| 516 | // end of options |
|||||||||||
| 517 | // the remaining arguments are parameters excluding this one |
|||||||||||
| 518 | $parameters = array_slice($this->args, $i + 1); |
|||||||||||
| 519 | break; |
|||||||||||
| 520 | } elseif ('-' == $arg) { |
|||||||||||
| 521 | // the stdin flag |
|||||||||||
| 522 | // the remaining arguments are parameters including this one |
|||||||||||
| 523 | $parameters = array_slice($this->args, $i); |
|||||||||||
| 524 | break; |
|||||||||||
| 525 | } elseif ('--' == substr($arg, 0, 2)) { |
|||||||||||
| 526 | // a long option, e.g. --foo |
|||||||||||
| 527 | if ($this->longOptionsDef) { |
|||||||||||
| 528 | $this->parseLongOption(substr($arg, 2)); |
|||||||||||
| 529 | } else { |
|||||||||||
| 530 | // not expecting long options, the remaining arguments are |
|||||||||||
| 531 | // parameters including this one stripped off of -- |
|||||||||||
| 532 | $parameters = array_slice($this->args, $i); |
|||||||||||
| 533 | $parameters[0] = substr($parameters[0], 2); |
|||||||||||
| 534 | break; |
|||||||||||
| 535 | } |
|||||||||||
| 536 | } elseif ('-' == $arg{0}) { |
|||||||||||
| 537 | // a short option, e.g. -h |
|||||||||||
| 538 | $this->parseShortOption(substr($arg, 1)); |
|||||||||||
| 539 | } else { |
|||||||||||
| 540 | // the first non option |
|||||||||||
| 541 | // the remaining arguments are parameters including this one |
|||||||||||
| 542 | $parameters = array_slice($this->args, $i); |
|||||||||||
| 543 | break; |
|||||||||||
| 544 | } |
|||||||||||
| 545 | } |
|||||||||||
| 546 | ||||||||||||
| 547 | return array($this->options, $parameters); |
|||||||||||
| 548 | } |
|||||||||||
| 549 | ||||||||||||
| 550 | /** |
|||||||||||
| 551 | * Reads the command arguments |
|||||||||||
| 552 | * |
|||||||||||
| 553 | * @return array the arguments |
|||||||||||
| 554 | * @access public |
|||||||||||
| 555 | * @static |
|||||||||||
| 556 | */ |
|||||||||||
| 557 | public static function readPHPArgv() |
|||||||||||
| 558 | { |
|||||||||||
| 559 | global $argv; |
|||||||||||
| 560 | ||||||||||||
| 561 | is_array($args = $argv) or is_array($args = $_SERVER['argv']) or is_array($args = $GLOBALS['HTTP_SERVER_VARS']['argv']) or self::exception('noargs'); |
|||||||||||
| 562 | ||||||||||||
| 563 | return $args; |
|||||||||||
| 564 | } |
|||||||||||
| 565 | ||||||||||||
| 566 | /** |
|||||||||||
| 567 | * Verifies there is no ambiguity with option names |
|||||||||||
| 568 | * |
|||||||||||
| 569 | * @param array $longOptionsDef the long options names and their types |
|||||||||||
| 570 | * @param string $ambiguity directive to handle option names ambiguity, |
|||||||||||
| 571 | * See getopt() for a complete description |
|||||||||||
| 572 | * @return boolean no ambiguity if true, false otherwise |
|||||||||||
| 573 | * @access public |
|||||||||||
| 574 | */ |
|||||||||||
| 575 | public function verifyNoAmbiguity($longOptionsDef, $ambiguity) |
|||||||||||
| 576 | { |
|||||||||||
| 577 | settype($longOptionsDef, 'array'); |
|||||||||||
| 578 | ||||||||||||
| 579 | foreach ($longOptionsDef as $name => $type) { |
|||||||||||
| 580 | foreach ($longOptionsDef as $name2 => $type2) { |
|||||||||||
| 581 | if ($name != $name2) { |
|||||||||||
| 582 | if ('loose' == $ambiguity and 'noarg' == $type) { |
|||||||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. Loading history...
|
||||||||||||
| 583 | // according to Getopt.php, CVS v 1.4 2007/06/12, |
|||||||||||
| 584 | // _parseLongOption(), line #236, the possible |
|||||||||||
| 585 | // ambiguity of a long option name with another one is |
|||||||||||
| 586 | // ignored if this option does not expect an argument! |
|||||||||||
| 587 | continue; |
|||||||||||
| 588 | } |
|||||||||||
| 589 | // checks options are not ambigous, e.g. --foo --foobar |
|||||||||||
| 590 | false === strpos($name2, $name) or self::exception('ambigous', $name); |
|||||||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
or instead of || is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. Loading history...
|
||||||||||||
| 591 | } |
|||||||||||
| 592 | // else: there is no ambiguity between an option and itself! |
|||||||||||
| 593 | } |
|||||||||||
| 594 | } |
|||||||||||
| 595 | ||||||||||||
| 596 | return true; |
|||||||||||
| 597 | } |
|||||||||||
| 598 | } |
|||||||||||
| 599 |
PHP has two types of connecting operators (logical operators, and boolean operators):
and&&or||The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like
&&, or||.Let’s take a look at a few examples:
Logical Operators are used for Control-Flow
One case where you explicitly want to use logical operators is for control-flow such as this:
Since
dieintroduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined withthrowat this point:These limitations lead to logical operators rarely being of use in current PHP code.