eZ Publish  [trunk]
ezmodule.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZModule 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  * The eZModule class is used to instanciate and use modules & views.
00013  *
00014  * Loading the "content" module, and running the "history" view
00015  * <code>
00016  * <?php
00017  * $contentModule = eZModule::findModule( 'content' );
00018  * $result = $contentModule->run( 'history', array( 1 ) );
00019  * ?>
00020  * </code>
00021  *
00022  * Running the CopyVersion action of the content/history view:
00023  * <code>
00024  * <?php
00025  * $contentModule = eZModule::findModule( 'content' );
00026  * $contentModule->setCurrentView( 'history' );
00027  * $contentModule->setCurrentAction( 'CopyVersion' );
00028  * // we will copy version 3
00029  * $contentModule->setActionParameter( 'VersionID', 3 );
00030  * $contentModule->run( 'history', array( 20 ) );
00031  * ?>
00032  * </code>
00033  */
00034 
00035 class eZModule
00036 {
00037     /**
00038      * Module execution status: IDLE
00039      * @var int
00040      */
00041     const STATUS_IDLE = 0;
00042 
00043     /**
00044      * Module execution status: OK
00045      * @var int
00046      */
00047     const STATUS_OK = 1;
00048 
00049     /**
00050      * Module execution status: FAILED
00051      * @var int
00052      */
00053     const STATUS_FAILED = 2;
00054 
00055     /**
00056      * Module execution status: REDIRECT
00057      * @var int
00058      */
00059     const STATUS_REDIRECT = 3;
00060 
00061     /**
00062      * Module execution status: RERUN
00063      * @var int
00064      */
00065     const STATUS_RERUN = 4;
00066 
00067     /**
00068      * Hooks execution status: OK
00069      * @var int
00070      */
00071     const HOOK_STATUS_OK = 0;
00072 
00073     /**
00074      * Hooks execution status: CANCEL_RUN
00075      * @var int
00076      */
00077     const HOOK_STATUS_CANCEL_RUN = 1;
00078 
00079     /**
00080      * Hooks execution status: FAILED
00081      * @var int
00082      */
00083     const HOOK_STATUS_FAILED = 2;
00084 
00085     /**
00086      * Constructor. Initializes the module.
00087      *
00088      * @param string $path
00089      *        Relative path to the module, without the module name
00090      * @param string $file
00091      *        Relative path to the module definition file module.php
00092      * @param string $moduleName
00093      * @param boolean $checkFileExistence
00094      *        Always set to false in the current code base, since the check is
00095      *        usually performed before the constructor is called
00096      */
00097     function eZModule( $path, $file, $moduleName, $checkFileExistence = true )
00098     {
00099         $this->initialize( $path, $file, $moduleName, $checkFileExistence);
00100     }
00101 
00102     /**
00103      * Initializes the module object.
00104      *
00105      * @param string $path
00106      *        Directory where the module is declared, without the modulename
00107      *        component
00108      * @param string $file
00109      *        Full (relative) path to the module.php file describing the module
00110      * @param string $moduleName
00111      *        The module name (content, user...)
00112      * @param bool $checkFileExistence
00113      *        Wether or not $file's existence should be checked
00114      * @return void
00115      */
00116     function initialize( $path, $file, $moduleName, $checkFileExistence = true )
00117     {
00118         if ( $checkFileExistence === false || file_exists( $file ) )
00119         {
00120             unset( $FunctionList );
00121             unset( $Module );
00122             unset( $ViewList );
00123             include( $file );
00124             $this->Functions = $ViewList;
00125             if ( isset( $FunctionList ) and
00126                  is_array( $FunctionList ) and
00127                  count( $FunctionList ) > 0 )
00128             {
00129                 ksort( $FunctionList, SORT_STRING );
00130                 $this->FunctionList = $FunctionList;
00131             }
00132             else
00133             {
00134                 $this->FunctionList = array();
00135             }
00136             if ( empty( $Module ) )
00137             {
00138                 $Module = array( "name" => "null",
00139                                  "variable_params" => false,
00140                                  "function" => array() );
00141             }
00142             $this->Module = $Module;
00143             $this->Name = $moduleName;
00144             $this->Path = $path;
00145             $this->Title = "";
00146             $this->UIContext = 'navigation';
00147             $this->UIComponent = $moduleName;
00148 
00149             $uiComponentMatch = 'module';
00150             if ( isset( $this->Module['ui_component_match'] ) )
00151             {
00152                 $uiComponentMatch = $this->Module['ui_component_match'];
00153             }
00154             $this->UIComponentMatch = $uiComponentMatch;
00155 
00156             foreach( $this->Functions as $key => $dummy)
00157             {
00158                 $this->Functions[$key]["uri"] = "/$moduleName/$key";
00159             }
00160         }
00161         else
00162         {
00163             $this->Functions = array();
00164             $this->Module = array( "name" => "null",
00165                                    "variable_params" => false,
00166                                    "function" => array() );
00167             $this->Name = $moduleName;
00168             $this->Path = $path;
00169             $this->Title = "";
00170             $this->UIContext = 'navigation';
00171             $this->UIComponent = $moduleName;
00172             $this->UIComponentMatch = 'module';
00173         }
00174         $this->HookList = array();
00175         $this->ExitStatus = eZModule::STATUS_IDLE;
00176         $this->ErrorCode = 0;
00177         $this->ViewActions = array();
00178         $this->OriginalParameters = null;
00179         $this->UserParameters = array();
00180 
00181         // Load in navigation part overrides
00182         $ini = eZINI::instance( 'module.ini' );
00183         $this->NavigationParts = $ini->variable( 'ModuleOverrides', 'NavigationPart' );
00184     }
00185 
00186     /**
00187      * Returns the module's URI (/content, /user...)
00188      * @return string The module's URI
00189      *
00190      * @see functionURI()
00191      */
00192     function uri()
00193     {
00194         return "/" . $this->Name;
00195     }
00196 
00197     /**
00198      * Returns the URI to a module's function
00199      *
00200      * @param string $function The function to return the URI for
00201      * @return string|null
00202      *         - the function's URI (content/edit, user/login, etc)
00203      *         - if $function is empty or the module is a singleView one,
00204      *           the module's uri (content/, user/...)
00205      *         - null if the function's not found
00206      *
00207      * @see uri()
00208      */
00209     function functionURI( $function )
00210     {
00211         if ( $this->singleFunction() or
00212              $function == '' )
00213             return $this->uri();
00214         if ( isset( $this->Functions[$function] ) )
00215             return $this->Functions[$function]["uri"];
00216         else
00217             return null;
00218     }
00219 
00220     /**
00221      * Returns the title of the last ran view. Normally set by the view itself,
00222      * and displayed as the page's title
00223      *
00224      * @return string
00225      *
00226      * @see setTitle()
00227      */
00228     function title()
00229     {
00230         return $this->Title;
00231     }
00232 
00233     /**
00234      * Sets the current view for the module to \a $title.
00235      *
00236      * @param string $title The title to be set
00237      *
00238      * @see title()
00239      */
00240     function setTitle( $title )
00241     {
00242         $this->Title = $title;
00243     }
00244 
00245     /**
00246      * Sets the name of the currently running module. The URIs will be updated
00247      * accordingly
00248      *
00249      * @param string $name The name to be set
00250      *
00251      * @return void
00252      *
00253      * @see uri(), functionURI()
00254      */
00255     function setCurrentName( $name )
00256     {
00257         $this->Name = $name;
00258         foreach( $this->Functions as $key => $dummy )
00259         {
00260             $this->Functions[$key]["uri"] = "/$name/$key";
00261         }
00262     }
00263 
00264     /**
00265      * Sets the currently executed view
00266      *
00267      * @param string $name The view name
00268      *
00269      * @return void
00270      *
00271      * @see currentView()
00272      */
00273     function setCurrentView( $name )
00274     {
00275         $GLOBALS['eZModuleCurrentView'] = $name;
00276     }
00277 
00278     /**
00279      * Checks if the module is a single view one
00280      * @return bool
00281      */
00282     function singleFunction()
00283     {
00284         return count( $this->Functions ) == 0;
00285     }
00286 
00287     /**
00288      * Returns the UI context
00289      * @return string The current UI context. Default: 'navigation'
00290      *
00291      * @see setUIContextName()
00292      */
00293     function uiContextName()
00294     {
00295         return $this->UIContext;
00296     }
00297 
00298     /**
00299      * Returns the UI component, by default the module name
00300      *
00301      * @return string The current UI component
00302      *
00303      * @see setUIComponentName()
00304      */
00305     function uiComponentName()
00306     {
00307         return $this->UIComponent;
00308     }
00309 
00310     /**
00311      * Sets the current context
00312      *
00313      * @param string $context The new context string
00314      *
00315      * @see uiContextName()
00316      *
00317      * @return void
00318      */
00319     function setUIContextName( $context )
00320     {
00321         $this->UIContext = $context;
00322     }
00323 
00324     /**
00325      * Sets the current component name
00326      *
00327      * @param string $component The new component name
00328      *
00329      * @see uiComponentName()
00330      *
00331      * @return void
00332      */
00333     function setUIComponentName( $component )
00334     {
00335         $this->UIComponent = $component;
00336     }
00337 
00338     /**
00339      * Returns the last exit status after a view has been executed
00340      *
00341      * @return int one of STATUS_* constants
00342      *
00343      * @see setExitStatus()
00344      */
00345     function exitStatus()
00346     {
00347         return $this->ExitStatus;
00348     }
00349 
00350     /**
00351      * Sets the exit status. This status will be used to inform the user,
00352      * perform a redirection...
00353      *
00354      * @param int $stat One of the eZModule::STATUS_* constants
00355      *
00356      * @see exitStatus()
00357      * @return void
00358      */
00359     function setExitStatus( $stat )
00360     {
00361         $this->ExitStatus = $stat;
00362     }
00363 
00364     /**
00365      * Returns the last error code. An error should only be returned if the
00366      * module's status is eZModule::STATUS_FAILED
00367      *
00368      * @return int The error code, or 0 if no error occured
00369      *
00370      * @see setErrorCode(), exitStatus(), setExitStatus()
00371      */
00372     function errorCode()
00373     {
00374         return $this->ErrorCode;
00375     }
00376 
00377     /**
00378      * Sets the current error code.
00379      * @note For the error code to be used, the module's status needs to be set
00380      *       to eZModule::STATUS_FAILED
00381      * @see setExitStatus(), errorCode()
00382      * @return void
00383      */
00384     function setErrorCode( $errorCode )
00385     {
00386         $this->ErrorCode = $errorCode;
00387     }
00388 
00389     /**
00390      * Returns the error module which will be ran if an error occurs
00391      *
00392      * @return array the error module name (keys: module, view)
00393      *
00394      * @see handleError()
00395      */
00396     function errorModule()
00397     {
00398         if ( !isset( $GLOBALS['eZModuleGlobalErrorModule'] ) )
00399             $GLOBALS['eZModuleGlobalErrorModule'] = array( 'module' => 'error',
00400                                         'view' => 'view' );
00401         return $GLOBALS['eZModuleGlobalErrorModule'];
00402     }
00403 
00404     /**
00405      * Sets the module to be used to handle errors
00406      *
00407      * @param string $moduleName
00408      * @param string $viewName
00409      *
00410      * @see handleError(), errorModule()
00411      */
00412     function setErrorModule( $moduleName, $viewName )
00413     {
00414         $GLOBALS['eZModuleGlobalErrorModule'] = array( 'module' => $moduleName,
00415                                                        'view' => $viewName );
00416     }
00417 
00418     /**
00419      * Runs the defined error module
00420      * Sets the state of the module object to \c failed and sets the error code.
00421      *
00422      * @param mixed $errorCode
00423      * @param mixed $errorType
00424      * @param array $parameters
00425      * @param mixed $userParameters
00426      *
00427      * @see setErrorModule(), errorModule()
00428      */
00429     function handleError( $errorCode, $errorType = false, $parameters = array(), $userParameters = false )
00430     {
00431         if ( !$errorType )
00432         {
00433             eZDebug::writeWarning( "No error type specified for error code $errorCode, assuming kernel.\nA specific error type should be supplied, please check your code.", __METHOD__ );
00434             $errorType = 'kernel';
00435         }
00436         $errorModule = $this->errorModule();
00437 
00438         $module = eZModule::findModule( $errorModule['module'], $this );
00439 
00440         if ( $module === null )
00441         {
00442             return false;
00443         }
00444 
00445         $result = $module->run( $errorModule['view'], array( $errorType, $errorCode, $parameters, $userParameters ) );
00446         // The error module may want to redirect to another URL, see error.ini
00447         if ( $this->exitStatus() != eZModule::STATUS_REDIRECT and
00448              $this->exitStatus() != eZModule::STATUS_RERUN )
00449         {
00450             $this->setExitStatus( eZModule::STATUS_FAILED );
00451             $this->setErrorCode( $errorCode );
00452         }
00453         return $result;
00454     }
00455 
00456     /**
00457      * Redirects to another module / view
00458      *
00459      * @note Use redirectModule() If the target module object is already available
00460      * @note Use redirectToView() if you want to redirect to another view in the same module
00461      *
00462      * @see redirectionURI(), redirectModule(), redirectToView()
00463      *
00464      * @param string $moduleName Target module name
00465      * @param string $viewName Target view name
00466      * @param array $parameters View parameters array
00467      * @param array $unorderedParameters Unordered parameters array
00468      * @param array $userParameters User parameters array
00469      * @param string $anchor Anchor to use in the redirection (prepended to the URL)
00470      *
00471      * @return bool true if the redirection was performed, false if the module wasn't found
00472      */
00473     function redirect( $moduleName, $viewName, $parameters = array(),
00474                        $unorderedParameters = null, $userParameters = false,
00475                        $anchor = false )
00476     {
00477         $module = eZModule::exists( $moduleName );
00478         if ( $module )
00479         {
00480             return $this->redirectModule( $module, $viewName, $parameters,
00481                                           $unorderedParameters, $userParameters, $anchor );
00482         }
00483         else
00484         {
00485             eZDebug::writeError( 'Undefined module: ' . $moduleName, __METHOD__ );
00486         }
00487         return false;
00488     }
00489 
00490     /**
00491      * Redirects to another view in the current module
00492      *
00493      * @see redirectionURI(), redirectModule(), redirect()
00494      *
00495      * @param string $viewName Target view name
00496      * @param array $parameters View parameters
00497      * @param array $unorderedParameters Unordered view parameters
00498      * @param array $userParameters User parameters
00499      * @param string $anchor Redirection URI anchor
00500      *
00501      * @return boolean true if successful, false if the view isn't found
00502      */
00503     function redirectToView( $viewName = '', $parameters = array(),
00504                              $unorderedParameters = null, $userParameters = false,
00505                              $anchor = false )
00506     {
00507         return $this->redirectModule( $this, $viewName, $parameters,
00508                                       $unorderedParameters, $userParameters, $anchor );
00509     }
00510 
00511     /**
00512      * Redirects to another module / view.
00513      *
00514      * The difference with redirect is that the $module parameter is an object
00515      * instead of a string
00516      *
00517      * @param eZModule $moduleName Target module name
00518      * @param string $viewName Target view name
00519      * @param array $parameters View parameters array
00520      * @param array $unorderedParameters Unordered parameters array
00521      * @param array $userParameters User parameters array
00522      * @param string $anchor Redirection URI anchor
00523      *
00524      * @return boolean true. Just true.
00525      *
00526      * @todo Deprecate; have redirect() check if $module is an eZModule or a string
00527      */
00528     function redirectModule( $module, $viewName, $parameters = array(),
00529                              $unorderedParameters = null, $userParameters = false,
00530                              $anchor = false )
00531     {
00532         $uri = $this->redirectionURIForModule( $module, $viewName, $parameters,
00533                                                $unorderedParameters, $userParameters, $anchor );
00534         $this->redirectTo( $uri );
00535         return true;
00536     }
00537 
00538     /**
00539      * Creates the redirection URI for a given module, view & parameters.
00540      * Unlike redirectionURIForModule(), the $module parameter is the module name
00541      *
00542      * @param string $moduleName Redirection module name
00543      * @param string $viewName Redirection view name
00544      * @param array $parameters View parameters
00545      * @param array $unorderedParameters Unordered parameters
00546      * @param array $userParameters User parameters
00547      * @param string $anchor Redirection URI anchor
00548      *
00549      * @return string|boolean The redirection URI, or false if the module isn't found
00550      *
00551      * @see redirect(), redirectionURIForModule(), redirectToView(), redirectModule()
00552      */
00553     function redirectionURI( $moduleName, $viewName, $parameters = array(),
00554                              $unorderedParameters = null, $userParameters = false,
00555                              $anchor = false )
00556     {
00557         $module = eZModule::exists( $moduleName );
00558         if ( $module )
00559         {
00560             return $this->redirectionURIForModule( $module, $viewName, $parameters,
00561                                                    $unorderedParameters, $userParameters, $anchor );
00562         }
00563         else
00564             eZDebug::writeError( 'Undefined module: ' . $moduleName, __METHOD__ );
00565         return false;
00566     }
00567 
00568     /**
00569      * Creates the redirection URI for the current module, view & parameters
00570      *
00571      * @return string The redirection URI
00572      *
00573      * @see redirectionURIForModule()
00574      */
00575     function currentRedirectionURI()
00576     {
00577         $module = $this;
00578         $viewName = eZModule::currentView();
00579         $parameters = $this->OriginalViewParameters;
00580         $unorderedParameters = $this->OriginalUnorderedParameters;
00581         $userParameters = $this->UserParameters;
00582         return $this->redirectionURIForModule( $module, $viewName, $parameters,
00583                                                $unorderedParameters, $userParameters );
00584     }
00585 
00586     /**
00587      * Redirects to the current module and view, it will use currentRedirectionURI() to
00588      * figure out the URL.
00589      *
00590      * @note By changing using setCurrentName() and setCurrentView() first it is
00591      *       possible to redirect to another module or view with the same
00592      *       parameters.
00593      *
00594      * @see currentRedirectionURI(), redirectTo()
00595      *
00596      * @return void
00597      */
00598     function redirectCurrent()
00599     {
00600         $this->redirectTo( $this->currentRedirectionURI() );
00601     }
00602 
00603     /**
00604      * Creates the redirection URI for a given module, view & parameters.
00605      * Unlike redirectionURI(), the $module parameter is a module object
00606      *
00607      * @param string $moduleName Redirection module name
00608      * @param string $viewName
00609      *        Redirection view name. If empty, the current view will be used
00610      * @param array $parameters View parameters
00611      * @param array $unorderedParameters Unordered parameters
00612      * @param array $userParameters User parameters
00613      * @param string $anchor Redirection URI anchor
00614      *
00615      * @return string|boolean The redirection URI, or false if the module isn't found
00616      *
00617      * @see redirect(), redirectionURIForModule(), redirectToView(), redirectModule()
00618      */
00619     function redirectionURIForModule( $module, $viewName, $parameters = array(),
00620                                       $unorderedParameters = null, $userParameters = false,
00621                                       $anchor = false )
00622     {
00623         if ( $viewName == '' )
00624             $viewName = eZModule::currentView();
00625         $uri = $module->functionURI( $viewName );
00626         $uri .= '/';
00627         $viewParameters = $module->parameters( $viewName );
00628         $parameterIndex = 0;
00629         $unorderedURI = '';
00630         $hasUnorderedParameter = false;
00631         if ( $unorderedParameters !== null )
00632         {
00633             $unorderedViewParameters = $module->unorderedParameters( $viewName );
00634             if ( is_array( $unorderedViewParameters ) )
00635             {
00636                 foreach ( $unorderedViewParameters as $unorderedViewParameterName => $unorderedViewParameterVariable )
00637                 {
00638                     if ( isset( $unorderedParameters[$unorderedViewParameterVariable] ) )
00639                     {
00640                         $unorderedURI .= $unorderedViewParameterName . '/' . $unorderedParameters[$unorderedViewParameterVariable] . '/';
00641                         $hasUnorderedParameter = true;
00642                     }
00643                 }
00644             }
00645         }
00646 
00647         if( !isset( $viewParameters ) )
00648             $viewParameters = array(); // prevent PHP warning below
00649 
00650         foreach ( $viewParameters as $viewParameter )
00651         {
00652             if ( !isset( $parameters[$parameterIndex] ) )
00653             {
00654                 // We don't show a warning anymore since some parameters can be optional
00655                 // In future versions we will need required and optional parameters
00656                 // for modules and give warnings for required ones.
00657 //                 eZDebug::writeWarning( "Missing parameter(s) " . implode( ', ', array_slice( $viewParameters, $parameterIndex ) ) .
00658 //                                        " in view '$viewName'", 'eZModule::redirect' );
00659             }
00660             else
00661                 $uri .= $parameters[$parameterIndex] . '/';
00662             ++$parameterIndex;
00663         }
00664         if ( $hasUnorderedParameter )
00665         {
00666             $uri .= $unorderedURI;
00667         }
00668 
00669         if ( is_array( $userParameters ) )
00670         {
00671             foreach ( $userParameters as $name => $value )
00672             {
00673                 $uri .= '/(' . $name . ')/' . $value;
00674             }
00675         }
00676 
00677         $uri = preg_replace( "#(^.*)(//+)$#", "\$1", $uri );
00678         if ( $anchor !== false )
00679             $uri .= '#' . urlencode( $anchor );
00680         return $uri;
00681     }
00682 
00683     /**
00684      * Returns the defined parameter for a view.
00685      *
00686      * @param string $viewName
00687      *        The view to get parameters for. If not specified, the current view
00688      *        is used
00689      *
00690      * @return array The parameters definition
00691      * @see unorderedParameters(), viewData(), currentView(), currentModule()
00692      */
00693     function parameters( $viewName = '' )
00694     {
00695         if ( $viewName == '' )
00696             $viewName = eZModule::currentView();
00697         $viewData = $this->viewData( $viewName );
00698         if ( isset( $viewData['params'] ) )
00699         {
00700             return $viewData['params'];
00701         }
00702         return null;
00703     }
00704 
00705     /**
00706      * Returns the unordered parameters definition.
00707      *
00708      * @param string $viewName
00709      *        The view to return parameters for. If npt specified, the current
00710      *        view is used
00711      *
00712      * @return the unordered parameter definition for the requested view
00713      *
00714      * @see parameters(), viewData(), currentView(), currentModule()
00715      */
00716     function unorderedParameters( $viewName = '' )
00717     {
00718         if ( $viewName == '' )
00719             $viewName = eZModule::currentView();
00720         $viewData = $this->viewData( $viewName );
00721         if ( isset( $viewData['unordered_params'] ) )
00722         {
00723             return $viewData['unordered_params'];
00724         }
00725         return null;
00726     }
00727 
00728     /**
00729      * Returns data for a view
00730      *
00731      * @param string $viewName
00732      *        The view to return data for. If omited, the current view is used
00733      * @see parameters(), unorderedParameters(), currentView(), currentModule()
00734      *
00735      * @return array
00736      */
00737     function viewData( $viewName = '' )
00738     {
00739         if ( $viewName == '' )
00740             $viewName = eZModule::currentView();
00741         if ( $this->singleFunction() )
00742             $viewData = $this->Module["function"];
00743         else
00744             $viewData = $this->Functions[$viewName];
00745         return $viewData;
00746     }
00747 
00748     /**
00749      * Sets the module to redirect at the end of the execution
00750      *
00751      * @param string $uri the URI to redirect to
00752      *
00753      * @see setRedirectURI(), setExitStatus()
00754      *
00755      * @return void
00756      */
00757     function redirectTo( $uri )
00758     {
00759         $originalURI = $uri;
00760         $uri = preg_replace( "#(^.*)(/+)$#", "\$1", $uri );
00761         if ( strlen( $originalURI ) != 0 and
00762              strlen( $uri ) == 0 )
00763             $uri = '/';
00764         $this->RedirectURI = $uri;
00765         $this->setExitStatus( eZModule::STATUS_REDIRECT );
00766     }
00767 
00768     /**
00769      * Returns the current redirection URI
00770      *
00771      * @return string
00772      *
00773      * @see setRedirectURI()
00774      */
00775     function redirectURI()
00776     {
00777         return $this->RedirectURI;
00778     }
00779 
00780     /**
00781      * Sets the URI which will be redirected to when the function exits
00782      *
00783      * @param string $uri The redirection URI
00784      *
00785      * @return void
00786      */
00787     function setRedirectURI( $uri )
00788     {
00789         $this->RedirectURI = $uri;
00790     }
00791 
00792     /**
00793      * Returns the redirection HTTP status (!)
00794      *
00795      * @see setRedirectStatus();
00796      *
00797      * @return the HTTP Status header
00798      */
00799     function redirectStatus()
00800     {
00801         return $this->RedirectStatus;
00802     }
00803 
00804     /**
00805      * Sets the HTTP status which will be set when redirecting
00806      *
00807      * @param string $status HTTP status
00808      *
00809      * @note The status must be a valid HTTP status with number and text.
00810      */
00811     function setRedirectStatus( $status )
00812     {
00813         $this->RedirectStatus = $status;
00814     }
00815 
00816     /**
00817      * Returns the defined object attributes (as in persistent objects)
00818      *
00819      * @return array the persistent object attributes
00820      */
00821     function attributes()
00822     {
00823         return array( "uri",
00824                       "functions",
00825                       'views',
00826                       "name",
00827                       "path",
00828                       "info",
00829                       "aviable_functions",
00830                       "available_functions" );
00831     }
00832 
00833     /**
00834      * Checks if an attribute exists
00835      *
00836      * @param string $attr Attribute name
00837      *
00838      * @return bool True if the attribute exists, false otherwise
00839      */
00840     function hasAttribute( $attr )
00841     {
00842         return in_array( $attr, $this->attributes() );
00843     }
00844 
00845     /**
00846      * Returns the value of an attribute
00847      *
00848      * @param string $attr Attribute name
00849      *
00850      * @return mixed The attribute value. If the attribute doesn't exist, a
00851      *               warning is thrown, and false is returned
00852      */
00853     function attribute( $attr )
00854     {
00855         switch( $attr )
00856         {
00857             case "uri":
00858                 return $this->uri();
00859                 break;
00860             case "functions":
00861                 return $this->Functions;
00862             case "views":
00863                 return $this->Functions;
00864             case "name":
00865                 return $this->Name;
00866             case "path":
00867                 return $this->Path;
00868             case "info":
00869                 return $this->Module;
00870             case 'aviable_functions':
00871             case 'available_functions':
00872                 return $this->FunctionList;
00873             default:
00874             {
00875                 eZDebug::writeError( "Attribute '$attr' does not exist", __METHOD__ );
00876                 return null;
00877             }
00878             break;
00879         }
00880     }
00881 
00882     /**
00883      * Sets the current action for a view
00884      *
00885      * @param string $actionName The action to make current
00886      * @param string $view
00887      *        The view to set the action for. If omited, the current view is used
00888      *
00889      * @return void
00890      *
00891      * @see currentAction(), isCurrentAction()
00892      */
00893     function setCurrentAction( $actionName, $view = '' )
00894     {
00895         if ( $view == '' )
00896             $view = eZModule::currentView();
00897         if ( $view == '' or $actionName == '' )
00898             return false;
00899         $this->ViewActions[$view] = $actionName;
00900     }
00901 
00902     /**
00903      * Returns the current action name.
00904      *
00905      * If the current action is not yet determined it will use the definitions in
00906      * module.php in order to find out the current action. It first looks trough
00907      * the \c single_post_actions array in the selected view mode, the key to
00908      * each element is the name of the post-variable to match, if it matches the
00909      * element value is set as the action.
00910      * \code
00911      * 'single_post_actions' => array( 'PreviewButton' => 'Preview',
00912      *                                 'PublishButton' => 'Publish' )
00913      * \endcode
00914      * If none of these matches it will use the elements from the \c post_actions
00915      * array to find a match. It uses the element value for each element to match
00916      * agains a post-variable, if it is found the contents of the post-variable
00917      * is set as the action.
00918      * \code
00919      * 'post_actions' => array( 'BrowseActionName' )
00920      * \endcode
00921      *
00922      * @return string The current action, or false if not set nor found
00923      *
00924      * @see setCurrentAction(), isCurrentAction()
00925      */
00926     function currentAction( $view = '' )
00927     {
00928         if ( $view == '' )
00929             $view = eZModule::currentView();
00930         if ( isset( $this->ViewActions[$view] ) )
00931             return $this->ViewActions[$view];
00932         $http = eZHTTPTool::instance();
00933         if ( isset( $this->Functions[$view]['default_action'] ) )
00934         {
00935             $defaultAction = $this->Functions[$view]['default_action'];
00936             foreach ( $defaultAction as $defaultActionStructure )
00937             {
00938                 $actionName = $defaultActionStructure['name'];
00939                 $type = $defaultActionStructure['type'];
00940                 if ( $type == 'post' )
00941                 {
00942                     $parameters = array();
00943                     if ( isset( $defaultActionStructure['parameters'] ) )
00944                         $parameters = $defaultActionStructure['parameters'];
00945                     $hasParameters = true;
00946                     foreach ( $parameters as $parameterName )
00947                     {
00948                         if ( !$http->hasPostVariable( $parameterName ) )
00949                         {
00950                             $hasParameters = false;
00951                             break;
00952                         }
00953                     }
00954                     if ( $hasParameters )
00955                     {
00956                         $this->ViewActions[$view] = $actionName;
00957                         return $this->ViewActions[$view];
00958                     }
00959                 }
00960                 else
00961                 {
00962                     eZDebug::writeWarning( 'Unknown default action type: ' . $type, __METHOD__ );
00963                 }
00964             }
00965         }
00966         if ( isset( $this->Functions[$view]['single_post_actions'] ) )
00967         {
00968             $singlePostActions = $this->Functions[$view]['single_post_actions'];
00969             foreach( $singlePostActions as $postActionName => $realActionName )
00970             {
00971                 if ( $http->hasPostVariable( $postActionName ) )
00972                 {
00973                     $this->ViewActions[$view] = $realActionName;
00974                     return $this->ViewActions[$view];
00975                 }
00976             }
00977         }
00978         if ( isset( $this->Functions[$view]['post_actions'] ) )
00979         {
00980             $postActions = $this->Functions[$view]['post_actions'];
00981             foreach( $postActions as $postActionName )
00982             {
00983                 if ( $http->hasPostVariable( $postActionName ) )
00984                 {
00985                     $this->ViewActions[$view] = $http->postVariable( $postActionName );
00986                     return $this->ViewActions[$view];
00987                 }
00988             }
00989         }
00990 
00991         $this->ViewActions[$view] = false;
00992         return false;
00993     }
00994 
00995     /**
00996      * Sets an action parameter value
00997      *
00998      * @param string $parameterName
00999      * @param mixed $parameterValue
01000      * @param string $view
01001      *        The view to set the action parameter for. If omited, the current
01002      *        view is used
01003      * @return void
01004      * @see actionParameter(), hasActionParameter()
01005      */
01006     function setActionParameter( $parameterName, $parameterValue, $view = '' )
01007     {
01008         if ( $view == '' )
01009             $view = eZModule::currentView();
01010         $this->ViewActionParameters[$view][$parameterName] = $parameterValue;
01011     }
01012 
01013     /**
01014      * Returns an action parameter value
01015      *
01016      * @param string $parameterName
01017      * @param string $view
01018      *        The view to return the parameter for. If omited, uses the current view
01019      *
01020      * @return mixed The parameter value, or null + error if not found
01021      * @see setActionParameter(), hasActionParameter()
01022      */
01023     function actionParameter( $parameterName, $view = '' )
01024     {
01025         if ( $view == '' )
01026             $view = eZModule::currentView();
01027         if ( isset( $this->ViewActionParameters[$view][$parameterName] ) )
01028             return $this->ViewActionParameters[$view][$parameterName];
01029         $currentAction = $this->currentAction( $view );
01030         $http = eZHTTPTool::instance();
01031         if ( isset( $this->Functions[$view]['post_action_parameters'][$currentAction] ) )
01032         {
01033             $postParameters = $this->Functions[$view]['post_action_parameters'][$currentAction];
01034             if ( isset( $postParameters[$parameterName] ) &&
01035                  $http->hasPostVariable( $postParameters[$parameterName] ) )
01036             {
01037                 return $http->postVariable( $postParameters[$parameterName] );
01038             }
01039             eZDebug::writeError( "No such action parameter: $parameterName", __METHOD__ );
01040         }
01041         if ( isset( $this->Functions[$view]['post_value_action_parameters'][$currentAction] ) )
01042         {
01043             $postParameters = $this->Functions[$view]['post_value_action_parameters'][$currentAction];
01044             if ( isset( $postParameters[$parameterName] ) )
01045             {
01046                 $postVariables = $http->attribute( 'post' );
01047                 $postVariableNameMatch = $postParameters[$parameterName];
01048                 $regMatch = "/^" . $postVariableNameMatch . "_(.+)$/";
01049                 foreach ( $postVariables as $postVariableName => $postVariableValue )
01050                 {
01051                     if ( preg_match( $regMatch, $postVariableName, $matches ) )
01052                     {
01053                         $parameterValue = $matches[1];
01054                         $this->ViewActionParameters[$view][$parameterName] = $parameterValue;
01055                         return $parameterValue;
01056                     }
01057                 }
01058                 eZDebug::writeError( "No such action parameter: $parameterName", __METHOD__ );
01059             }
01060         }
01061         return null;
01062     }
01063 
01064     /**
01065      * Checks if an action parameter is defined for a view
01066      *
01067      * @param string $parameterName
01068      * @param string $view
01069      *        The view to check the parameter for. If omited, uses the current view
01070      *
01071      * @return bool
01072      *
01073      * @see setActionParameter(), actionParameter()
01074      */
01075     function hasActionParameter( $parameterName, $view = '' )
01076     {
01077         if ( $view == '' )
01078             $view = eZModule::currentView();
01079         if ( isset( $this->ViewActionParameters[$view][$parameterName] ) )
01080             return true;
01081         $currentAction = $this->currentAction( $view );
01082         $http = eZHTTPTool::instance();
01083         if ( isset( $this->Functions[$view]['post_action_parameters'][$currentAction] ) )
01084         {
01085             $postParameters = $this->Functions[$view]['post_action_parameters'][$currentAction];
01086             if ( isset( $postParameters[$parameterName] ) and
01087                  $http->hasPostVariable( $postParameters[$parameterName] ) )
01088             {
01089                 return true;
01090             }
01091         }
01092         if ( isset( $this->Functions[$view]['post_value_action_parameters'][$currentAction] ) )
01093         {
01094             $postParameters = $this->Functions[$view]['post_value_action_parameters'][$currentAction];
01095             if ( isset( $postParameters[$parameterName] ) )
01096             {
01097                 $postVariables = $http->attribute( 'post' );
01098                 $postVariableNameMatch = $postParameters[$parameterName];
01099                 $regMatch = "/^" . $postVariableNameMatch . "_(.+)$/";
01100                 foreach ( $postVariables as $postVariableName => $postVariableValue )
01101                 {
01102                     if ( preg_match( $regMatch, $postVariableName, $matches ) )
01103                     {
01104                         $parameterValue = $matches[1];
01105                         $this->ViewActionParameters[$view][$parameterName] = $parameterValue;
01106                         return true;
01107                     }
01108                 }
01109             }
01110         }
01111         return false;
01112     }
01113 
01114     /**
01115      * Checks if the current action is the given one
01116      *
01117      * @param string $actionName The action to check
01118      * @param string $view The view to check the action for. Current view if omited.
01119      *
01120      * @return bool
01121      *
01122      * @see currentAction(), setCurrentAction()
01123      */
01124     function isCurrentAction( $actionName, $view = '' )
01125     {
01126         if ( $view == '' )
01127             $view = eZModule::currentView();
01128         if ( $view == '' or $actionName == '' )
01129             return false;
01130         return $this->currentAction( $view ) == $actionName;
01131     }
01132 
01133     /**
01134      * Adds an entry to a hook. The entry is placed before all other existing
01135      * entries (LIFO) unless $append is set to true.
01136      * @param string $hookName
01137      *        The hook name.
01138      * @param string $function
01139      *        Either the name of the function to be run or an array where the
01140      *        first entry is the object and the second is the method name.
01141      * @param integer $priority
01142      *        The hook priority in the hooks stack.
01143      * @param boolean $expandParameters
01144      *        Wether or not to expand parameters. If set to true (default), the
01145      *        parameters will be sent as real function parameters to the hooked
01146      *        function/method. If set to false, they will be sent as a single
01147      *        array.
01148      *        In both cases, the eZModule object will be the first parameter sent
01149      *        to each hook.
01150      * @param boolean $append
01151      *        If set to false (default), the hook will be added at the top of
01152      *        the hooks list. If set to true, it will be added at the end
01153      *
01154      * @return void
01155      */
01156     function addHook( $hookName, $function, $priority = 1, $expandParameters = true, $append = false )
01157     {
01158         $hookEntries = isset( $this->HookList[$hookName] ) ? $this->HookList[$hookName] : false;
01159         if ( !is_array( $hookEntries ) )
01160         {
01161             $hookEntries = array();
01162         }
01163         $entry = array( 'function' => $function,
01164                         'expand_parameters' => $expandParameters );
01165 
01166         $position = $priority;
01167         if ( $append )
01168         {
01169             while ( isset( $hookEntries[$position] ) )
01170                 ++$position;
01171         }
01172         else
01173         {
01174             while ( isset( $hookEntries[$position] ) )
01175                 --$position;
01176         }
01177         $this->HookList[$hookName][$position] = $entry;
01178     }
01179 
01180     /**
01181      * Runs all hooks found in the hook list named $hookName.
01182      *
01183      * @param string $hookName
01184      * @param array $parameters
01185      *        Parameters to provide each function with
01186      *
01187      * @return integer The hook execution status, as one of the eZModule::HOOK_STATUS_*
01188      *         constants:
01189      *         - HOOK_STATUS_OK: means that every hook was executed correctly.
01190      *         - HOOK_STATUS_CANCEL_RUN: execution was cancelled by one hook
01191      *         - HOOK_STATUS_FAILED: only returned if the last hook failed. In
01192      *           any case, a warning is thrown.
01193      *
01194      */
01195     function runHooks( $hookName, $parameters = null )
01196     {
01197         $status = null;
01198         $hookEntries = isset( $this->HookList[$hookName] ) ? $this->HookList[$hookName] : false;
01199         if ( isset( $hookEntries ) and
01200              is_array( $hookEntries ) )
01201         {
01202             ksort( $hookEntries );
01203             foreach ( $hookEntries as $hookEntry )
01204             {
01205                 $function = $hookEntry['function'];
01206                 $expandParameters = $hookEntry['expand_parameters'];
01207                 if ( is_string( $function ) )
01208                 {
01209                     $functionName = $function;
01210                     if ( function_exists( $functionName ) )
01211                     {
01212                         if ( $parameters === null ||
01213                              $expandParameters === null )
01214                         {
01215                             $retVal = $functionName( $this );
01216                         }
01217                         else if ( $expandParameters )
01218                         {
01219                             $retVal = call_user_func_array( $functionName, array_merge( array( $this ), $parameters ) );
01220                         }
01221                         else
01222                         {
01223                             $retVal = $functionName( $this, $parameters );
01224                         }
01225                     }
01226                     else
01227                     {
01228                         eZDebug::writeError( "Unknown hook function '$functionName' in hook: $hookName", __METHOD__ );
01229                     }
01230                 }
01231                 else if ( is_array( $function ) )
01232                 {
01233                     if ( isset( $function[0] ) &&
01234                          isset( $function[1] ) )
01235                     {
01236                         $object = $function[0];
01237                         $functionName = $function[1];
01238                         if ( method_exists( $object, $functionName ) )
01239                         {
01240                             if ( $parameters === null )
01241                             {
01242                                 $retVal = $object->$function( $this );
01243                             }
01244                             else if ( $expandParameters )
01245                             {
01246                                 $retVal = call_user_func_array( array( $object, $functionName ), array_merge( array( $this ), $parameters ) );
01247                             }
01248                             else
01249                             {
01250                                 $retVal = $object->$functionName( $this, $parameters );
01251                             }
01252                         }
01253                         else
01254                         {
01255                             eZDebug::writeError( "Unknown hook method '$functionName' in class '" . strtolower( get_class( $object ) ) . "' in hook: $hookName", __METHOD__ );
01256                         }
01257                     }
01258                     else
01259                     {
01260                         eZDebug::writeError( "Missing data for method handling in hook: $hookName", __METHOD__ );
01261                     }
01262                 }
01263                 else
01264                 {
01265                     eZDebug::writeError( 'Unknown entry type ' . gettype( $function ) . 'in hook: ' . $hookName, __METHOD__ );
01266                 }
01267 
01268                 switch( $retVal )
01269                 {
01270                     case eZModule::HOOK_STATUS_OK:
01271                     {
01272                     } break;
01273 
01274                     case eZModule::HOOK_STATUS_FAILED:
01275                     {
01276                         eZDebug::writeWarning( 'Hook execution failed in hook: ' . $hookName, __METHOD__ );
01277                     } break;
01278 
01279                     case eZModule::HOOK_STATUS_CANCEL_RUN:
01280                     {
01281                         return $retVal;
01282                     } break;
01283                 }
01284             }
01285         }
01286         return $status;
01287     }
01288 
01289     /**
01290      * Sets the view result
01291      *
01292      * @param string $result The (usually HTML) view result
01293      * @param string $view
01294      *        The view to set the result for. If omited, the current view is used
01295      *
01296      * @return void
01297      * @see hasViewResult(), viewResult()
01298      */
01299     function setViewResult( $result, $view = '' )
01300     {
01301         if ( $view == '' )
01302             $view = $this->currentView();
01303         $this->ViewResult[$view] = $result;
01304     }
01305 
01306     /**
01307      * Checks if a view has a result set
01308      *
01309      * @param string $view The view to test for. If omited, uses the current view
01310      * @return bool
01311      */
01312     function hasViewResult( $view = '' )
01313     {
01314         if ( $view == '' )
01315             $view = $this->currentView();
01316         return isset( $this->ViewResult[$view] );
01317     }
01318 
01319     /**
01320      * Returns the view result
01321      *
01322      * @param string $view
01323      *        The view to return the result for, or the current one if omited
01324      *
01325      * @return string|null The view result, or null if not set
01326      */
01327     function viewResult( $view = '' )
01328     {
01329         if ( $view == '' )
01330             $view = $this->currentView();
01331         if ( isset( $this->ViewResult[$view] ) )
01332         {
01333             return $this->ViewResult[$view];
01334         }
01335         return null;
01336     }
01337 
01338     /**
01339      * Forwards the current execution to another module/view with the existing
01340      * parameters.
01341      *
01342      * @param eZModule $module The eZModule object the request will be forwarded to
01343      * @param string $functionName The function to run in that module
01344      * @param array $parameters
01345      *        An array of parameters that will be added to the request. These
01346      *        will be merged with the existing parameters
01347      * @return array The forwarded module/view result
01348      */
01349     function forward( $module, $functionName, $parameters = false )
01350     {
01351         $Return = null;
01352         if ( $module && $functionName )
01353         {
01354             $viewName = eZModule::currentView();
01355 
01356             if ( $parameters === false)
01357             {
01358                 $parameters = array();
01359             }
01360 
01361             $parameters = array_merge( $parameters, $this->OriginalViewParameters );
01362             $unorderedParameters = $this->OriginalUnorderedParameters;
01363             $userParameters = $this->UserParameters;
01364 
01365             $Return = $module->run( $functionName, $parameters, $unorderedParameters, $userParameters );
01366 
01367             // override default navigation part
01368             if ( $Return['is_default_navigation_part'] === true )
01369             {
01370                 if ( $this->singleFunction() )
01371                     $function = $this->Module["function"];
01372                 else
01373                     $function = $this->Functions[$functionName];
01374 
01375                 if ( isset( $function['default_navigation_part'] ) )
01376                 {
01377                     $Return['navigation_part'] = $function['default_navigation_part'];
01378                 }
01379             }
01380 
01381             $this->RedirectURI = $module->redirectURI();
01382             $this->setExitStatus( $module->exitStatus() );
01383         }
01384         return $Return;
01385     }
01386 
01387     /**
01388      * Runs a function in the current module
01389      *
01390      * @param string $functionName The function to run
01391      * @param array $parameters
01392      *         An indexed list of parameters, these will be mapped onto real
01393      *         parameters names using the defined parameters names in the
01394      *         module/function definition.
01395      *         Any unspecified parameter will be assigned null.
01396      * @param array $overrideParameters
01397      *        An asociative array of parameters that will ultimately override
01398      *        what's in $parameters
01399      * @param array $userParameters User (custom view) parameters
01400      *
01401      * @return array The run result
01402      */
01403     function run( $functionName, $parameters = array(), $overrideParameters = false, $userParameters = false )
01404     {
01405         if ( count( $this->Functions ) > 0 and
01406              !isset( $this->Functions[$functionName] ) )
01407         {
01408             eZDebug::writeError( "Undefined view: " . $this->Module["name"] . "::$functionName ",
01409                                  "eZModule" );
01410             $this->setExitStatus( eZModule::STATUS_FAILED );
01411             $Return = null;
01412             return $Return;
01413         }
01414         if ( $this->singleFunction() )
01415             $function = $this->Module["function"];
01416         else
01417             $function = $this->Functions[$functionName];
01418 
01419         $params = array();
01420         $i = 0;
01421         $parameterValues = array();
01422         if ( isset( $function["params"] ) )
01423         {
01424             $functionParameterDefinitions = $function["params"];
01425             foreach ( $functionParameterDefinitions as $param )
01426             {
01427                 if ( isset( $parameters[$i] ) )
01428                 {
01429                     $params[$param] = $parameters[$i];
01430                     $parameterValues[] = $parameters[$i];
01431                 }
01432                 else
01433                 {
01434                     $params[$param] = null;
01435                     $parameterValues[] = null;
01436                 }
01437                 ++$i;
01438             }
01439         }
01440 
01441         $this->ViewParameters = $parameters;
01442         $this->OriginalParameters = $parameters;
01443         $this->OriginalViewParameters = $parameterValues;
01444         $this->NamedParameters = $params;
01445 
01446         $GLOBALS['eZRequestedModuleParams'] = array( 'module_name' => $this->Name,
01447                                                      'function_name' => $functionName,
01448                                                      'parameters' => $params );
01449 
01450         $this->UserParameters = $userParameters;
01451 
01452         if ( isset( $function['ui_context'] ) )
01453         {
01454             $this->UIContext = $function['ui_context'];
01455         }
01456         if ( isset( $function['ui_component'] ) )
01457         {
01458             $this->UIComponent = $function['ui_component'];
01459         }
01460         else if ( $this->UIComponentMatch == 'view' )
01461         {
01462             $this->UIComponent = $functionName;
01463         }
01464 
01465         if ( array_key_exists( 'Limitation', $parameters  ) )
01466         {
01467             $params['Limitation'] =& $parameters[ 'Limitation' ];
01468         }
01469 
01470         // check for unordered parameters and initialize variables if they exist
01471         $unorderedParametersList = array();
01472         $unorderedParameters = array();
01473         if ( isset( $function["unordered_params"] ) )
01474         {
01475             $unorderedParams = $function["unordered_params"];
01476 
01477             foreach ( $unorderedParams as $urlParamName => $variableParamName )
01478             {
01479                 if ( in_array( $urlParamName, $parameters ) )
01480                 {
01481                     $pos = array_search( $urlParamName, $parameters );
01482 
01483                     $params[$variableParamName] = $parameters[$pos + 1];
01484                     $unorderedParameters[$variableParamName] = $parameters[$pos + 1];
01485                     $unorderedParametersList[$variableParamName] = $parameters[$pos + 1];
01486                 }
01487                 else
01488                 {
01489                     $params[$variableParamName] = false;
01490                     $unorderedParameters[$variableParamName] = false;
01491                 }
01492             }
01493         }
01494 
01495         // Loop through user defines parameters
01496         if ( $userParameters !== false )
01497         {
01498             if ( !isset( $params['UserParameters'] ) or
01499                  !is_array( $params['UserParameters'] ) )
01500             {
01501                 $params['UserParameters'] = array();
01502             }
01503 
01504             if ( is_array( $userParameters ) && count( $userParameters ) > 0 )
01505             {
01506                 foreach ( array_keys( $userParameters ) as $paramKey )
01507                 {
01508                     if( isset( $function['unordered_params'] ) &&
01509                         $unorderedParams != null )
01510                     {
01511                         if ( array_key_exists( $paramKey, $unorderedParams ) )
01512                         {
01513                             $params[$unorderedParams[$paramKey]] = $userParameters[$paramKey];
01514                             $unorderedParametersList[$unorderedParams[$paramKey]] = $userParameters[$paramKey];
01515                         }
01516                     }
01517 
01518                     $params['UserParameters'][$paramKey] = $userParameters[$paramKey];
01519                 }
01520             }
01521         }
01522 
01523         $this->OriginalUnorderedParameters = $unorderedParametersList;
01524 
01525         if ( is_array( $overrideParameters ) )
01526         {
01527             foreach ( $overrideParameters as $param => $value )
01528             {
01529                 $params[$param] = $value;
01530             }
01531         }
01532         $params["Module"] = $this;
01533         $params["ModuleName"] = $this->Name;
01534         $params["FunctionName"] = $functionName;
01535         $params["Parameters"] = $parameters;
01536         $params_as_var = isset( $this->Module["variable_params"] ) ? $this->Module["variable_params"] : false;
01537         $this->ExitStatus = eZModule::STATUS_OK;
01538 //        eZDebug::writeNotice( $params, 'module parameters1' );
01539 
01540         $currentView =& $GLOBALS['eZModuleCurrentView'];
01541         $viewStack =& $GLOBALS['eZModuleViewStack'];
01542         if ( !isset( $currentView ) )
01543             $currentView = false;
01544         if ( !isset( $viewStack ) )
01545             $viewStack = array();
01546         if ( is_array( $currentView ) )
01547             $viewStack[] = $currentView;
01548         $currentView = array( 'view' => $functionName,
01549                               'module' => $this->Name );
01550         $Return = eZProcess::run( $this->Path . "/" . $this->Name . "/" . $function["script"],
01551                                   $params,
01552                                   $params_as_var );
01553 
01554         if ( $this->hasViewResult( $functionName ) )
01555         {
01556             $Return = $this->viewResult( $functionName );
01557         }
01558 
01559         if ( count( $viewStack ) > 0 )
01560             $currentView = array_pop( $viewStack );
01561         else
01562             $currentView = false;
01563 
01564         // Check if the module has set the navigation part, if not default to module setting
01565         if ( !isset( $Return['navigation_part'] ) )
01566         {
01567             $Return['is_default_navigation_part'] = true;
01568             if ( isset( $function['default_navigation_part'] ) )
01569                 $Return['navigation_part'] = $function['default_navigation_part'];
01570 
01571         }
01572         else
01573         {
01574             $Return['is_default_navigation_part'] = false;
01575         }
01576 
01577         // Check if we have overrides for navigation part
01578         $viewName = $this->Name . '/' . $functionName;
01579         if ( isset( $this->NavigationParts[$viewName] ) )
01580         {
01581             $Return['is_default_navigation_part'] = false;
01582             $Return['navigation_part'] = $this->NavigationParts[$viewName];
01583         }
01584         else if ( isset( $this->NavigationParts[$this->Name] ) )
01585         {
01586             $Return['is_default_navigation_part'] = false;
01587             $Return['navigation_part'] = $this->NavigationParts[$this->Name];
01588         }
01589 
01590         return $Return;
01591     }
01592 
01593     /**
01594      * Returns the current view name
01595      *
01596      * @return string The current view name, or false if not defined
01597      *
01598      * @note This is a system-wide value
01599      *
01600      * @see currentModule(), setCurrentView()
01601      */
01602     function currentView()
01603     {
01604         $currentView = $GLOBALS['eZModuleCurrentView'];
01605         if ( $currentView !== false )
01606             return $currentView['view'];
01607         return false;
01608     }
01609 
01610     /**
01611      * Returns the current module name
01612      *
01613      * @return string the current module name, or false if not set
01614      *
01615      * @note This is a system-wide value
01616      */
01617     function currentModule()
01618     {
01619         $currentView = $GLOBALS['eZModuleCurrentView'];
01620         if ( $currentView !== false )
01621             return $currentView['module'];
01622         return false;
01623     }
01624 
01625     /**
01626      * Returns the search path list for modules
01627      *
01628      * @return array
01629      *
01630      * @see setGlobalPathList(), addGlobalPathList()
01631      */
01632     static function globalPathList()
01633     {
01634         if ( !isset( $GLOBALS['eZModuleGlobalPathList'] ) )
01635             return null;
01636         return $GLOBALS['eZModuleGlobalPathList'];
01637     }
01638 
01639     /**
01640      * Returns the list of active module repositories, as defined in module.ini
01641      *
01642      * @param boolean $useExtensions
01643      *        If true, module.ini files in extensions will be scanned as well.
01644      *        If false, only the module.ini overrides in settings will be.
01645      *
01646      * @return array a path list of currently active modules
01647      */
01648     static function activeModuleRepositories( $useExtensions = true )
01649     {
01650         $moduleINI = eZINI::instance( 'module.ini' );
01651         $moduleRepositories = $moduleINI->variable( 'ModuleSettings', 'ModuleRepositories' );
01652 
01653         if ( $useExtensions )
01654         {
01655             $extensionRepositories = $moduleINI->variable( 'ModuleSettings', 'ExtensionRepositories' );
01656             $extensionDirectory = eZExtension::baseDirectory();
01657             $activeExtensions = eZExtension::activeExtensions();
01658             $globalExtensionRepositories = array();
01659 
01660             foreach ( $extensionRepositories as $extensionRepository )
01661             {
01662                 $extPath = $extensionDirectory . '/' . $extensionRepository;
01663                 $modulePath = $extPath . '/modules';
01664                 if ( !in_array( $extensionRepository, $activeExtensions ) )
01665                 {
01666                     eZDebug::writeWarning( "Extension '$extensionRepository' was reported to have modules but has not yet been activated.\n" .
01667                                            "Check the setting ModuleSettings/ExtensionRepositories in module.ini for your extensions\n" .
01668                                            "or make sure it is activated in the setting ExtensionSettings/ActiveExtensions in site.ini." );
01669                 }
01670                 else if ( file_exists( $modulePath ) )
01671                 {
01672                     $globalExtensionRepositories[] = $modulePath;
01673                 }
01674                 else if ( !file_exists( $extPath ) )
01675                 {
01676                     eZDebug::writeWarning( "Extension '$extensionRepository' was reported to have modules but the extension itself does not exist.\n" .
01677                                            "Check the setting ModuleSettings/ExtensionRepositories in module.ini for your extensions.\n" .
01678                                            "You should probably remove this extension from the list." );
01679                 }
01680                 else
01681                 {
01682                     eZDebug::writeWarning( "Extension '$extensionRepository' does not have the subdirectory 'modules' allthough it reported it had modules.\n" .
01683                                            "Looked for directory '" . $modulePath . "'\n" .
01684                                            "Check the setting ModuleSettings/ExtensionRepositories in module.ini for your extension." );
01685                 }
01686             }
01687 
01688             $moduleRepositories = array_merge( $moduleRepositories, $globalExtensionRepositories );
01689         }
01690 
01691         return $moduleRepositories;
01692     }
01693 
01694     /**
01695      * Sets the value of the global path list used to search for modules.
01696      * @param array|string $pathList
01697      *        Either an array of path, or a single path as a string
01698      * @return void
01699      * @see addGlobalPathList(), globalPathList()
01700      */
01701     static function setGlobalPathList( $pathList )
01702     {
01703         if ( !is_array( $pathList ) )
01704             $pathList = array( $pathList );
01705         $GLOBALS['eZModuleGlobalPathList'] = $pathList;
01706     }
01707 
01708     /**
01709      * Adds a new entry to the global path list
01710      * @param array|string $pathList
01711      *        Either an array of path or a single path string
01712      * @return void
01713      * @see setGlobalPathList(), globalPathList()
01714      */
01715     static function addGlobalPathList( $pathList )
01716     {
01717         if ( !is_array( $GLOBALS['eZModuleGlobalPathList'] ) )
01718         {
01719             $GLOBALS['eZModuleGlobalPathList'] = array();
01720         }
01721         if ( !is_array( $pathList ) )
01722         {
01723             $pathList = array( $pathList );
01724         }
01725         $GLOBALS['eZModuleGlobalPathList'] = array_merge( $GLOBALS['eZModuleGlobalPathList'], $pathList );
01726     }
01727 
01728     /**
01729      * Loads a module object by name
01730      *
01731      * @param string $moduleName The name of the module to find (ex: content)
01732      * @param array|string
01733      *        Either an array of path or a single path string. These will be
01734      *        used as additionnal locations that will be looked into
01735      * @param boolean $showError
01736      *        If true an error will be shown if the module it not found.
01737      * @return eZModule The eZModule object, or null if the module wasn't found
01738      * @see findModule()
01739      */
01740     static function exists( $moduleName, $pathList = null, $showError = false )
01741     {
01742         $module = null;
01743         return eZModule::findModule( $moduleName, $module, $pathList, $showError );
01744     }
01745 
01746     /**
01747      * Loads a module object by name.
01748      * The only difference with exists() is that the $module parameter will be
01749      * assigned the found module.
01750      *
01751      * @param string $moduleName The name of the module to find (ex: content)
01752      * @param mixed $module This parameter will receive the found module object
01753      * @param array|string
01754      *        Either an array of path or a single path string. These will be
01755      *        used as additionnal locations that will be looked into
01756      * @param boolean $showError
01757      *        If true an error will be shown if the module it not found.
01758      * @return eZModule The eZModule object, or null if the module wasn't found
01759      * @see exists()
01760      */
01761     static function findModule( $moduleName, $module = null, $pathList = null, $showError = false )
01762     {
01763         if ( $pathList === null )
01764             $pathList = array();
01765         else if ( !is_array( $pathList ) )
01766             $pathList = array( $pathList );
01767         $searchPathList = eZModule::globalPathList();
01768         if ( $searchPathList === null )
01769             $searchPathList = array();
01770         $searchPathList = array_merge( $searchPathList, $pathList );
01771         $triedList = array();
01772         $triedDirList = array();
01773         $foundADir = false;
01774         foreach ( $searchPathList as $path )
01775         {
01776             $dir = "$path/$moduleName";
01777             $file = "$dir/module.php";
01778             if ( file_exists( $file ) )
01779             {
01780                 if ( $module === null )
01781                     $module = new eZModule( $path, $file, $moduleName, false );
01782                 else
01783                     $module->initialize( $path, $file, $moduleName, false );
01784                 return $module;
01785             }
01786             else if ( !file_exists( $dir ) )
01787             {
01788                 $triedDirList[] = $dir;
01789             }
01790             else
01791             {
01792                 $foundADir = true;
01793                 $triedList[] = $dir;
01794             }
01795         }
01796 
01797         $msg = "Could not find module named '$moduleName'";
01798         if ( $foundADir )
01799         {
01800             $msg = "\nThese directories had a directory named '$moduleName' but did not contain the module.php file:\n" .
01801                    implode( ", ", $triedList ) . "\n" .
01802                    "This usually means it is missing or has a wrong name.";
01803             if ( count( $triedDirList ) > 0 )
01804                 $msg .= "\n\nThese directories were tried too but none of them exists:\n" . implode( ', ', $triedDirList );
01805         }
01806         else
01807         {
01808             if ( count( $triedDirList ) > 0 )
01809                 $msg.= "\nThese directories were tried but none of them exists:\n" . implode( ", ", $triedDirList );
01810         }
01811         if ( $showError )
01812             eZDebug::writeWarning( $msg );
01813 
01814         return null;
01815     }
01816 
01817     /**
01818      * Returns the named parameters array
01819      * @return array
01820      */
01821     function getNamedParameters()
01822     {
01823         return $this->NamedParameters;
01824     }
01825 
01826     /**
01827      * Checks if access is allowed to a module/view based on site.ini[SiteAccessRules]Rules[] settings
01828      *
01829      * @since 4.4
01830      * @param eZURI $uri
01831      * @return array An associative array with:
01832      *   'result'       => bool   Indicates if access is allowed
01833      *   'module'       => string Module name
01834      *   'view'         => string View name
01835      *   'view_checked' => bool   Indicates if view access has been checked
01836      */
01837     public static function accessAllowed( eZURI $uri )
01838     {
01839         $moduleName = $uri->element();
01840         $viewName = $uri->element( 1 );
01841         $check = array( 'result' => true,
01842                         'module' => $moduleName,
01843                         'view' => $viewName,
01844                         'view_checked' => false );
01845 
01846         $ini = eZINI::instance();
01847 
01848         $access = true;
01849         $currentAccess = true;
01850         if ( !$ini->hasGroup( 'SiteAccessRules' ) )
01851             return $check;
01852         $items = $ini->variableArray( 'SiteAccessRules', 'Rules' );
01853         foreach( $items as $item )
01854         {
01855             $name = strtolower( $item[0] );
01856             if ( isset ( $item[1] ) )
01857                 $value = $item[1];
01858             else
01859                 $value = null;
01860             switch( $name )
01861             {
01862                 case 'access':
01863                 {
01864                     $currentAccess = ( $value == 'enable' );
01865                 } break;
01866                 case 'moduleall':
01867                 {
01868                     $access = $currentAccess;
01869                 } break;
01870                 case 'module':
01871                 {
01872                     if ( preg_match( "#([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)#", $value, $matches ) )
01873                     {
01874                         if ( $matches[1] == $moduleName and
01875                              $matches[2] == $viewName )
01876                         {
01877                             $check['view_checked'] = true;
01878                             $access = $currentAccess;
01879                         }
01880                     }
01881                     else
01882                     {
01883                         if ( $value == $moduleName )
01884                         {
01885                             $access = $currentAccess;
01886                             $check['view_checked'] = false;
01887                         }
01888                     }
01889                 } break;
01890                 default:
01891                 {
01892                     eZDebug::writeError( "Unknown access rule: $name=$value", 'Access' );
01893                 } break;
01894             }
01895         }
01896 
01897         $check['result'] = $access;
01898         return $check;
01899     }
01900 
01901     /**
01902      * List of defined views for the module, as defined in the $ViewList variable
01903      * in module.php
01904      * @var array
01905      * @private
01906      */
01907     public $Functions;
01908 
01909     /**
01910      * Array of module information.
01911      * Available keys:
01912      * - string  name: the module name
01913      * - array   function: the known function (view) list
01914      * - boolean variable_params
01915      * - string  ui_component_match
01916      * @var array
01917      * @private
01918      */
01919     public $Module;
01920 
01921     /**
01922      * The module name
01923      * @var string
01924      */
01925     public $Name;
01926 
01927     /**
01928      * The module's path, without the module name and module.php
01929      * Examples: kernel, extension/mymoduleextension/modules
01930      * @var string
01931      */
01932     public $Path;
01933 
01934     /**
01935      * The last execution's exit status.
01936      * Accepts one of the STATUS_ constants.
01937      * @see STATUS_OK, STATUS_FAILED, STATUS_REDIRECT, STATUS_RERUN
01938      * @see setExitStatus(), exitStatus()
01939      * @var int
01940      */
01941     public $ExitStatus;
01942 
01943     /**
01944      * The last execution's error code, if an error occured
01945      * @see errorCode(), setErrorCode()
01946      * @var int
01947      */
01948     public $ErrorCode;
01949 
01950     /**
01951      * The redirection URI that will be used to redirect after execution has ended.
01952      * @see redirectURI(), setRedirectURI(), redirectTo(), STATUS_REDIRECT
01953      * @var string
01954      */
01955     public $RedirectURI;
01956 
01957     /**
01958      * The redirection HTTP status
01959      * @see setRedirectStatus(), redirectStatus(), STATUS_REDIRECT
01960      * @var string
01961      */
01962     public $RedirectStatus;
01963 
01964     /**
01965      * The last execution's result title
01966      * @var string
01967      * @see title(), setTitle()
01968      */
01969     public $Title;
01970 
01971     /**
01972      * The hook list for this module
01973      * @see addHook(), runHooks()
01974      * @var array
01975      */
01976     public $HookList;
01977 
01978     /**
01979      * Current action per view, as an associative array.
01980      * Each key is a view name, and the value the current action
01981      * @var array
01982      * @see viewAction(), setCurrentAction(), isCurrentAction()
01983      */
01984     public $ViewActions;
01985 
01986     /**
01987      * The last execution view result, as an array
01988      * Common keys: content, title, url...
01989      * @var array
01990      */
01991     public $ViewResult;
01992 
01993     /**
01994      * Ordered view parameters values
01995      * @var array
01996      * @private
01997      */
01998     public $ViewParameters;
01999 
02000     /**
02001      * Original parameters, before they're mapped to view/unordered/user
02002      * @var array
02003      * @private
02004      */
02005     public $OriginalParameters;
02006 
02007     /**
02008      * View parameters values
02009      * @var array
02010      * @private
02011      */
02012     public $OriginalViewParameters;
02013 
02014     /**
02015      * Named parameters, indexed by name
02016      * @var array
02017      * @private
02018      */
02019     public $NamedParameters;
02020 
02021     /**
02022      * Unordered parameters
02023      * @var array
02024      * @private
02025      */
02026     public $OriginalUnorderedParameters;
02027 
02028     /**
02029      * User parameters (customized ones, as the content/view "view" parameters)
02030      * @var array
02031      * @private
02032      */
02033     public $UserParameters;
02034 
02035     /**
02036      * The current UI context
02037      * By default 'navigation' but can be changed depending on module or PHP code
02038      * @var string
02039      * @private
02040      */
02041     public $UIContext;
02042 
02043     /**
02044      * The current UI context
02045      * By default the current module but can be changed depending on module or PHP code
02046      * @var string
02047      * @private
02048      */
02049     public $UIComponent;
02050 
02051     /**
02052      * Controls at which level UI component matching is done:
02053      * either 'module' which uses module name or 'view' which uses view name
02054      * @var string
02055      * @private
02056      */
02057     public $UIComponentMatch;
02058 }
02059 
02060 ?>