eZ Publish  [4.0]
ezmoduleoperationinfo.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZModuleOperationInfo class
00004 //
00005 // Created on: <06-Oct-2002 16:27:36 amos>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezmoduleoperationinfo.php
00032 */
00033 
00034 /*!
00035   \class eZModuleOperationInfo ezmoduleoperationinfo.php
00036   \brief The class eZModuleOperationInfo does
00037 
00038 */
00039 
00040 //include_once( 'lib/ezutils/classes/ezmodule.php' );
00041 require_once( 'lib/ezutils/classes/ezdebug.php' );
00042 //include_once( 'lib/ezutils/classes/ezoperationmemento.php' );
00043 //include_once( 'kernel/classes/eztrigger.php' );
00044 
00045 class eZModuleOperationInfo
00046 {
00047     const ERROR_NO_CLASS = 5;
00048     const ERROR_NO_CLASS_METHOD = 6;
00049     const ERROR_CLASS_INSTANTIATE_FAILED = 7;
00050     const ERROR_MISSING_PARAMETER = 8;
00051 
00052     const STATUS_CONTINUE = 1;
00053     const STATUS_CANCELLED = 2;
00054     const STATUS_HALTED = 3;
00055     const STATUS_REPEAT = 4;
00056 
00057     /**
00058      * Constructor
00059      * @param string $moduleName
00060      * @param bool $useTriggers
00061     **/
00062     function eZModuleOperationInfo( $moduleName, $useTriggers = true )
00063     {
00064         $this->ModuleName = $moduleName;
00065         $this->IsValid = false;
00066         $this->OperationList = array();
00067         $this->Memento = null;
00068         $this->UseTriggers = $useTriggers;
00069     }
00070 
00071     /**
00072      * ???
00073      *
00074      * @return bool
00075      */
00076     function isValid()
00077     {
00078         return $this->IsValid;
00079     }
00080 
00081     /**
00082     * Loads the operations definition for the current module
00083     * @return bool true if the operations were loaded, false if an error occured
00084     **/
00085     function loadDefinition()
00086     {
00087         $pathList = eZModule::globalPathList();
00088         foreach ( $pathList as $path )
00089         {
00090             $definitionFile = $path . '/' . $this->ModuleName . '/operation_definition.php';
00091             if ( file_exists( $definitionFile ) )
00092                 break;
00093             $definitionFile = null;
00094         }
00095         if ( $definitionFile === null )
00096         {
00097             eZDebug::writeError( 'Missing operation definition file for module: ' . $this->ModuleName,
00098                                  'eZModuleOperationInfo::loadDefinition' );
00099             return false;
00100         }
00101         unset( $OperationList );
00102         include( $definitionFile );
00103         if ( !isset( $OperationList ) )
00104         {
00105             eZDebug::writeError( 'Missing operation definition list for module: ' . $this->ModuleName,
00106                                  'eZModuleOperationInfo::loadDefinition' );
00107             return false;
00108         }
00109         $this->OperationList = $OperationList;
00110         $this->IsValid = true;
00111         return true;
00112     }
00113 
00114     function makeOperationKeyArray( $operationDefinition, $operationParameters )
00115     {
00116         $keyDefinition = null;
00117         if ( array_key_exists( 'keys', $operationDefinition ) and
00118              is_array( $operationDefinition['keys'] ) )
00119         {
00120             $keyDefinition = $operationDefinition['keys'];
00121         }
00122         return $this->makeKeyArray( $keyDefinition, $operationDefinition['parameters'], $operationParameters );
00123     }
00124 
00125     function makeKeyArray( $keyDefinition, $parameterDefinition, $operationParameters )
00126     {
00127         $keyArray = array();
00128         if ( $keyDefinition !== null )
00129         {
00130             foreach ( $keyDefinition as $key )
00131             {
00132                 $keyArray[$key] = $operationParameters[$key];
00133             }
00134         }
00135         else
00136         {
00137             foreach ( $parameterDefinition as $operationParameter )
00138             {
00139                 $keyArray[$operationParameter['name']] = $operationParameters[$operationParameter['name']];
00140             }
00141         }
00142         return $keyArray;
00143     }
00144 
00145     /**
00146      * Executes the operation
00147      *
00148      * @param string $operationName
00149      * @param array $operationParameters
00150      * @param array $mementoData
00151      * @return mixed the operation execution result, or null if an error occured
00152      */
00153     function execute( $operationName, $operationParameters, $mementoData = null )
00154     {
00155         $moduleName = $this->ModuleName;
00156         if ( !isset( $this->OperationList[$operationName] ) )
00157         {
00158             eZDebug::writeError( "No such operation '$operationName' in module '$moduleName'",
00159                                  'eZModuleOperationInfo::execute' );
00160             return null;
00161         }
00162         $operationDefinition = $this->OperationList[$operationName];
00163         if ( !isset( $operationName['default_call_method'] ) )
00164         {
00165             eZDebug::writeError( "No call method defined for operation '$operationName' in module '$moduleName'",
00166                                  'eZModuleOperationInfo::execute' );
00167             return null;
00168         }
00169         if ( !isset( $operationName['body'] ) )
00170         {
00171             eZDebug::writeError( "No body for operation '$operationName' in module '$moduleName'",
00172                                  'eZModuleOperationInfo::execute' );
00173             return null;
00174         }
00175         if ( !isset( $operationName['parameters'] ) )
00176         {
00177             eZDebug::writeError( "No parameters defined for operation '$operationName' in module '$moduleName'",
00178                                  'eZModuleOperationInfo::execute' );
00179             return null;
00180         }
00181         $callMethod = $operationDefinition['default_call_method'];
00182         $resultArray = null;
00183         $this->Memento = null;
00184         if ( isset( $callMethod['include_file'] ) and
00185              isset( $callMethod['class'] ) )
00186         {
00187             $bodyCallCount = array( 'loop_run' => array() );
00188             $operationKeys = null;
00189             if ( isset( $operationDefinition['keys'] ) )
00190                 $operationKeys = $operationDefinition['keys'];
00191             $operationParameterDefinitions = $operationDefinition['parameters'];
00192             $this->storeOperationMemento( $operationKeys, $operationParameterDefinitions, $operationParameters, $bodyCallCount, $operationName );
00193 
00194             $runOperation = true;
00195             if ( $mementoData === null )
00196             {
00197                 $keyArray = $this->makeOperationKeyArray( $operationDefinition, $operationParameters );
00198                 $http = eZHTTPTool::instance();
00199                 $keyArray['session_key'] = $http->getSessionKey();
00200                 $mainMemento = null;
00201                 if ( $this->UseTriggers )
00202                     $mainMemento = eZOperationMemento::fetchMain( $keyArray );
00203 
00204                 if ( $mainMemento !== null )
00205                 {
00206                     $this->Memento = $mainMemento;
00207                     $mementoOperationData = $this->Memento->data();
00208                     if ( isset( $mementoOperationData['loop_run'] ) )
00209                         $bodyCallCount['loop_run'] = $mementoOperationData['loop_run'];
00210                 }
00211 //                 else
00212 //                     eZDebug::writeWarning( 'Missing main operation memento for key: ' . $this->Memento->attribute( 'memento_key' ), 'eZModuleOperationInfo::execute' );
00213 
00214                 $mementoList = null;
00215                 if ( $this->UseTriggers )
00216                     $mementoList = eZOperationMemento::fetchList( $keyArray );
00217 
00218                 if ( count( $mementoList ) > 0 )
00219                 {
00220                     $lastResultArray = array();
00221                     $mementoRestoreSuccess = true;
00222                     // restoring running operation
00223                     foreach ( $mementoList as $memento )
00224                     {
00225                         $mementoData = $memento->data();
00226                         $memento->remove();
00227 
00228                         $resultArray = $this->executeBody( $callMethod['include_file'], $callMethod['class'], $operationDefinition['body'],
00229                                                            $operationKeys, $operationParameterDefinitions, $operationParameters,
00230                                                            $mementoData, $bodyCallCount, $operationDefinition['name'] );
00231                         if ( is_array( $resultArray ) )
00232                         {
00233                             $lastResultArray = array_merge( $lastResultArray, $resultArray );
00234                             if ( !$resultArray['status'] )
00235                                 $mementoRestoreSuccess = false;
00236                         }
00237                     }
00238                     $resultArray = $lastResultArray;
00239                     //                 $resultArray['status'] = $mementoRestoreSuccess;
00240                     $runOperation = false;
00241                 }
00242             }
00243             if ( $runOperation )
00244             {
00245                 // start  new operation
00246                 $resultArray = $this->executeBody( $callMethod['include_file'], $callMethod['class'], $operationDefinition['body'],
00247                                                     $operationKeys, $operationParameterDefinitions, $operationParameters,
00248                                                     $mementoData, $bodyCallCount, $operationDefinition['name'] );
00249 
00250 //                 eZDebug::writeDebug( $resultArray, 'ezmodule operation result array' );
00251             }
00252 
00253             if ( is_array( $resultArray ) and
00254                  isset( $resultArray['status'] ) and
00255                  ( $resultArray['status'] == eZModuleOperationInfo::STATUS_HALTED
00256                    or $resultArray['status'] == eZModuleOperationInfo::STATUS_REPEAT ) )
00257             {
00258 //                 eZDebug::writeDebug( $this->Memento, 'ezmodule operation result halted' );
00259                 if ( $this->Memento !== null )
00260                 {
00261                     $this->Memento->store();
00262                 }
00263             }
00264             else if ( $this->Memento !== null and
00265                       $this->Memento->attribute( 'id' ) !== null )
00266             {
00267 //                 eZDebug::writeDebug( $this->Memento, 'ezmodule operation result not halted' );
00268                 $this->Memento->remove();
00269             }
00270 //            if ( $resultArray['status'] == eZModuleOperationInfo::STATUS_CANCELLED )
00271 //            {
00272 //                return null;
00273 //            }
00274             /*
00275             else if ( isset( $mementoData['memento_key'] ) )
00276             {
00277                 $memento = eZOperationMemento::fetch( $mementoData['mementoKey'] );
00278                 if ( $memento->attribute( 'main_key') !=  $mementoData['mementoKey'] )
00279                 {
00280                     $mainMemento = eZOperationMemento::fetch( $memento->attribute( 'main_key') );
00281                 }
00282                 $memento->remove();
00283             }
00284             */
00285             $this->Memento = null;
00286         }
00287         else
00288         {
00289             eZDebug::writeError( "No valid call methods found for operation '$operationName' in module '$moduleName'",
00290                                  'eZModuleOperationInfo::execute' );
00291             return null;
00292         }
00293         if ( !is_array( $resultArray ) )
00294         {
00295             eZDebug::writeError( "Operation '$operationName' in module '$moduleName' did not return a result array",
00296                                  'eZOperationHandler::execute' );
00297             return null;
00298         }
00299         if ( isset( $resultArray['internal_error'] ) )
00300         {
00301             switch ( $resultArray['internal_error'] )
00302             {
00303                 case eZModuleOperationInfo::ERROR_NO_CLASS:
00304                 {
00305                     $className = $resultArray['internal_error_class_name'];
00306                     eZDebug::writeError( "No class '$className' available for operation '$operationName' in module '$moduleName'",
00307                                          'eZModuleOperationInfo::execute' );
00308                     return null;
00309                 } break;
00310                 case eZModuleOperationInfo::ERROR_NO_CLASS_METHOD:
00311                 {
00312                     $className = $resultArray['internal_error_class_name'];
00313                     $classMethodName = $resultArray['internal_error_class_method_name'];
00314                     eZDebug::writeError( "No method '$classMethodName' in class '$className' available for operation '$operationName' in module '$moduleName'",
00315                                          'eZModuleOperationInfo::execute' );
00316                     return null;
00317                 } break;
00318                 case eZModuleOperationInfo::ERROR_CLASS_INSTANTIATE_FAILED:
00319                 {
00320                     $className = $resultArray['internal_error_class_name'];
00321                     eZDebug::writeError( "Failed instantiating class '$className' which is needed for operation '$operationName' in module '$moduleName'",
00322                                          'eZModuleOperationInfo::execute' );
00323                     return null;
00324                 } break;
00325                 case eZModuleOperationInfo::ERROR_MISSING_PARAMETER:
00326                 {
00327                     $parameterName = $resultArray['internal_error_parameter_name'];
00328                     eZDebug::writeError( "Missing parameter '$parameterName' for operation '$operationName' in module '$moduleName'",
00329                                          'eZModuleOperationInfo::execute' );
00330                     return null;
00331                 } break;
00332                 default:
00333                 {
00334                     $internalError = $resultArray['internal_error'];
00335                     eZDebug::writeError( "Unknown internal error '$internalError' for operation '$operationName' in module '$moduleName'",
00336                                          'eZModuleOperationInfo::execute' );
00337                     return null;
00338                 } break;
00339             }
00340             return null;
00341         }
00342         else if ( isset( $resultArray['error'] ) )
00343         {
00344         }
00345         else if ( isset( $resultArray['status'] ) )
00346         {
00347             return $resultArray;
00348         }
00349         else
00350         {
00351             eZDebug::writeError( "Operation '$operationName' in module '$moduleName' did not return a result value",
00352                                  'eZOperationHandler::execute' );
00353         }
00354         return null;
00355     }
00356 
00357     /**
00358      * Executes the operation body
00359      *
00360      * @param string $includeFile Path to the file where the operation class is defined
00361      * @param string $className Name of the class holding the operation methods (@see $includeFile)
00362      * @param array $bodyStructure
00363      * @param array $operationKeys
00364      * @param array $operationParameterDefinitions
00365      * @param array $operationParameters
00366      * @param array $mementoData
00367      * @param int $bodyCallCount
00368      * @param string $operationName
00369      * @param array $currentLoopData
00370      * @return array
00371      */
00372     function executeBody( $includeFile, $className, $bodyStructure,
00373                           $operationKeys, $operationParameterDefinitions, $operationParameters,
00374                           &$mementoData, &$bodyCallCount, $operationName, $currentLoopData = null )
00375     {
00376         $bodyReturnValue = array( 'status' => eZModuleOperationInfo::STATUS_CONTINUE );
00377         foreach ( $bodyStructure as $body )
00378         {
00379             if ( !isset( $body['type'] ) )
00380             {
00381                 eZDebug::writeError( 'No type for body element, skipping', 'eZModuleOperationInfo::executeBody' );
00382                 continue;
00383             }
00384             if ( !isset( $body['name'] ) )
00385             {
00386                 eZDebug::writeError( 'No name for body element, skipping', 'eZModuleOperationInfo::executeBody' );
00387                 continue;
00388             }
00389             $bodyName = $body['name'];
00390             if ( !isset( $bodyCallCount['loop_run'][$bodyName] ) )
00391                 $bodyCallCount['loop_run'][$bodyName] = 0;
00392             $type = $body['type'];
00393             switch ( $type )
00394             {
00395                 case 'loop':
00396                 {
00397                     $children = $body['children'];
00398                     $tmpOperationParameterDefinitions = $operationParameterDefinitions;
00399                     if ( isset( $body['child_parameters'] ) )
00400                         $tmpOperationParameterDefinitions = $body['child_parameters'];
00401                     $loopName = $body['name'];
00402 
00403                     if ( $mementoData !== null )
00404                     {
00405                         $returnValue = $this->executeBody( $includeFile, $className, $children,
00406                                                            $operationKeys, $tmpOperationParameterDefinitions, $operationParameters,
00407                                                            $mementoData, $bodyCallCount, $operationName, null );
00408                         if ( !$returnValue['status'] )
00409                             return $returnValue;
00410                     }
00411                     else
00412                     {
00413                         ++$bodyCallCount['loop_run'][$bodyName];
00414 
00415                         $method = $body['method'];
00416                         $resultArray = $this->executeClassMethod( $includeFile, $className, $method,
00417                                                                   $operationParameterDefinitions, $operationParameters );
00418                         $parameters = array();
00419                         if ( isset( $resultArray['parameters'] ) )
00420                         {
00421                             $parameters = $resultArray['parameters'];
00422                         }
00423                         $count = 0;
00424                         $countDone = 0;
00425                         $countHalted = 0;
00426                         $countCanceled = 0;
00427                         $countRepeated = 0;
00428                         foreach ( $parameters as $parameterStructure )
00429                         {
00430                             $tmpOperationParameters = $operationParameters;
00431                             foreach ( $parameterStructure as $parameterName => $parameterValue )
00432                             {
00433                                 $tmpOperationParameters[$parameterName] = $parameterValue;
00434                             }
00435 
00436                             ++$count;
00437                             $returnValue = $this->executeBody( $includeFile, $className, $children,
00438                                                                $operationKeys, $tmpOperationParameterDefinitions, $tmpOperationParameters,
00439                                                                $mementoData, $bodyCallCount, $operationName, array( 'name' => $loopName,
00440                                                                                                                     'count' => count( $parameters ),
00441                                                                                                                     'index' => $count  ) );
00442                             switch( $returnValue['status'] )
00443                             {
00444                                 case eZModuleOperationInfo::STATUS_CANCELLED:
00445                                 {
00446                                     $bodyReturnValue = $returnValue;
00447                                     ++$countCanceled;
00448                                 }break;
00449                                 case eZModuleOperationInfo::STATUS_CONTINUE:
00450                                 {
00451                                     $bodyReturnValue = $returnValue;
00452 
00453                                     ++$countDone;
00454                                 }break;
00455                                 case eZModuleOperationInfo::STATUS_HALTED:
00456                                 {
00457                                     $bodyReturnValue = $returnValue;
00458                                     ++$countHalted;
00459                                 }break;
00460                                 case eZModuleOperationInfo::STATUS_REPEAT:
00461                                 {
00462                                     $bodyReturnValue = $returnValue;
00463                                     ++$countRepeated;
00464                                 }break;
00465                             }
00466                         }
00467                         if ( $body['continue_operation'] == 'all' )
00468                         {
00469                             if ( $count == $countDone )
00470                             {
00471                                 // continue operation
00472                             }
00473                             if ( $countCanceled > 0 )
00474                             {
00475                                 return $bodyReturnValue;
00476                                 //cancel operation
00477                             }
00478                             if ( $countHalted > 0 )
00479                             {
00480                                 return $bodyReturnValue;                                //show tempalate
00481                             }
00482 
00483                         }
00484                     }
00485                 } break;
00486                 case 'trigger':
00487                 {
00488                     if ( !$this->UseTriggers )
00489                     {
00490                         $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_CONTINUE;
00491                         continue;
00492 
00493                     }
00494 
00495                     $triggerName = $body['name'];
00496                     $triggerRestored = false;
00497                     $executeTrigger = true;
00498                     if ( $mementoData !== null )
00499                     {
00500                         if ( $mementoData['name'] == $triggerName )
00501                         {
00502                             $executeTrigger =  $this->restoreBodyMementoData( $bodyName, $mementoData,
00503                                                                               $operationParameters, $bodyCallCount, $currentLoopData );
00504                             $triggerRestored = true;
00505                         }
00506                         else
00507                         {
00508                             $executeTrigger = false;
00509                         }
00510                     }
00511                     if ( $executeTrigger )
00512                     {
00513                         $status = $this->executeTrigger( $bodyReturnValue, $body,
00514                                                           $operationParameterDefinitions, $operationParameters,
00515                                                           $bodyCallCount, $currentLoopData,
00516                                                           $triggerRestored, $operationName, $operationKeys );
00517 
00518                         switch( $status )
00519                         {
00520                             case eZModuleOperationInfo::STATUS_CONTINUE:
00521                             {
00522                                 $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_CONTINUE;
00523                             }break;
00524                             case eZModuleOperationInfo::STATUS_CANCELLED:
00525                             {
00526                                 $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_CANCELLED;
00527                                 return $bodyReturnValue;
00528                             }break;
00529                             case eZModuleOperationInfo::STATUS_HALTED:
00530                             {
00531 
00532                                 $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_HALTED;
00533                                 return $bodyReturnValue;
00534                             }
00535                             case eZModuleOperationInfo::STATUS_REPEAT:
00536                             {
00537 
00538                                 $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_REPEAT;
00539                                 return $bodyReturnValue;
00540                             }
00541                         }
00542                     }else
00543                     {
00544                         $bodyReturnValue['status'] = eZModuleOperationInfo::STATUS_CONTINUE;
00545                     }
00546                 } break;
00547                 case 'method':
00548                 {
00549                     if ( $mementoData === null )
00550                     {
00551                         $method = $body['method'];
00552                         $frequency = $body['frequency'];
00553                         $executeMethod = true;
00554                         if ( $frequency == 'once' and
00555                              $bodyCallCount['loop_run'][$bodyName] != 0 )
00556                             $executeMethod = false;
00557                         $tmpOperationParameterDefinitions = $operationParameterDefinitions;
00558                         if ( isset( $body['parameters'] ) )
00559                             $tmpOperationParameterDefinitions = $body['parameters'];
00560                         if ( $executeMethod )
00561                         {
00562                             ++$bodyCallCount['loop_run'][$bodyName];
00563                             $result = $this->executeClassMethod( $includeFile, $className, $method,
00564                                                                  $tmpOperationParameterDefinitions, $operationParameters );
00565                             if ( $result && array_key_exists( 'status', $result ) )
00566                             {
00567                                 switch( $result['status'] )
00568                                 {
00569                                     case eZModuleOperationInfo::STATUS_CONTINUE:
00570                                     default:
00571                                     {
00572                                         $result['status'] = eZModuleOperationInfo::STATUS_CONTINUE;
00573                                         $bodyReturnValue = $result;
00574                                     } break;
00575 
00576                                     case eZModuleOperationInfo::STATUS_CANCELLED:
00577                                     case eZModuleOperationInfo::STATUS_HALTED:
00578                                     {
00579                                         return $result;
00580                                     } break;
00581                                 }
00582                             }
00583                         }
00584                     }
00585                 } break;
00586                 default:
00587                 {
00588                     eZDebug::writeError( "Unknown operation type $type", 'eZModuleOperationInfo::executeBody' );
00589                 }
00590             }
00591         }
00592 
00593         return $bodyReturnValue;
00594     }
00595 
00596     /**
00597      * Executes an operation trigger
00598      *
00599      * @param array $bodyReturnValue The current return value
00600      * @param array $body Body data for the trigger being executed
00601      * @param array $operationParameterDefinitions Operation parameters definition
00602      * @param array $operationParameters Operation parameters values
00603      * @param int $bodyCallCount Number of times the body was called
00604      * @param array $currentLoopData Memento data for the operation
00605      * @param bool $triggerRestored Boolean that indicates if operation data (memento) was restored
00606      * @param string $operationName The operation name
00607      * @param array $operationKeys Additional parameters. Only used by looping so far.
00608      * @return
00609      */
00610     function executeTrigger( &$bodyReturnValue, $body,
00611                              $operationParameterDefinitions, $operationParameters,
00612                              &$bodyCallCount, $currentLoopData,
00613                              $triggerRestored, $operationName, &$operationKeys )
00614     {
00615         $triggerName = $body['name'];
00616         $triggerKeys = $body['keys'];
00617 
00618         $status = eZTrigger::runTrigger( $triggerName, $this->ModuleName, $operationName, $operationParameters, $triggerKeys );
00619 
00620 
00621         if ( $status['Status'] == eZTrigger::WORKFLOW_DONE ||
00622              $status['Status'] == eZTrigger::NO_CONNECTED_WORKFLOWS )
00623         {
00624             ++$bodyCallCount['loop_run'][$triggerName];
00625             return eZModuleOperationInfo::STATUS_CONTINUE;
00626         }
00627         else if ( $status['Status'] == eZTrigger::STATUS_CRON_JOB ||
00628                   $status['Status'] == eZTrigger::FETCH_TEMPLATE ||
00629                   $status['Status'] == eZTrigger::FETCH_TEMPLATE_REPEAT ||
00630                   $status['Status'] == eZTrigger::REDIRECT )
00631         {
00632             $bodyMemento = $this->storeBodyMemento( $triggerName, $triggerKeys,
00633                                                     $operationKeys, $operationParameterDefinitions, $operationParameters,
00634                                                     $bodyCallCount, $currentLoopData, $operationName );
00635             $workflowProcess = $status['WorkflowProcess'];
00636             if ( ! is_null( $workflowProcess ) )
00637             {
00638                 $workflowProcess->setAttribute( 'memento_key', $bodyMemento->attribute( 'memento_key' ) );
00639                 $workflowProcess->store();
00640             }
00641 
00642             $bodyReturnValue['result'] = $status['Result'];
00643             if ( $status['Status'] == eZTrigger::REDIRECT )
00644             {
00645                 $bodyReturnValue['redirect_url'] = $status['Result'];
00646             }
00647             if ( $status['Status'] == eZTrigger::FETCH_TEMPLATE_REPEAT )
00648             {
00649                 // Hack for project issue #14371 (fetch template repeat)
00650                 // The object version's status is set to REPEAT so that it can
00651                 // be submitted again
00652                 if ( $operationName == 'publish' && $this->ModuleName == 'content' )
00653                 {
00654                     eZContentOperationCollection::setVersionStatus( $operationParameters['object_id'],
00655                         $operationParameters['version'], eZContentObjectVersion::STATUS_REPEAT );
00656                 }
00657                 return eZModuleOperationInfo::STATUS_REPEAT;
00658             }
00659             else
00660             {
00661                 return eZModuleOperationInfo::STATUS_HALTED;
00662             }
00663         }
00664         else if ( $status['Status'] == eZTrigger::WORKFLOW_CANCELLED or
00665                   $status['Status'] == eZTrigger::WORKFLOW_RESET )
00666         {
00667              return eZModuleOperationInfo::STATUS_CANCELLED;
00668              $bodyReturnValue['result'] = $status['Result'];
00669         }
00670     }
00671 
00672     function storeOperationMemento( $operationKeys, $operationParameterDefinitions, $operationParameters,
00673                                     &$bodyCallCount, $operationName )
00674     {
00675         $mementoData = array();
00676         $mementoData['module_name'] = $this->ModuleName;
00677         $mementoData['operation_name'] = $operationName;
00678         if ( $this->Memento === null )
00679         {
00680             $keyArray = $this->makeKeyArray( $operationKeys, $operationParameterDefinitions, $operationParameters );
00681             $http = eZHTTPTool::instance();
00682             $keyArray['session_key'] = $http->getSessionKey();
00683             $mementoData['loop_run'] = $bodyCallCount['loop_run'];
00684             $memento = eZOperationMemento::create( $keyArray, $mementoData, true );
00685             $this->Memento = $memento;
00686         }
00687         else
00688         {
00689             $mementoData = $this->Memento->data();
00690             $mementoData['loop_run'] = $bodyCallCount['loop_run'];
00691             $this->Memento->setData( $mementoData );
00692         }
00693     }
00694 
00695     function removeBodyMemento( $bodyName, $bodyKeys,
00696                                 $operationKeys, $operationParameterDefinitions, $operationParameters,
00697                                 &$bodyCallCount, $currentLoopData, $operationName )
00698     {
00699         $keyArray = $this->makeKeyArray( $operationKeys, $operationParameterDefinitions, $operationParameters );
00700     }
00701 
00702     /**
00703      * Packs the current body data (memento) for save & re-use
00704      *
00705      * @param string $bodyName
00706      * @param array $bodyKeys
00707      * @param array $operationKeys
00708      * @param array $operationParameterDefinitions
00709      * @param array $operationParameters
00710      * @param int $bodyCallCount
00711      * @param array $currentLoopData
00712      * @param string $operationName
00713      * @return The memento
00714      */
00715     function storeBodyMemento( $bodyName, $bodyKeys,
00716                                $operationKeys, $operationParameterDefinitions, $operationParameters,
00717                                &$bodyCallCount, $currentLoopData, $operationName )
00718     {
00719         $this->storeOperationMemento( $operationKeys, $operationParameterDefinitions, $operationParameters, $bodyCallCount, $operationName );
00720 
00721         $keyArray = $this->makeKeyArray( $operationKeys, $operationParameterDefinitions, $operationParameters );
00722         $http = eZHTTPTool::instance();
00723         $keyArray['session_key'] = $http->getSessionKey();
00724         $mementoData = array();
00725         $mementoData['name'] = $bodyName;
00726         $mementoData['parameters'] = $operationParameters;
00727         $mementoData['loop_data'] = $currentLoopData;
00728         $mementoData['module_name'] = $this->ModuleName;
00729         $mementoData['operation_name'] = $operationName;
00730         $memento = eZOperationMemento::create( $keyArray, $mementoData, false, $this->Memento->attribute( 'memento_key' ) );
00731         $memento->store();
00732         return $memento;
00733     }
00734 
00735     function restoreBodyMementoData( $bodyName, &$mementoData,
00736                                      &$operationParameters, &$bodyCallCount, &$currentLoopData )
00737     {
00738         $operationParameters = array();
00739         if ( isset( $mementoData['parameters'] ) )
00740             $operationParameters = $mementoData['parameters'];
00741         if ( isset( $mementoData[ 'main_memento' ] ) )
00742         {
00743             $this->Memento = $mementoData[ 'main_memento' ];
00744             $mainMementoData = $this->Memento->data();
00745             if ( isset( $mainMementoData['loop_run'] ) )
00746             {
00747                 $bodyCallCount['loop_run'] = $mainMementoData['loop_run'];
00748             }
00749 
00750         }
00751 
00752 //         if ( $this->Memento !== null )
00753 //         {
00754 //             $mementoOperationData = $this->Memento->data();
00755 //             if ( isset( $mementoOperationData['loop_run'] ) )
00756 //                 $bodyCallCount['loop_run'] = $mementoOperationData['loop_run'];
00757 //         }
00758         if ( isset( $mementoData['loop_data'] ) )
00759             $currentLoopData = $mementoData['loop_data'];
00760 
00761         if ( isset( $mementoData['skip_trigger'] ) && $mementoData['skip_trigger'] == true )
00762         {
00763             $mementoData = null;
00764             return false;
00765         }
00766         else
00767         {
00768             $mementoData = null;
00769             return true;
00770         }
00771 
00772         return true;
00773     }
00774 
00775     /**
00776      * Executes a class method in an operation body
00777      *
00778      * @param string $includeFile The file where the class & method are defined
00779      * @param string $className The class where the method is implemented
00780      * @param string $methodName The method to call
00781      * @param mixed $operationParameterDefinitions The method parameters definition
00782      * @param mixed $operationParameters The method parameters values
00783      * @return array
00784      */
00785     function executeClassMethod( $includeFile, $className, $methodName,
00786                                  $operationParameterDefinitions, $operationParameters )
00787     {
00788         include_once( $includeFile );
00789         if ( !class_exists( $className ) )
00790         {
00791             return array( 'internal_error' => eZModuleOperationInfo::ERROR_NO_CLASS,
00792                           'internal_error_class_name' => $className );
00793         }
00794         $classObject = $this->objectForClass( $className );
00795         if ( $classObject === null )
00796         {
00797             return array( 'internal_error' => eZModuleOperationInfo::ERROR_CLASS_INSTANTIATE_FAILED,
00798                           'internal_error_class_name' => $className );
00799         }
00800         if ( !method_exists( $classObject, $methodName ) )
00801         {
00802             return array( 'internal_error' => eZModuleOperationInfo::ERROR_NO_CLASS_METHOD,
00803                           'internal_error_class_name' => $className,
00804                           'internal_error_class_method_name' => $methodName );
00805         }
00806         $parameterArray = array();
00807 
00808         foreach ( $operationParameterDefinitions as $operationParameterDefinition )
00809         {
00810             $parameterName = $operationParameterDefinition['name'];
00811             if ( isset( $operationParameterDefinition['constant'] ) )
00812             {
00813                 $constantValue = $operationParameterDefinition['constant'];
00814                 $parameterArray[] = $constantValue;
00815             }
00816             else if ( isset( $operationParameters[$parameterName] ) )
00817             {
00818                 // Do type checking
00819                 $parameterArray[] = $operationParameters[$parameterName];
00820             }
00821             else
00822             {
00823                 if ( $operationParameterDefinition['required'] )
00824                 {
00825 
00826                     return array( 'internal_error' => eZModuleOperationInfo::ERROR_MISSING_PARAMETER,
00827                                   'internal_error_parameter_name' => $parameterName );
00828                 }
00829                 else if ( isset( $operationParameterDefinition['default'] ) )
00830                 {
00831                     $parameterArray[] = $operationParameterDefinition['default'];
00832                 }
00833                 else
00834                 {
00835                     $parameterArray[] = null;
00836                 }
00837             }
00838         }
00839 
00840         return call_user_func_array( array( $classObject, $methodName ), $parameterArray );
00841     }
00842 
00843     /**
00844      * Helper method that keeps and returns the instances of operation objects
00845      * @param string $className The class the method should return an object for
00846      * @return $className
00847      * @private
00848      * @todo Use a static variable instead of globals
00849      **/
00850     function objectForClass( $className )
00851     {
00852         if ( !isset( $GLOBALS['eZModuleOperationClassObjectList'] ) )
00853         {
00854             $GLOBALS['eZModuleOperationClassObjectList'] = array();
00855         }
00856         if ( isset( $GLOBALS['eZModuleOperationClassObjectList'][$className] ) )
00857         {
00858             return $GLOBALS['eZModuleOperationClassObjectList'][$className];
00859         }
00860 
00861         return $GLOBALS['eZModuleOperationClassObjectList'][$className] = new $className();
00862     }
00863 
00864     /**
00865      * @deprecated use call_user_func_array() instead
00866     **/
00867     function callClassMethod( $methodName, $classObject, $parameterArray )
00868     {
00869         return call_user_func_array( array( $classObject, $methodName ), $parameterArray );
00870     }
00871 
00872 
00873     /// \privatesection
00874     public $ModuleName;
00875     public $FunctionList;
00876     public $IsValid;
00877     public $UseTriggers = false;
00878 }
00879 
00880 ?>