eZ Publish  [trunk]
ezscript.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZScript 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 kernel
00009  */
00010 
00011 /*!
00012   \class eZScript ezscript.php
00013   \brief Handles the basics of script execution
00014 
00015   By using this class for script execution startup, initializing
00016   and shutdown the amount code required to write a new script is
00017   reduced significantly.
00018 
00019   It is also recommended to use the eZCLI class in addition to this
00020   class.
00021 
00022   What this class will handle is:
00023   - Startup of database
00024   - Startup/shutdown of session
00025   - Debug initialize and display
00026   - Text codec initialize
00027 
00028   This class consists of the static functions startup(), initialize()
00029   and shutdown().
00030 
00031   A typical usage:
00032 \code
00033 $script = eZScript::instance();
00034 
00035 $script->startup();
00036 
00037 // Read arguments and modify script accordingly
00038 
00039 $script->initialize();
00040 
00041 // Do the actual script here
00042 
00043 $script->shutdown(); // Finish execution
00044 
00045 \endcode
00046 
00047 */
00048 class eZScript
00049 {
00050     /*!
00051      Constructor
00052     */
00053     function eZScript( $settings = array() )
00054     {
00055         $settings = array_merge( array( 'debug-message' => false,
00056                                         'debug-output' => false,
00057                                         'debug-include' => false,
00058                                         'debug-levels' => false,
00059                                         'debug-accumulator' => false,
00060                                         'debug-timing' => false,
00061                                         'use-session' => false,
00062                                         'use-extensions' => true,
00063                                         'use-modules' => false,
00064                                         'user' => false,
00065                                         'description' => 'eZ Publish script',
00066                                         'site-access' => false,
00067                                         'min_version' => false,
00068                                         'max_version' => false ),
00069                                  $settings );
00070         $this->DebugMessage = $settings['debug-message'];
00071         $this->UseDebugOutput = $settings['debug-output'];
00072         $this->AllowedDebugLevels = $settings['debug-levels'];
00073         $this->UseDebugAccumulators = $settings['debug-accumulator'];
00074         $this->UseDebugTimingPoints = $settings['debug-timing'];
00075         $this->UseIncludeFiles = $settings['debug-include'];
00076         $this->UseSession = $settings['use-session'];
00077         $this->UseModules = $settings['use-modules'];
00078         $this->UseExtensions = $settings['use-extensions'];
00079         $this->User = $settings['user'];
00080         $this->SiteAccess = $settings['site-access'];
00081         $this->Description = $settings['description'];
00082         $this->MinVersion = $settings['min_version'];
00083         $this->MaxVersion = $settings['max_version'];
00084         $this->ExitCode = false;
00085         $this->IsQuiet = false;
00086         $this->ShowVerbose = false;
00087         $this->IsInitialized = false;
00088         $this->CurrentOptions = false;
00089         $this->CurrentOptionConfig = false;
00090         $this->CurrentStandardOptions = false;
00091         $this->CurrentExcludeOptions = false;
00092         $this->CurrentOptionHelp = false;
00093 
00094         $this->IterationTrueString = '.';
00095         $this->IterationFalseString = '~';
00096         $this->IterationNumericStrings = false;
00097         $this->IterationWrapNumeric = false;
00098         $this->IterationIndex = 0;
00099         $this->IterationColumn = 0;
00100         $this->IterationColumnMax = 70;
00101         $this->IterationMax = false;
00102         $this->InitializationErrorMessage = 'unknown error';
00103     }
00104 
00105     /*!
00106      Checks if the script is run on correct eZ Publish version.
00107     */
00108     function validateVersion()
00109     {
00110         $versionValidated = false;
00111         $ezversion = eZPublishSDK::version();
00112         if ( $this->MinVersion !== false )
00113         {
00114             if ( $this->MaxVersion !== false )
00115             {
00116                 if ( version_compare( $this->MinVersion, $ezversion , 'le' ) &&
00117                      version_compare( $this->MaxVersion, $ezversion , 'ge' ) )
00118                 {
00119                     return true;
00120                 }
00121                 return false;
00122             }
00123             if ( version_compare( $this->MinVersion, $ezversion , 'le' ) )
00124             {
00125                 return true;
00126             }
00127             return false;
00128         }
00129         else
00130         {
00131             if ( version_compare( $this->MaxVersion, $ezversion , 'ge' ) )
00132             {
00133                 return true;
00134             }
00135             return false;
00136         }
00137     }
00138 
00139     /*!
00140      Checks if the script is run in CLI mode, if not it exits with a warning.
00141      The PHP local is also initialized if it is used.
00142 
00143      Call this at the very start of your script and always before getOptions() and initialize().
00144     */
00145     function startup()
00146     {
00147         error_reporting( E_ALL );
00148 
00149         eZDebug::setHandleType( eZDebug::HANDLE_TO_PHP );
00150 
00151         if ( php_sapi_name() != 'cli' )
00152         {
00153             $cli = eZCLI::instance();
00154             $cli->output( "PHP is currently using the '" . php_sapi_name() . "' interface. Make sure it is using the 'cli' interface." );
00155             exit( 1 );
00156         }
00157 
00158         $ini = eZINI::instance();
00159         $phpLocale = trim( $ini->variable( 'RegionalSettings', 'SystemLocale' ) );
00160         if ( $phpLocale != '' )
00161         {
00162             setlocale( LC_ALL, explode( ',', $phpLocale ) );
00163         }
00164 
00165         // Set correct site timezone
00166         $timezone = $ini->variable( "TimeZoneSettings", "TimeZone" );
00167         if ( $timezone )
00168         {
00169             date_default_timezone_set( $timezone );
00170         }
00171     }
00172 
00173     /*!
00174      Initializes all settings which are required for the script to run,
00175      must be called after startup() and getOptions().
00176 
00177      If you modify the eZScript object using the set* functions you must make sure that
00178      is done before this function is called.
00179     */
00180     function initialize()
00181     {
00182         if( ob_get_length() != 0 )
00183             ob_end_clean();
00184         $debugINI = eZINI::instance( 'debug.ini' );
00185         eZDebugSetting::setDebugINI( $debugINI );
00186 
00187         // Initialize text codec settings
00188         $this->updateTextCodecSettings();
00189 
00190         // Initialize debug settings
00191         $this->updateDebugSettings( $this->UseDebugOutput );
00192 
00193         // Set the different permissions/settings.
00194         $ini = eZINI::instance();
00195         $iniFilePermission = $ini->variable( 'FileSettings', 'StorageFilePermissions' );
00196         $iniDirPermission = $ini->variable( 'FileSettings', 'StorageDirPermissions' );
00197         $iniVarDirectory = eZSys::cacheDirectory() ;
00198 
00199         eZCodePage::setPermissionSetting( array( 'file_permission' => octdec( $iniFilePermission ),
00200                                                  'dir_permission'  => octdec( $iniDirPermission ),
00201                                                  'var_directory'   => $iniVarDirectory ) );
00202 
00203         eZExecution::addCleanupHandler( 'eZDBCleanup' );
00204         eZExecution::addFatalErrorHandler( 'eZFatalError' );
00205 
00206         eZDebug::setHandleType( eZDebug::HANDLE_FROM_PHP );
00207 
00208         if ( $this->UseExtensions )
00209         {
00210             // Check for extension
00211             eZExtension::activateExtensions( 'default' );
00212             // Extension check end
00213         }
00214         else if ( !$this->isQuiet() )
00215         {
00216             $cli = eZCLI::instance();
00217             $cli->output( "Notice: This script uses 'use-extensions' => false, meaning extension settings are not loaded!" );
00218         }
00219 
00220         $siteaccess = $this->SiteAccess;
00221         if ( $siteaccess )
00222         {
00223             $access = array( 'name' => $siteaccess,
00224                              'type' => eZSiteAccess::TYPE_STATIC );
00225         }
00226         else
00227         {
00228             $ini = eZINI::instance();
00229             $siteaccess = $ini->variable( 'SiteSettings', 'DefaultAccess' );
00230             $access = array( 'name' => $siteaccess,
00231                              'type' => eZSiteAccess::TYPE_DEFAULT );
00232         }
00233 
00234         $access = eZSiteAccess::change( $access );
00235 
00236         if ( $this->UseExtensions )
00237         {
00238             // Check for siteaccess extension
00239             eZExtension::activateExtensions( 'access' );
00240             // Extension check end
00241         }
00242 
00243         // Now that all extensions are activated and siteaccess has been changed, reset
00244         // all eZINI instances as they may not take into account siteaccess specific settings.
00245         eZINI::resetAllInstances( false );
00246 
00247         // Set the global setting which is read by the session lib
00248         $GLOBALS['eZSiteBasics']['session-required'] = $this->UseSession;
00249 
00250         if ( $this->UseSession )
00251         {
00252             $db = eZDB::instance();
00253             if ( $db->isConnected() )
00254             {
00255                 eZSession::start();
00256             }
00257             else
00258             {
00259                 $this->IsInitialized = false;
00260                 $this->InitializationErrorMessage = 'database error: ' . $db->errorMessage();
00261                 return;
00262             }
00263         }
00264 
00265         if ( $this->User )
00266         {
00267             $userLogin = $this->User['login'];
00268             $userPassword = $this->User['password'];
00269             if ( $userLogin and $userPassword )
00270             {
00271                 $userID = eZUser::loginUser( $userLogin, $userPassword );
00272                 if ( !$userID )
00273                 {
00274                     $cli = eZCLI::instance();
00275                     if ( $this->isLoud() )
00276                         $cli->warning( 'Failed to login with user ' . $userLogin );
00277                     eZExecution::cleanup();
00278                     eZExecution::setCleanExit();
00279                 }
00280             }
00281         }
00282 
00283         // Initialize module handling
00284         if ( $this->UseModules )
00285         {
00286             $moduleRepositories = eZModule::activeModuleRepositories( $this->UseExtensions );
00287             eZModule::setGlobalPathList( $moduleRepositories );
00288         }
00289         $this->IsInitialized = true;
00290     }
00291 
00292     function isInitialized()
00293     {
00294         return $this->IsInitialized;
00295     }
00296 
00297     function initializationError()
00298     {
00299         return $this->InitializationErrorMessage;
00300     }
00301 
00302     /*!
00303      Shuts down the currently running script, the following things will be done:
00304      - Remove current session (if sessions are used)
00305      - Print debug messages (if debug is enabled)
00306      - Call cleanup function using eZExecution
00307      - Sets the clean exit flag, that way an exit, die or other stops will not issue an error
00308 
00309      If an exit code is set, PHP will exit with that code set (this means that this function never returns),
00310      otherwise this function returns normally.
00311     */
00312     function shutdown( $exitCode = false, $exitText = false )
00313     {
00314         $cli = eZCLI::instance();
00315         if ( class_exists( 'eZDB' )
00316              and eZDB::hasInstance() )
00317         {
00318             $db = eZDB::instance( false, array( 'show_errors' => false ) );
00319             // Perform transaction check
00320             $transactionCounterCheck = eZDB::checkTransactionCounter();
00321             if ( isset( $transactionCounterCheck['error'] ) )
00322                 $cli->error( $transactionCounterCheck['error'] );
00323 
00324             if ( $this->UseSession and
00325                  $db->isConnected() )
00326             {
00327                 eZUser::logoutCurrent();
00328                 eZSession::remove();
00329             }
00330         }
00331 
00332         $webOutput = $cli->isWebOutput();
00333 
00334         if ( $this->UseDebugOutput or
00335              eZDebug::isDebugEnabled() )
00336         {
00337             if ( $this->DebugMessage )
00338                 fputs( STDERR, $this->DebugMessage );
00339             fputs( STDERR, eZDebug::printReport( false, $webOutput, true,
00340                                                  $this->AllowedDebugLevels, $this->UseDebugAccumulators,
00341                                                  $this->UseDebugTimingPoints, $this->UseIncludeFiles ) );
00342         }
00343 
00344         eZExecution::cleanup();
00345         eZExecution::setCleanExit();
00346         $this->IsInitialized = false;
00347         if ( $exitCode !== false )
00348             $this->ExitCode = $exitCode;
00349         if ( $this->ExitCode !== false )
00350         {
00351             if ( $exitText !== false )
00352                 $cli->output( $exitText );
00353             exit( $this->ExitCode );
00354         }
00355     }
00356 
00357     /*!
00358      Sets the text message which is shown before the debug list.
00359      There will be a default message which should suit most scripts.
00360      \note This requires that setUseDebugOutput is set to true or that
00361            the user has enabled debug in the arguments.
00362     */
00363     function setDebugMessage( $message )
00364     {
00365         $this->DebugMessage = $message;
00366     }
00367 
00368     /*!
00369      Sets whether debug output should be enabled or not.
00370      \note This can also be called by the argument parser if the user specifies to show debug.
00371     */
00372     function setUseDebugOutput( $useDebug )
00373     {
00374         $this->UseDebugOutput = $useDebug;
00375     }
00376 
00377     /*!
00378      Sets whether accumulators should be shown on debug output or not.
00379      \note This requires that setUseDebugOutput is set to true or that
00380            the user has enabled debug in the arguments.
00381     */
00382     function setUseDebugAccumulators( $useAccumulators )
00383     {
00384         $this->UseDebugAccumulators = $useAccumulators;
00385     }
00386 
00387     /*!
00388      Sets whether timing points should be shown on debug output or not.
00389      \note This requires that setUseDebugOutput is set to true or that
00390            the user has enabled debug in the arguments.
00391     */
00392     function setUseDebugTimingPoints( $useTimingPoints )
00393     {
00394         $this->UseDebugTimingPoints = $useTimingPoints;
00395     }
00396 
00397     /*!
00398      Sets whether include files should be shown on debug output or not.
00399      \note This requires that setUseDebugOutput is set to true or that
00400            the user has enabled debug in the arguments.
00401     */
00402     function setUseIncludeFiles( $useIncludeFiles )
00403     {
00404         $this->UseIncludeFiles = $useIncludeFiles;
00405     }
00406 
00407     /*!
00408      Sets which debug levels are to be shown on debug output, this must be an array
00409      with EZ_LEVEL_* definitions taken from eZDebug.
00410      \note This requires that setUseDebugOutput is set to true or that
00411            the user has enabled debug in the arguments.
00412     */
00413     function setAllowedDebugLevels( $allowedDebugLevels )
00414     {
00415         $this->AllowedDebugLevels = $allowedDebugLevels;
00416     }
00417 
00418     /*!
00419      Sets whether session is to be used or not.
00420      \note This will only work if it is set before initialized() is called.
00421      \note If session is enabled the current session data will be removed on shutdown().
00422     */
00423     function setUseSession( $useSession )
00424     {
00425         $this->UseSession = $useSession;
00426     }
00427 
00428     /*!
00429      Sets whether extension support is to be added or not.
00430      \note This will only work if it is set before initialized() is called.
00431     */
00432     function setUseExtensions( $useExtensions )
00433     {
00434         $this->UseExtensions = $useExtensions;
00435     }
00436 
00437     /*!
00438      Sets the current site access to \a $siteAccess.
00439      \note This will only work if it is set before initialized() is called.
00440      \note This will be filled in if getOptions() is used and the user specifices it in the arguments.
00441     */
00442     function setUseSiteAccess( $siteAccess )
00443     {
00444         $this->SiteAccess = $siteAccess;
00445     }
00446 
00447     /*!
00448      \return the currently set siteaccess or \c false if none is set.
00449     */
00450     function usedSiteAccess()
00451     {
00452         return $this->SiteAccess;
00453     }
00454 
00455     function setUseModules( $useModules )
00456     {
00457         $this->UseModules = $useModules;
00458     }
00459 
00460     function setUser( $userLogin, $userPassword )
00461     {
00462         $this->User = array( 'login' => $userLogin,
00463                              'password' => $userPassword );
00464     }
00465 
00466     /*!
00467      Controls whether verbose output is used or not, use \c false to turn it off,
00468      \c true to turn it on or a number to select the verbose level (\c true == 1).
00469      The actual behaviour of verbose output depends on the script, however enabling
00470      it will make sure iteration looping displays the iteration name instead of a dot.
00471     */
00472     function setShowVerboseOutput( $verbose )
00473     {
00474         if ( $verbose === true )
00475             $verbose = 1;
00476         $this->ShowVerbose = $verbose;
00477     }
00478 
00479     /*!
00480      \return the verbosity level for the script, will be \c false or a number in the range 1 and up.
00481     */
00482     function verboseOutputLevel()
00483     {
00484         return $this->ShowVerbose;
00485     }
00486 
00487     /*!
00488      \return the currently set options if getOptions() has been run or \c false if no options are set.
00489     */
00490     function currentOptions()
00491     {
00492         return $this->CurrentOptions;
00493     }
00494 
00495     /*!
00496      \return the current option configuration, this will be a mix of the standard options and script specified.
00497     */
00498     function currentOptionConfig()
00499     {
00500         return $this->CurrentOptionConfig;
00501     }
00502 
00503     /*!
00504      Sets the current exit code which will be set with an exit() call in shutdown().
00505      If you don't want shutdown() to exit automatically set it to \c false.
00506     */
00507     function setExitCode( $code = false )
00508     {
00509         $this->ExitCode = $code;
00510     }
00511 
00512     function exitCode()
00513     {
00514         return $this->ExitCode;
00515     }
00516 
00517     /*!
00518      Sets whether any output should be used or not.
00519      \sa isQuiet, isLoud
00520      \note it will also call eZCLI::setIsQuiet()
00521     */
00522     function setIsQuiet( $isQuiet )
00523     {
00524         $cli = eZCLI::instance();
00525         $this->IsQuiet = $isQuiet;
00526         $cli->setIsQuiet( $isQuiet );
00527     }
00528 
00529     /*!
00530      \return \c true if output is not allowed.
00531      \sa isLoud
00532     */
00533     function isQuiet()
00534     {
00535         return $this->IsQuiet;
00536     }
00537 
00538     /*!
00539      \return \c true if output is allowed.
00540      \sa isQuiet
00541     */
00542     function isLoud()
00543     {
00544         return !$this->IsQuiet;
00545     }
00546 
00547     function setIterationData( $trueString, $falseString,
00548                                $numericStrings = false, $wrapNumeric = false )
00549     {
00550         $this->IterationTrueString = $trueString;
00551         $this->IterationFalseString = $falseString;
00552         $this->IterationNumericStrings = $numericStrings;
00553         $this->IterationWrapNumeric = $wrapNumeric;
00554     }
00555 
00556     function resetIteration( $iterationMax = false, $startIndex = 0 )
00557     {
00558         $this->IterationIndex = $startIndex;
00559         $this->IterationColumn = 0;
00560         $this->IterationMax = $iterationMax;
00561     }
00562 
00563     function iterate( $cli, $status, $text = false )
00564     {
00565         if ( !$this->IterationNumericStrings )
00566             $status = (bool)$status;
00567         if ( $this->verboseOutputLevel() === false or
00568              $text === false )
00569         {
00570             if ( is_bool( $status ) )
00571             {
00572                 $statusText = $status ? $this->IterationTrueString : $this->IterationFalseString;
00573             }
00574             else
00575             {
00576                 if ( $this->IterationWrapNumeric )
00577                     $status = $status % count( $this->IterationNumericStrings );
00578                 if ( $status < count( $this->IterationNumericStrings ) )
00579                     $statusText = $this->IterationNumericStrings[$status];
00580                 else
00581                     $statusText = ' ';
00582             }
00583             $endLine = false;
00584             $changeLine = false;
00585             ++$this->IterationIndex;
00586             ++$this->IterationColumn;
00587             $iterationColumn = $this->IterationColumn;
00588             if ( $this->IterationColumn >= $this->IterationColumnMax )
00589             {
00590                 $this->IterationColumn = 0;
00591                 $changeLine = true;
00592             }
00593             if ( $this->IterationMax !== false )
00594             {
00595                 if ( $this->IterationIndex >= $this->IterationMax )
00596                 {
00597                     $this->IterationColumn = 0;
00598                     $changeLine = true;
00599                 }
00600             }
00601             if ( $changeLine )
00602             {
00603                 if ( $this->IterationMax !== false )
00604                 {
00605                     $spacing = $this->IterationColumnMax - $iterationColumn;
00606                     $percent = ( $this->IterationIndex * 100 ) / $this->IterationMax;
00607                     if ( $percent > 100.0 )
00608                         $percent = 100;
00609                     else
00610                         $spacing += 1;
00611                     $percentText = number_format( $percent, 2 ) . '%';
00612                     $statusText .= str_repeat( ' ', $spacing );
00613                     $statusText .= $percentText;
00614                 }
00615                 $endLine = true;
00616             }
00617             $cli->output( $statusText, $endLine );
00618         }
00619         else
00620         {
00621             $statusLevel = $status;
00622             if ( is_bool( $status ) )
00623                 $statusLevel = $status ? 0 : 1;
00624             if ( $statusLevel > 0 )
00625             {
00626                 --$statusLevel;
00627                 $statusLevels = array( 'warning', 'failure' );
00628                 if ( $statusLevel > count( $statusLevels ) )
00629                     $statusLevel = count( $statusLevels ) - 1;
00630                 $levelText = $statusLevels[$statusLevel];
00631                 $cli->output( $cli->stylize( $levelText, $text ) );
00632             }
00633             else
00634             {
00635                 $cli->output( $text );
00636             }
00637         }
00638     }
00639 
00640     function showHelp( $useStandardOptions = false, $optionConfig = false, $optionHelp = false, $argumentConfig = false, $arguments = false )
00641     {
00642         if ( $useStandardOptions === false )
00643         {
00644             $useStandardOptions = $this->CurrentStandardOptions;
00645         }
00646         if ( $optionConfig === false )
00647         {
00648             $optionConfig = $this->CurrentOptionConfig;
00649         }
00650         if ( $optionHelp === false )
00651         {
00652             $optionHelp = $this->CurrentOptionHelp;
00653         }
00654         if ( $argumentConfig === false )
00655         {
00656             $argumentConfig = $this->ArgumentConfig;
00657         }
00658         $optionList = array();
00659         foreach ( $optionConfig['list'] as $configItem )
00660         {
00661             if ( in_array( $configItem['name'], $this->CurrentExcludeOptions ) )
00662                 continue;
00663             $optionText = '-';
00664             if ( $configItem['is-long-option'] )
00665                 $optionText .= '-';
00666             $optionText .= $configItem['name'];
00667             if ( $configItem['has-value'] and $configItem['is-long-option'] )
00668                 $optionText .= "=VALUE";
00669             $hasMultipleValues = ( $configItem['quantifier']['min'] > 1 or
00670                                    $configItem['quantifier']['max'] === false or
00671                                    $configItem['quantifier']['max'] > 1 );
00672             if ( $hasMultipleValues )
00673                 $optionText .= "...";
00674             $optionDescription = '';
00675             if ( isset( $optionHelp[$configItem['name']] ) )
00676                 $optionDescription = $optionHelp[$configItem['name']];
00677             $optionList[] = array( $optionText, $optionDescription );
00678         }
00679         if ( $arguments === false )
00680         {
00681             $arguments = $_SERVER['argv'];
00682             $program = $arguments[0];
00683         }
00684         $cli = eZCLI::instance();
00685         $generalOptionList = array();
00686         $generalOptionList = array();
00687         if ( $useStandardOptions )
00688         {
00689             $generalOptionList[] = array( '-h,--help', 'display this help and exit');
00690             $generalOptionList[] = array( '-q,--quiet', 'do not give any output except when errors occur' );
00691             if ( $useStandardOptions['siteaccess'] )
00692                 $generalOptionList[] = array( '-s,--siteaccess', "selected siteaccess for operations,\nif not specified default siteaccess is used" );
00693             if ( $useStandardOptions['debug'] )
00694                 $generalOptionList[] = array( '-d,--debug...', ( "display debug output at end of execution,\n" .
00695                                                                  "the following debug items can be controlled: \n" .
00696                                                                  "all, accumulator, include, timing, error, warning, debug, notice or strict." ) );
00697             if ( $useStandardOptions['colors'] )
00698             {
00699                 $generalOptionList[] = array( '-c,--colors', 'display output using ANSI colors (default)' );
00700                 $generalOptionList[] = array( '--no-colors', 'do not use ANSI coloring' );
00701             }
00702             if ( $useStandardOptions['user'] )
00703             {
00704                 $generalOptionList[] = array( '-l,--login USER', 'login with USER and use it for all operations' );
00705                 $generalOptionList[] = array( '-p,--password PWD', 'use PWD as password for USER' );
00706             }
00707             if ( $useStandardOptions['log'] )
00708             {
00709                 $generalOptionList[] = array( '--logfiles', 'create log files' );
00710                 $generalOptionList[] = array( '--no-logfiles', 'do not create log files (default)' );
00711             }
00712             if ( $useStandardOptions['verbose'] )
00713             {
00714                 $generalOptionList[] = array( '-v,--verbose...', "display more information, \nused multiple times will increase amount of information" );
00715             }
00716             if( $useStandardOptions['root'] )
00717             {
00718                 $generalOptionList[] = array( '-r,--allow-root-user', "Allows the script to be run by the root user" );
00719             }
00720         }
00721         $description = $this->Description;
00722         $helpText =  "Usage: " . $program;
00723         if ( count( $optionList ) > 0 or count( $generalOptionList ) > 0 )
00724         {
00725             $helpText .= " [OPTION]...";
00726         }
00727         if ( $argumentConfig && isset( $argumentConfig['list'] ) && is_array( $argumentConfig['list'] ) )
00728         {
00729             foreach ( $argumentConfig['list'] as $argumentItem )
00730             {
00731                 $argumentName = strtoupper( $argumentItem['name'] );
00732                 $quantifier = $argumentItem['quantifier'];
00733                 if ( $quantifier['min'] > 1 or $quantifier['max'] === false or $quantifier['max'] > 1 )
00734                     $helpText .= " [$argumentName]...";
00735                 else
00736                     $helpText .= " [$argumentName]";
00737             }
00738         }
00739         if ( $description )
00740             $helpText .= "\n" . $description . "\n";
00741         if ( count( $generalOptionList ) > 0 )
00742         {
00743             $helpText .= "\nGeneral options:\n";
00744             $maxLength = 0;
00745             foreach ( $generalOptionList as $optionItem )
00746             {
00747                 $maxLength = max( strlen( $optionItem[0] ), $maxLength );
00748             }
00749             $spacingLength = $maxLength + 2;
00750             foreach ( $generalOptionList as $optionItem )
00751             {
00752                 $option = $optionItem[0];
00753                 $optionDescription = $optionItem[1];
00754                 $optionLines = explode( "\n", $option );
00755                 $optionDescriptionLines = explode( "\n", $optionDescription );
00756                 $count = max( count( $optionLines ), count( $optionDescriptionLines ) );
00757                 for ( $i = 0; $i < $count; ++$i )
00758                 {
00759                     $optionText = '';
00760                     if ( isset( $optionLines[$i] ) )
00761                         $optionText = $optionLines[$i];
00762                     $optionDescriptionText = '';
00763                     if ( isset( $optionDescriptionLines[$i] ) )
00764                         $optionDescriptionText = $optionDescriptionLines[$i];
00765                     $spacing = $spacingLength - strlen( $optionText );
00766                     if ( $optionText or $optionDescriptionText )
00767                         $helpText .= '  ';
00768                     $helpText .= $optionText;
00769                     if ( $i > 0 )
00770                         $spacing += 2;
00771                     if ( $optionDescriptionText )
00772                         $helpText .= str_repeat( ' ', $spacing ) . $optionDescriptionText;
00773                     $helpText .= "\n";
00774                 }
00775             }
00776         }
00777         if ( count( $optionList ) > 0 )
00778         {
00779             $helpText .= "\nOptions:\n";
00780             $maxLength = 0;
00781             foreach ( $optionList as $optionItem )
00782             {
00783                 $maxLength = max( strlen( $optionItem[0] ), $maxLength );
00784             }
00785             $spacingLength = $maxLength + 2;
00786             foreach ( $optionList as $optionItem )
00787             {
00788                 $option = $optionItem[0];
00789                 $optionDescription = $optionItem[1];
00790                 $optionLines = explode( "\n", $option );
00791                 $optionDescriptionLines = explode( "\n", $optionDescription );
00792                 $count = max( count( $optionLines ), count( $optionDescriptionLines ) );
00793                 for ( $i = 0; $i < $count; ++$i )
00794                 {
00795                     $optionText = '';
00796                     if ( isset( $optionLines[$i] ) )
00797                         $optionText = $optionLines[$i];
00798                     $optionDescriptionText = '';
00799                     if ( isset( $optionDescriptionLines[$i] ) )
00800                         $optionDescriptionText = $optionDescriptionLines[$i];
00801                     $spacing = $spacingLength - strlen( $optionText );
00802                     if ( $optionText or $optionDescriptionText )
00803                         $helpText .= '  ';
00804                     $helpText .= $optionText;
00805                     if ( $i > 0 )
00806                         $spacing += 2;
00807                     if ( $optionDescriptionText )
00808                         $helpText .= str_repeat( ' ', $spacing ) . $optionDescriptionText;
00809                     $helpText .= "\n";
00810                 }
00811             }
00812         }
00813         $cli->output( $helpText );
00814     }
00815 
00816     /*!
00817      Parse command line into options array. If stanadrd options are in use, carry
00818      out the associated task (eg. switch siteaccess ir logged-in user)
00819      /param $config see ezcli::parseOptionString
00820      /param $argumentConfig  see ezcli::getOptions (unused for now)
00821      /param $optionHelp string echoed to screen when script invoked with -h/--help
00822      /param $arguments array of arguments. If false, command line is parsed automatically
00823      /param $useStandardOptions true or an array of standard options to be used.
00824        standard options are: 'debug', 'colors', 'log', 'siteaccess', 'verbose', 'user' (false), and can be set to false to be disabled
00825     */
00826     function getOptions( $config = '', $argumentConfig = '', $optionHelp = false,
00827                          $arguments = false, $useStandardOptions = true )
00828     {
00829         if ( is_string( $config ) )
00830             $config = eZCLI::parseOptionString( $config, $tmpConfig );
00831         if ( is_string( $argumentConfig ) )
00832             $argumentConfig = eZCLI::parseOptionString( $argumentConfig, $tmpArgumentConfig );
00833 
00834         if ( $useStandardOptions )
00835         {
00836             if ( !is_array( $useStandardOptions ) )
00837                 $useStandardOptions = array();
00838             $useStandardOptions = array_merge( array( 'debug' => true,
00839                                                       'colors' => true,
00840                                                       'log' => true,
00841                                                       'siteaccess' => true,
00842                                                       'verbose' => true,
00843                                                       'root' => true,
00844                                                       'user' => false ),
00845                                                $useStandardOptions );
00846         }
00847 
00848         if ( $useStandardOptions )
00849         {
00850             $optionConfig = $config;
00851             $excludeOptions = array();
00852             $optionString = "[h|help][q|quiet]";
00853             $excludeOptions[] = 'h';
00854             $excludeOptions[] = 'help';
00855             $excludeOptions[] = 'q';
00856             $excludeOptions[] = 'quiet';
00857             if ( $useStandardOptions['debug'] )
00858             {
00859                 $optionString .= "[d;*|debug;*]";
00860                 $excludeOptions[] = 'd';
00861                 $excludeOptions[] = 'debug';
00862             }
00863             if ( $useStandardOptions['colors'] )
00864             {
00865                 $optionString .= "[c|colors][no-colors]";
00866                 $excludeOptions[] = 'c';
00867                 $excludeOptions[] = 'colors';
00868                 $excludeOptions[] = 'no-colors';
00869             }
00870             if ( $useStandardOptions['log'] )
00871             {
00872                 $optionString .= "[logfiles][no-logfiles]";
00873                 $excludeOptions[] = 'logfiles';
00874                 $excludeOptions[] = 'no-logfiles';
00875             }
00876             if ( $useStandardOptions['siteaccess'] )
00877             {
00878                 $optionString .= "[s:|siteaccess:]";
00879                 $excludeOptions[] = 's';
00880                 $excludeOptions[] = 'siteaccess';
00881             }
00882             if ( $useStandardOptions['user'] )
00883             {
00884                 $optionString .= "[l:|login:][p:|password:]";
00885                 $excludeOptions[] = 'l';
00886                 $excludeOptions[] = 'login';
00887                 $excludeOptions[] = 'p';
00888                 $excludeOptions[] = 'password';
00889             }
00890             if ( $useStandardOptions['verbose'] )
00891             {
00892                 $optionString .= "[v*|verbose*]";
00893                 $excludeOptions[] = 'v';
00894                 $excludeOptions[] = 'verbose';
00895             }
00896             if( $useStandardOptions['root'] )
00897             {
00898                 $optionString .= "[r?|allow-root-user?]";
00899                 $excludeOptions[] = 'r';
00900                 $excludeOptions[] = 'allow-root-user';
00901             }
00902 
00903             $config = eZCLI::parseOptionString( $optionString, $optionConfig );
00904         }
00905         $cli = eZCLI::instance();
00906         $options = $cli->getOptions( $config, $argumentConfig, $arguments );
00907         $this->CurrentOptionConfig = $config;
00908         $this->CurrentOptions = $options;
00909         $this->CurrentStandardOptions = $useStandardOptions;
00910         $this->CurrentExcludeOptions = $excludeOptions;
00911         $this->CurrentOptionHelp = $optionHelp;
00912         $this->ArgumentConfig = $argumentConfig;
00913         if ( !$options )
00914         {
00915             if ( !$this->IsInitialized )
00916                 $this->initialize();
00917             $this->shutdown( 1 );
00918         }
00919 
00920         if ( $useStandardOptions )
00921         {
00922             if ( function_exists( 'posix_getuid' ) )
00923             {
00924                 if( posix_getuid() === 0 )
00925                 {
00926                     if( !$options['allow-root-user'] )
00927                     {
00928                         $cli->warning( "Running scripts as root may be dangerous." );
00929                         $cli->warning( "If you think you know what you are doing, you can run this script with the " );
00930                         $cli->warning( "root account by appending the parameter --allow-root-user." );
00931 
00932                         exit( 1 );
00933                     }
00934                     else
00935                     {
00936                         // ho no, you are not going to be quiet while
00937                         // running with root priviledges
00938                         $this->setIsQuiet( false );
00939 
00940                         $cli = eZCLI::instance();
00941 
00942                         $cli->warning( 'With great power comes great responsibility.' );
00943                         $cli->warning( "You have 10 seconds to break the script (press Ctrl-C)." );
00944                         sleep( 10 );
00945                     }
00946                 }
00947             }
00948 
00949             if ( $options['quiet'] )
00950                 $this->setIsQuiet( true );
00951             $useColors = true;
00952             if ( $options['colors'] )
00953                 $useColors = true;
00954             if ( $options['no-colors'] )
00955                 $useColors = false;
00956             $cli->setUseStyles( $useColors );
00957             if ( $options['debug'] )
00958             {
00959                 $levels = array();
00960                 foreach ( $options['debug'] as $debugOption )
00961                 {
00962                     $levels = array_merge( $levels, explode( ',', $debugOption ) );
00963                 }
00964                 $allowedDebugLevels = array();
00965                 $useDebugAccumulators = false;
00966                 $useDebugTimingpoints = false;
00967                 $useIncludeFiles = false;
00968                 foreach ( $levels as $level )
00969                 {
00970                     if ( $level == 'all' )
00971                     {
00972                         $useDebugAccumulators = true;
00973                         $allowedDebugLevels = false;
00974                         $useDebugTimingpoints = true;
00975                         break;
00976                     }
00977                     if ( $level == 'accumulator' )
00978                     {
00979                         $useDebugAccumulators = true;
00980                         continue;
00981                     }
00982                     if ( $level == 'timing' )
00983                     {
00984                         $useDebugTimingpoints = true;
00985                         continue;
00986                     }
00987                     if ( $level == 'include' )
00988                     {
00989                         $useIncludeFiles = true;
00990                     }
00991                     if ( $level == 'strict' )
00992                         $level = eZDebug::LEVEL_STRICT;
00993                     else if ( $level == 'error' )
00994                         $level = eZDebug::LEVEL_ERROR;
00995                     else if ( $level == 'warning' )
00996                         $level = eZDebug::LEVEL_WARNING;
00997                     else if ( $level == 'debug' )
00998                         $level = eZDebug::LEVEL_DEBUG;
00999                     else if ( $level == 'notice' )
01000                         $level = eZDebug::LEVEL_NOTICE;
01001                     else if ( $level == 'timing' )
01002                         $level = eZDebug::LEVEL_TIMING_POINT;
01003                     $allowedDebugLevels[] = $level;
01004                 }
01005                 $this->setUseDebugOutput( true );
01006                 $this->setAllowedDebugLevels( $allowedDebugLevels );
01007                 $this->setUseDebugAccumulators( $useDebugAccumulators );
01008                 $this->setUseDebugTimingPoints( $useDebugTimingpoints );
01009                 $this->setUseIncludeFiles( $useIncludeFiles );
01010                 $this->setDebugMessage( "\n\n" . str_repeat( '#', 36 ) . $cli->style( 'emphasize' ) . " DEBUG " . $cli->style( 'emphasize-end' )  . str_repeat( '#', 36 ) . "\n" );
01011             }
01012             if ( count( $options['verbose'] ) > 0 )
01013             {
01014                 $this->setShowVerboseOutput( count( $options['verbose'] ) );
01015             }
01016 
01017             if ( isset( $options['siteaccess'] ) and $options['siteaccess'] )
01018                 $this->setUseSiteAccess( $options['siteaccess'] );
01019 
01020             if ( $options['help'] )
01021             {
01022                 if ( !$this->IsInitialized )
01023                     $this->initialize();
01024                 $this->showHelp();
01025                 $this->shutdown( 0 );
01026             }
01027 
01028             if ( isset( $options['login'] ) and $options['login'] )
01029                 $this->setUser( $options['login'], isset( $options['password'] ) ? $options['password'] : false );
01030         }
01031         return $options;
01032     }
01033 
01034     /**
01035      * Returns a shared instance of the eZScript class.
01036      *
01037      * @param array $settings Used by the first generated instance, but ignored for subsequent calls.
01038      * @return eZScript
01039      */
01040     static function instance( $settings = array() )
01041     {
01042         if ( !isset( $GLOBALS['eZScriptInstance'] ) or
01043              !( $GLOBALS['eZScriptInstance'] instanceof eZScript ) )
01044         {
01045             $GLOBALS['eZScriptInstance'] = new eZScript( $settings );
01046         }
01047         return $GLOBALS['eZScriptInstance'];
01048     }
01049 
01050     /*!
01051      \static
01052      Reads settings from site.ini and passes them to eZDebug.
01053     */
01054     function updateDebugSettings( $useDebug = null )
01055     {
01056         global $debugOutput;
01057         global $useLogFiles;
01058         $ini = eZINI::instance();
01059         $cli = eZCLI::instance();
01060         $debugSettings = array();
01061         $debugSettings['debug-enabled'] = ( $ini->variable( 'DebugSettings', 'DebugOutput' ) == 'enabled' and
01062                                             $ini->variable( 'DebugSettings', 'ScriptDebugOutput' ) == 'enabled' );
01063         if ( $useDebug !== null )
01064             $debugSettings['debug-enabled'] = $useDebug;
01065         $debugSettings['debug-by-ip'] = $ini->variable( 'DebugSettings', 'DebugByIP' ) == 'enabled';
01066         $debugSettings['debug-ip-list'] = $ini->variable( 'DebugSettings', 'DebugIPList' );
01067         if ( isset( $debugOutput ) )
01068             $debugSettings['debug-enabled'] = $debugOutput;
01069         $debugSettings['debug-log-files-enabled'] = $useLogFiles;
01070         if ( $cli->useStyles() and
01071              !$cli->isWebOutput() )
01072         {
01073             $debugSettings['debug-styles'] = $cli->terminalStyles();
01074         }
01075         $logList = $ini->variable( 'DebugSettings', 'AlwaysLog' );
01076         $logMap = array( 'notice' => eZDebug::LEVEL_NOTICE,
01077                          'warning' => eZDebug::LEVEL_WARNING,
01078                          'error' => eZDebug::LEVEL_ERROR,
01079                          'debug' => eZDebug::LEVEL_DEBUG,
01080                          'strict' => eZDebug::LEVEL_STRICT );
01081         $debugSettings['always-log'] = array();
01082         foreach ( $logMap as $name => $level )
01083         {
01084             $debugSettings['always-log'][$level] = in_array( $name, $logList );
01085         }
01086         eZDebug::updateSettings( $debugSettings );
01087     }
01088 
01089     /*!
01090      \static
01091      Reads settings from i18n.ini and passes them to eZTextCodec.
01092     */
01093     function updateTextCodecSettings()
01094     {
01095         $ini = eZINI::instance( 'i18n.ini' );
01096         $i18nSettings = array();
01097         $i18nSettings['internal-charset'] = $ini->variable( 'CharacterSettings', 'Charset' );
01098         $i18nSettings['http-charset'] = $ini->variable( 'CharacterSettings', 'HTTPCharset' );
01099         $i18nSettings['mbstring-extension'] = $ini->variable( 'CharacterSettings', 'MBStringExtension' ) == 'enabled';
01100         eZTextCodec::updateSettings( $i18nSettings );
01101     }
01102 
01103     /// \privatesection
01104     public $InitializationErrorMessage;
01105     public $DebugMessage;
01106     public $UseDebugOutput;
01107     public $UseSession;
01108     public $UseExtensions;
01109     public $UseModules;
01110     public $User;
01111     public $SiteAccess;
01112     public $ExitCode;
01113     public $IsQuiet;
01114     public $ShowVerbose;
01115 }
01116 
01117 function eZDBCleanup()
01118 {
01119     if ( class_exists( 'ezdb' )
01120          and eZDB::hasInstance() )
01121     {
01122         $db = eZDB::instance();
01123         $db->setIsSQLOutputEnabled( false );
01124     }
01125 }
01126 
01127 function eZFatalError()
01128 {
01129     $cli = eZCLI::instance();
01130     $endl = $cli->endlineString();
01131     $webOutput = $cli->isWebOutput();
01132     $bold = $cli->style( 'bold' );
01133     $unbold = $cli->style( 'bold-end' );
01134     $par = $cli->style( 'paragraph' );
01135     $unpar = $cli->style( 'paragraph-end' );
01136 
01137     $allowedDebugLevels = true;
01138     $useDebugAccumulators = true;
01139     $useDebugTimingpoints = true;
01140 
01141     eZDebug::setHandleType( eZDebug::HANDLE_NONE );
01142     if ( !$webOutput )
01143         fputs( STDERR, $endl );
01144     fputs( STDERR, $bold . "Fatal error" . $unbold . ": eZ Publish did not finish its request$endl" );
01145     fputs( STDERR, $par . "The execution of eZ Publish was abruptly ended, the debug output is present below." . $unpar . $endl );
01146     fputs( STDERR, eZDebug::printReport( false, $webOutput, true ) );
01147 }
01148 
01149 /*!
01150   Dummy function, required by some scripts in eZ Publish.
01151 */
01152 function eZUpdateDebugSettings( $useDebug = null )
01153 {
01154 }
01155 
01156 /*!
01157   Dummy function, required by some scripts in eZ Publish.
01158 */
01159 function eZUpdateTextCodecSettings()
01160 {
01161 }
01162 
01163 ?>