eZ Publish  [trunk]
ezcli.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZCLI class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package lib
00009  */
00010 
00011 /*!
00012   \class eZCLI ezcli.php
00013   \brief CLI handling
00014 
00015   Provides functionality to work with the CLI (Command Line Interface).
00016   The CLI can be run from either a terminal (shell) or a web interface.
00017 
00018   A typical usage:
00019 \code
00020 $cli = eZCLI::instance();
00021 
00022 $cli->setUseStyles( true ); // enable colors
00023 
00024 $cli->output( "This is a text string" );
00025 
00026 \endcode
00027 
00028 */
00029 
00030 class eZCLI
00031 {
00032     const TERMINAL_ENDOFLINE_STRING = "\n";
00033 
00034     /*!
00035      Initializes object and detects if the CLI is used.
00036     */
00037     function eZCLI()
00038     {
00039         $endl = "<br/>";
00040         $webOutput = true;
00041         if ( isset( $_SERVER['argv'] ) )
00042         {
00043             $endl = self::TERMINAL_ENDOFLINE_STRING;
00044             $webOutput = false;
00045         }
00046         $this->EndlineString = $endl;
00047         $this->WebOutput = $webOutput;
00048         $this->TerminalStyles = array( 'warning' => "\033[1;33m",
00049                                        'warning-end' => "\033[0;39m",
00050                                        'error' => "\033[1;31m",
00051                                        'error-end' => "\033[0;39m",
00052                                        'failure' => "\033[1;31m",
00053                                        'failure-end' => "\033[0;39m",
00054                                        'notice' => "\033[0;32m",
00055                                        'notice-end' => "\033[0;39m",
00056                                        'strict' => "\033[0;35m",
00057                                        'strict-end' => "\033[0;39m",
00058                                        'debug' => "\033[0;30m",
00059                                        'debug-end' => "\033[0;39m",
00060                                        'timing' => "\033[1;34m",
00061                                        'timing-end' => "\033[0;39m",
00062                                        'success' => "\033[1;32m",
00063                                        'success-end' => "\033[0;39m",
00064                                        'file' => "\033[1;38m",
00065                                        'file-end' => "\033[0;39m",
00066                                        'dir' => "\033[1;34m",
00067                                        'dir-end' => "\033[0;39m",
00068                                        'link' => "\033[0;36m",
00069                                        'link-end' => "\033[0;39m",
00070                                        'exe' => "\033[1;32m",
00071                                        'exe-end' => "\033[0;39m",
00072                                        'archive' => "\033[1;31m",
00073                                        'archive-end' => "\033[0;39m",
00074                                        'image' => "\033[1;35m",
00075                                        'image-end' => "\033[0;39m",
00076 
00077                                        'red' => "\033[1;31m",
00078                                        'red-end' => "\033[0;39m",
00079                                        'green' => "\033[1;32m",
00080                                        'green-end' => "\033[0;39m",
00081                                        'yellow' => "\033[1;33m",
00082                                        'yellow-end' => "\033[0;39m",
00083                                        'blue' => "\033[1;34m",
00084                                        'blue-end' => "\033[0;39m",
00085                                        'magenta' => "\033[1;35m",
00086                                        'magenta-end' => "\033[0;39m",
00087                                        'cyan' => "\033[1;36m",
00088                                        'cyan-end' => "\033[0;39m",
00089                                        'white' => "\033[1;37m",
00090                                        'white-end' => "\033[0;39m",
00091                                        'gray' => "\033[1;30m",
00092                                        'gray-end' => "\033[0;39m",
00093 
00094                                        'dark-red' => "\033[0;31m",
00095                                        'dark-red-end' => "\033[0;39m",
00096                                        'dark-green' => "\033[0;32m",
00097                                        'dark-green-end' => "\033[0;39m",
00098                                        'dark-yellow' => "\033[0;33m",
00099                                        'dark-yellow-end' => "\033[0;39m",
00100                                        'dark-blue' => "\033[0;34m",
00101                                        'dark-blue-end' => "\033[0;39m",
00102                                        'dark-magenta' => "\033[0;35m",
00103                                        'dark-magenta-end' => "\033[0;39m",
00104                                        'dark-cyan' => "\033[0;36m",
00105                                        'dark-cyan-end' => "\033[0;39m",
00106                                        'dark-white' => "\033[0;37m",
00107                                        'dark-white-end' => "\033[0;39m",
00108                                        'dark-gray' => "\033[0;30m",
00109                                        'dark-gray-end' => "\033[0;39m",
00110 
00111                                        'red-bg' => "\033[1;41m",
00112                                        'red-bg-end' => "\033[0;39m",
00113                                        'green-bg' => "\033[1;42m",
00114                                        'green-bg-end' => "\033[0;39m",
00115                                        'yellow-bg' => "\033[1;43m",
00116                                        'yellow-bg-end' => "\033[0;39m",
00117                                        'blue-bg' => "\033[1;44m",
00118                                        'blue-bg-end' => "\033[0;39m",
00119                                        'magenta-bg' => "\033[1;45m",
00120                                        'magenta-bg-end' => "\033[0;39m",
00121                                        'cyan-bg' => "\033[1;46m",
00122                                        'cyan-bg-end' => "\033[0;39m",
00123                                        'white-bg' => "\033[1;47m",
00124                                        'white-bg-end' => "\033[0;39m",
00125 
00126                                        'text' => "\033[0;39m",
00127                                        'text-end' => "\033[0;39m",
00128                                        'variable' => "\033[1;34m",
00129                                        'variable-end' => "\033[0;39m",
00130                                        'symbol' => "\033[0;37m",
00131                                        'symbol-end' => "\033[0;39m",
00132                                        'emphasize' => "\033[1;38m",
00133                                        'emphasize-end' => "\033[0;39m",
00134                                        'header' => "\033[1;38m",
00135                                        'header-end' => "\033[0;39m",
00136                                        'strong' => "\033[1;39m",
00137                                        'strong-end' => "\033[0;39m",
00138                                        'mark' => "\033[1;30m",
00139                                        'mark-end' => "\033[0;39m",
00140                                        'bold' => "\033[1;38m",
00141                                        'bold-end' => "\033[0;39m",
00142                                        'italic' => "\033[0;39m",
00143                                        'italic-end' => "\033[0;39m",
00144                                        'underline' => "\033[0;39m",
00145                                        'underline-end' => "\033[0;39m",
00146                                        'paragraph' => "\033[0;39m",
00147                                        'paragraph-end' => "\033[0;39m",
00148                                        'normal' => "\033[0;39m",
00149                                        'normal-end' => "\033[0;39m",
00150 
00151                                        );
00152 
00153         $this->WebStyles = array( 'warning' => '<span class="cli warning" style="color: orange;">',
00154                                   'warning-end' => '</span>',
00155                                   'error' => '<span class="cli error" style="color: red;">',
00156                                   'error-end' => '</span>',
00157                                   'failure' => '<span class="cli failure" style="color: red;">',
00158                                   'failure-end' => '</span>',
00159                                   'notice' => '<span class="cli notice" style="color: green;">',
00160                                   'notice-end' => '</span>',
00161                                   'debug' => '<span class="cli debug" style="color: brown;">',
00162                                   'debug-end' => '</span>',
00163                                   'timing' => '<span class="cli timing" style="color: blue;">',
00164                                   'timing-end' => '</span>',
00165                                   'success' => '<span class="cli success" style="color: green;">',
00166                                   'success-end' => '</span>',
00167                                   'file' => '<span class="cli file" style="font-style: italic;">',
00168                                   'file-end' => '</span>',
00169                                   'dir' => '<span class="cli dir" style="color: blue;">',
00170                                   'dir-end' => '</span>',
00171                                   'link' => '<span class="cli link" style="color: cyan;">',
00172                                   'link-end' => '</span>',
00173                                   'symbol' => '<span class="cli symbol" style="font-style: italic;">',
00174                                   'symbol-end' => '</span>',
00175                                   'emphasize' => "<em>",
00176                                   'emphasize-end' => "</em>",
00177                                   'header' => "<h1>",
00178                                   'header-end' => "</h1>",
00179                                   'strong' => '<strong>',
00180                                   'strong-end' => '</strong>',
00181                                   'mark' => '',
00182                                   'mark-end' => '',
00183                                   'bold' => '<span style="font-weight: bold;">',
00184                                   'bold-end' => '</span>',
00185                                   'italic' => '<span style="font-style: italic;">',
00186                                   'italic-end' => '</span>',
00187                                   'underline' => '<span style="text-decoration: underline">',
00188                                   'underline-end' => '</span>',
00189                                   'paragraph' => '<p>',
00190                                   'paragraph-end' => '</p>',
00191                                   'normal' => '',
00192                                   'normal-end' => '' );
00193 
00194         $this->EmptyStyles = array();
00195         foreach ( $this->TerminalStyles as $styleName => $styleValue )
00196         {
00197             $this->EmptyStyles[$styleName] = false;
00198         }
00199         $this->UseStyles = false;
00200         $this->IsQuiet = false;
00201     }
00202 
00203     /*!
00204      \return the string used to end lines. This is either the \n if CLI is used
00205              or <br/> if the script is run in a webinterface.
00206     */
00207     function endlineString()
00208     {
00209         return $this->EndlineString;
00210     }
00211 
00212     /*!
00213      \return \c true if the current script is run in a webinterface.
00214     */
00215     function isWebOutput()
00216     {
00217         return $this->WebOutput;
00218     }
00219 
00220     /*!
00221      \return the style for the name \a $name. The style is specific for terminals.
00222     */
00223     function terminalStyle( $name )
00224     {
00225         if ( isset( $this->TerminalStyles[$name] ) )
00226         {
00227             return $this->TerminalStyles[$name];
00228         }
00229         return false;
00230     }
00231 
00232     /*!
00233      \return the style for the name \a $name. The style is specific for web.
00234     */
00235     function webStyle( $name )
00236     {
00237         return $this->WebStyles[$name];
00238     }
00239 
00240     /*!
00241      \return a hash with all terminal styles.
00242     */
00243     function terminalStyles()
00244     {
00245         return $this->TerminalStyles;
00246     }
00247 
00248     /*!
00249      \return a hash with all web styles.
00250     */
00251     function webStyles()
00252     {
00253         return $this->WebStyles;
00254     }
00255 
00256     /*!
00257      \return a hash with empty styles.
00258     */
00259     function emptyStyles()
00260     {
00261         return $this->EmptyStyles;
00262     }
00263 
00264     /*!
00265      \return the style for the name \a $name. The style is taken from the current interface type.
00266     */
00267     function style( $name )
00268     {
00269         if ( $this->UseStyles )
00270         {
00271             if ( $this->isWebOutput() )
00272                 return $this->webStyle( $name );
00273             else
00274                 return $this->terminalStyle( $name );
00275         }
00276         return false;
00277     }
00278 
00279     /*!
00280      \return the text \a $text wrapped in the style \a $styleName.
00281     */
00282     function stylize( $styleName, $text )
00283     {
00284         $preStyle = $this->style( $styleName );
00285         $postStyle = $this->style( $styleName . '-end' );
00286         return $preStyle . $text . $postStyle;
00287     }
00288 
00289     /*!
00290      \static
00291      \returns an ANSI sequence which will store the current position.
00292     */
00293     static function storePosition()
00294     {
00295         return "\033[s";
00296     }
00297 
00298     /*!
00299      \static
00300      \returns an ANSI sequence which will restore the current position.
00301     */
00302     static function restorePosition()
00303     {
00304         return "\033[u";
00305     }
00306 
00307     /*!
00308      \return an ANSI sequence which will tell the console go to the specified column.
00309     */
00310     function gotoColumn( $column )
00311     {
00312         if ( !$this->UseStyles )
00313         {
00314             return "\t\t";
00315         }
00316         else
00317         {
00318             return "\033[" . $column . "G";
00319         }
00320     }
00321 
00322     /*!
00323      Controls whether styles are to be used or not. If disabled
00324      empty strings are returned when asking for styles.
00325      \note This only controls the style() function.
00326     */
00327     function setUseStyles( $useStyles )
00328     {
00329         if ( getenv('TERM') != '' )
00330         {
00331             $this->UseStyles = $useStyles;
00332         }
00333     }
00334 
00335     /*!
00336      \return \c true if styles are enabled.
00337     */
00338     function useStyles()
00339     {
00340         return $this->UseStyles;
00341     }
00342 
00343     /*!
00344      Outputs the string \a $string to the current interface.
00345      If \a $addEOL is true then the end-of-line string is added.
00346     */
00347     function output( $string = false, $addEOL = true )
00348     {
00349         if ( $this->isQuiet() )
00350             return;
00351         print( $string );
00352         if ( $addEOL )
00353             print( $this->endlineString() );
00354     }
00355 
00356     /*!
00357      Outputs the string \a $string to the current interface as a notice.
00358      If \a $addEOL is true then the end-of-line string is added.
00359     */
00360     function notice( $string = false, $addEOL = true )
00361     {
00362         fputs( STDERR, $string );
00363         if ( $addEOL )
00364             fputs( STDERR, $this->endlineString() );
00365     }
00366 
00367     /*!
00368      Outputs the string \a $string to the current interface as an warning.
00369      If \a $addEOL is true then the end-of-line string is added.
00370     */
00371     function warning( $string = false, $addEOL = true )
00372     {
00373         $string = $this->stylize( 'warning', $string );
00374         fputs( STDERR, $string );
00375         if ( $addEOL )
00376             fputs( STDERR, $this->endlineString() );
00377     }
00378 
00379     /*!
00380      Outputs the string \a $string to the current interface as an error.
00381      If \a $addEOL is true then the end-of-line string is added.
00382     */
00383     function error( $string = false, $addEOL = true )
00384     {
00385         $string = $this->stylize( 'error', $string );
00386         fputs( STDERR, $string );
00387         if ( $addEOL )
00388             fputs( STDERR, $this->endlineString() );
00389     }
00390 
00391     /**
00392      * Sets whether the output() method should print out anything.
00393      *
00394      * @param bool $isQuiet
00395      *
00396      * @see isQuiet, isLoud
00397      */
00398     function setIsQuiet( $isQuiet )
00399     {
00400         $this->IsQuiet = $isQuiet;
00401     }
00402 
00403     /*!
00404      \return \c true if output is not allowed.
00405      \sa isLoud
00406     */
00407     function isQuiet()
00408     {
00409         return $this->IsQuiet;
00410     }
00411 
00412     /*!
00413      \return \c true if output is allowed.
00414      \sa isQuiet
00415     */
00416     function isLoud()
00417     {
00418         return !$this->IsQuiet;
00419     }
00420 
00421     /*!
00422      Parses the string describing command line options into an internal format
00423      that is used by getOptions.
00424      Format:
00425      [o] short-format option, accepts "-o"
00426      [o:] short-format option with a value, accepts "-o=value"
00427      [o;] short-format option with an optional value, accepts "-o" and "-o=value"
00428      [o?] option can be present zero or 1 times (max not enforced yet)
00429      [o*] option can be present n times
00430      [o+] option can be present 1 or more times (min not enforced yet)
00431      [opt] long-format option, accepts "--opt"
00432      [o|opt] the option can be given in long or short format
00433      [o:|opt:] and [o:+] and similar combinations are also valid
00434      weird api: $optionConfig is modified and returned as well
00435      \param $configString string
00436      \param $optionConfig array - if it is not empty, parsed options are added to it
00437      \return array members: 'list', 'long', 'short', with 'list' containing both long and short members
00438     */
00439     static function parseOptionString( $configString, &$optionConfig )
00440     {
00441         $len = strlen( $configString );
00442         $i = 0;
00443         if ( !is_array( $optionConfig ) )
00444         {
00445             $optionConfig = array( 'list' => array(),
00446                                    'short' => array(),
00447                                    'long' => array() );
00448         }
00449         while ( $i < $len )
00450         {
00451             $option = $configString[$i];
00452             if ( $option == '[' )
00453             {
00454                 $end = strpos( $configString, ']', $i + 1 );
00455                 if ( $end === false )
00456                 {
00457                     eZDebug::writeError( "Missing end marker ] in option string at position $i", __METHOD__ );
00458                     return $optionConfig;
00459                 }
00460                 $optionList = substr( $configString, $i + 1, $end - $i - 1 );
00461                 $i += 1 + ( $end - $i );
00462                 $startMarkerPos = strpos( $optionList, '[' );
00463                 if ( $startMarkerPos !== false )
00464                 {
00465                     eZDebug::writeError( "Start marker [ found in option string at position, it should not be present. Skipping current option" . ( $i + 1 + $startMarkerPos ),
00466                                          'eZCLI::parseOptionString' );
00467                     continue;
00468                 }
00469                 $optionList = explode( '|', $optionList );
00470             }
00471             else
00472             {
00473                 $text = $option;
00474                 ++$i;
00475                 if ( $i < $len and
00476                      in_array( $configString[$i], array( ':', ';' ) ) )
00477                 {
00478                     $text .= $configString[$i];
00479                     ++$i;
00480                 }
00481                 if ( $i < $len and
00482                      in_array( $configString[$i], array( '?', '*', '+' ) ) )
00483                 {
00484                     $text .= $configString[$i];
00485                     ++$i;
00486                 }
00487                 $optionList = array( $text );
00488             }
00489             $optionStoreName = false;
00490             unset( $optionConfigList );
00491             $optionConfigList = array();
00492             foreach ( $optionList as $optionItem )
00493             {
00494                 $optionLen = strlen( $optionItem );
00495                 $hasValue = false;
00496                 $optionName = $optionItem;
00497                 $quantifierText = false;
00498                 $quantifier = array( 'min' => 0,
00499                                      'max' => 0 );
00500                 if ( $optionLen > 0 and in_array( $optionName[$optionLen - 1], array( '?', '*', '+' ) ) )
00501                 {
00502                     $quantifierText = $optionName[$optionLen - 1];
00503                     $optionName = substr( $optionName, 0, $optionLen - 1 );
00504                     --$optionLen;
00505                     if ( $quantifierText == '?' )
00506                         $quantifier = array( 'min' => 0,
00507                                              'max' => 1 );
00508                     else if ( $quantifierText == '*' )
00509                         $quantifier = array( 'min' => 0,
00510                                              'max' => false );
00511                     else if ( $quantifierText == '+' )
00512                         $quantifier = array( 'min' => 1,
00513                                              'max' => false );
00514                 }
00515                 if ( $optionLen > 0 and in_array( $optionName[$optionLen - 1], array( ':', ';' ) ) )
00516                 {
00517                     $valueText = $optionName[$optionLen - 1];
00518                     $optionName = substr( $optionName, 0, $optionLen - 1 );
00519                     --$optionLen;
00520                     if ( $valueText == ':' )
00521                         $hasValue = true;
00522                     else if ( $valueText == ';' )
00523                         $hasValue = 'optional';
00524                 }
00525                 $optionLen = strlen( $optionName );
00526                 if ( $optionLen == 0 )
00527                     continue;
00528                 $optionStoreName = $optionName;
00529                 $optionConfigItem = array( 'name' => $optionName,
00530                                            'has-value' => $hasValue,
00531                                            'quantifier' => $quantifier,
00532                                            'store-name' => false,
00533                                            'is-long-option' => strlen( $optionName ) > 1 );
00534                 $optionConfigList[] = $optionConfigItem;
00535             }
00536             foreach ( array_keys( $optionConfigList ) as $optionConfigItemKey )
00537             {
00538                 $optionConfigItem =& $optionConfigList[$optionConfigItemKey];
00539                 $optionName = $optionConfigItem['name'];
00540                 $optionConfigItem['store-name'] = $optionStoreName;
00541                 $optionConfig['list'][] = $optionConfigItem;
00542                 if ( $optionConfigItem['is-long-option'] )
00543                     $optionConfig['long'][$optionName] = $optionConfigItem;
00544                 else
00545                     $optionConfig['short'][$optionName] = $optionConfigItem;
00546             }
00547         }
00548         return $optionConfig;
00549     }
00550 
00551     /*!
00552      Parses the arguments from array $arguments (or from command line if $arguments == false)
00553      according to the options specified by $config and $argumentConfig.
00554      Option arguments can be specified using the following formats:
00555        -o (option 'o' in short format)
00556        -ovalue (option 'o' in short format with value 'value' )
00557        -o value (option 'o' in short format with value 'value' )
00558        --option (option 'option' in long format)
00559        --option=value (option 'option' in long format with value 'value' )
00560      Any argument that does not start with a '-' char or follows an option is considered an argument
00561      \param $config definition of options as string or array in internal format. NB: 'quantifier' descriptor of options right now can only be used to specify 1/many values
00562      \param $argumentconfig defition of options as string or array in internal format. NB: UNUSED for now
00563      \param array $arguments
00564      \return array containing a member for every option specified in $config and a member 'arguments' for all non-option arguments.
00565                    If an option is defined as optional in $config but not present in $arguments, it will be given a null value.
00566                    If an option is defined as mandatory value in $config but not present in $arguments, the function will return false instead
00567     */
00568     function getOptions( $config, $argumentConfig, $arguments = false )
00569     {
00570         $program = false;
00571         if ( $arguments === false )
00572         {
00573             $arguments = $GLOBALS['argv'];
00574             $program = $arguments[0];
00575             array_shift( $arguments );
00576         }
00577 
00578         if ( is_string( $config ) )
00579             $config = eZCLI::parseOptionString( $config, $tmpConfig );
00580         if ( is_string( $argumentConfig ) )
00581             $argumentConfig = eZCLI::parseOptionString( $argumentConfig, $tmpArgumentConfig );
00582 
00583         $options = array();
00584 
00585         $helpOption = false;
00586         $helpText = false;
00587         if ( isset( $config['short']['h'] ) )
00588             $helpOption = '-h';
00589         else if ( isset( $config['short']['help'] ) )
00590             $helpOption = '--help';
00591         if ( $helpOption )
00592             $helpText = "\n" . "Try `$program $helpOption' for more information.";
00593 
00594         $options['arguments'] = array();
00595 
00596         $arguments = array_values( $arguments );
00597         $argumentCount = count( $arguments );
00598         for ( $i = 0; $i < $argumentCount; ++$i )
00599         {
00600             $argument = $arguments[$i];
00601             $argumentLen = strlen( $argument );
00602             if ( $argumentLen > 1 and
00603                  $argument[0] == '-' )
00604             {
00605                 $argumentValue = false;
00606                 if ( $argumentLen > 2 and
00607                      $argument[1] == '-' )
00608                 {
00609                     $optionName = substr( $argument, 2 );
00610                     $assignPosition = strpos( $optionName, '=' );
00611                     if ( $assignPosition !== false )
00612                     {
00613                         $argumentValue = substr( $optionName, $assignPosition + 1 );
00614                         $optionName = substr( $optionName, 0, $assignPosition );
00615                     }
00616                     $optionType = 'long';
00617                     $optionPrefix = '--';
00618                     $checkNext = false;
00619                 }
00620                 else
00621                 {
00622                     $optionName = $argument[1];
00623                     if ( $argumentLen > 2 )
00624                     {
00625                         $argumentValue = substr( $argument, 2 );
00626                     }
00627                     $optionType = 'short';
00628                     $optionPrefix = '-';
00629                     $checkNext = true;
00630                 }
00631                 $configItem =& $config[$optionType][$optionName];
00632                 if ( isset( $configItem ) )
00633                 {
00634                     $value = true;
00635                     $hasValue = $configItem['has-value'];
00636                     $hasMultipleValues = ( $configItem['quantifier']['min'] > 1 or
00637                                            $configItem['quantifier']['max'] === false or
00638                                            $configItem['quantifier']['max'] > 1 );
00639                     if ( $hasValue )
00640                     {
00641                         $hasArgumentValue = false;
00642                         if ( $argumentValue !== false )
00643                         {
00644                             $value = $argumentValue;
00645                         }
00646                         else if ( $checkNext and $configItem['has-value'] !== 'optional' )
00647                         {
00648                             ++$i;
00649                             if ( $i < $argumentCount )
00650                             {
00651                                 $hasArgumentValue = true;
00652                             }
00653                             else
00654                             {
00655                                 --$i;
00656                                 $this->error( "$program: option `$optionPrefix$optionName' requires an argument" . $helpText );
00657                                 return false;
00658                             }
00659                             if ( $hasArgumentValue )
00660                                 $value = $arguments[$i];
00661                         }
00662                         else
00663                         {
00664                             if ( $configItem['has-value'] !== 'optional' )
00665                             {
00666                                 $this->error( "$program: option `$optionPrefix$optionName' requires an argument" . $helpText );
00667                                 return false;
00668                             }
00669                         }
00670                     }
00671                     $optionStoreName = $configItem['store-name'];
00672                     if ( !$optionStoreName )
00673                         $optionStoreName = $optionName;
00674                     if ( $hasMultipleValues )
00675                     {
00676                         if ( !isset( $options[$optionStoreName] ) )
00677                             $options[$optionStoreName] = array();
00678                         $options[$optionStoreName][] = $value;
00679                     }
00680                     else
00681                     {
00682                         $options[$optionStoreName] = $value;
00683                     }
00684                 }
00685                 else
00686                 {
00687                     $this->error( "$program: invalid option `$optionPrefix$optionName'" . $helpText );
00688                     return false;
00689                 }
00690             }
00691             else
00692             {
00693                 $options['arguments'][] = $argument;
00694             }
00695         }
00696         foreach ( $config['list'] as $configItem )
00697         {
00698             $optionStoreName = $configItem['store-name'];
00699             if ( $optionStoreName and !isset( $options[$optionStoreName] ) )
00700                 $options[$optionStoreName] = null;
00701         }
00702         return $options;
00703     }
00704 
00705     /**
00706      * Returns a shared instance of the eZCLI class.
00707      *
00708      * @return eZCLI
00709      */
00710     static function instance()
00711     {
00712         if ( !isset( $GLOBALS['eZCLIInstance'] ) ||
00713              !( $GLOBALS['eZCLIInstance'] instanceof eZCLI ) )
00714         {
00715             $GLOBALS['eZCLIInstance'] = new eZCLI();
00716         }
00717 
00718         return $GLOBALS['eZCLIInstance'];
00719     }
00720 
00721     /*!
00722      \return \c true if instance of eZCLI already exists otherwise \c false.
00723     */
00724     static function hasInstance()
00725     {
00726         return isset( $GLOBALS['eZCLIInstance'] ) && $GLOBALS['eZCLIInstance'] instanceof eZCLI;
00727     }
00728 }
00729 
00730 ?>