| <?php |
| /** |
| * File containing the ezcWorkflowNodeSubWorkflow class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Workflow |
| * @version //autogen// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * An object of the ezcWorkflowNodeSubWorkflow class represents a sub-workflow. |
| * |
| * When the node is reached during execution of the workflow, the specified sub-workflow |
| * is started. The original workflow is suspended until the sub-workflow has finished executing. |
| * |
| * Incoming nodes: 1 |
| * Outgoing nodes: 1 |
| * |
| * The example below creates a sub-workflow node that passes the parent |
| * execution's variable 'x' to the variable 'y' in the child execution when the |
| * sub-workflow is started. When it ends, the child execution's 'y' variable is |
| * passed to the parent execution as 'z'. |
| * |
| * <code> |
| * <?php |
| * $subWorkflow = new ezcWorkflowNodeSubWorkflow( |
| * array( |
| * 'workflow' => 'IncrementVariable', |
| * 'variables' => array( |
| * 'in' => array( |
| * 'x' => 'y' |
| * ), |
| * 'out' => array( |
| * 'y' => 'z' |
| * ) |
| * ) |
| * ) |
| * ); |
| * ?> |
| * </code> |
| * |
| * @package Workflow |
| * @version //autogen// |
| */ |
| class ezcWorkflowNodeSubWorkflow extends ezcWorkflowNode |
| { |
| /** |
| * Execution ID of the sub workflow, |
| * 0 if it has not been started yet. |
| * |
| * @var integer |
| */ |
| protected $state = 0; |
| |
| /** |
| * Constructs a new sub workflow with the configuration $configuration. |
| * |
| * Configuration format |
| * <ul> |
| * <li> |
| * <b>String:</b> |
| * The name of the workflow to execute. The workflow is loaded using the |
| * loadByName method on the execution engine. |
| * </li> |
| * |
| * <li> |
| * <b>Array:</b> |
| * <ul> |
| * <li><i>workflow:</i> The name of the workflow to execute. The workflow |
| * is loaded using the loadByName method on the execution engine.</li> |
| * <li><i>variables:</i> An array with the information for mapping |
| * workflow variables between parent and child workflow execution.</li> |
| * </ul> |
| * <li> |
| * </ul> |
| * |
| * @param mixed $configuration |
| */ |
| public function __construct( $configuration ) |
| { |
| if ( is_string( $configuration ) ) |
| { |
| $configuration = array( 'workflow' => $configuration ); |
| } |
| |
| if ( !isset( $configuration['variables'] ) ) |
| { |
| $configuration['variables'] = array( |
| 'in' => array(), 'out' => array() |
| ); |
| } |
| |
| parent::__construct( $configuration ); |
| } |
| |
| /** |
| * Executes this node. |
| * |
| * @param ezcWorkflowExecution $execution |
| * @return boolean true when the node finished execution, |
| * and false otherwise |
| * @ignore |
| */ |
| public function execute( ezcWorkflowExecution $execution ) |
| { |
| if ( $execution->definitionStorage === null ) |
| { |
| throw new ezcWorkflowExecutionException( |
| 'No ezcWorkflowDefinitionStorage implementation available.' |
| ); |
| } |
| |
| $workflow = $execution->definitionStorage->loadByName( $this->configuration['workflow'] ); |
| |
| // Sub Workflow is not interactive. |
| if ( !$workflow->isInteractive() && !$workflow->hasSubWorkflows() ) |
| { |
| $subExecution = $execution->getSubExecution( null, false ); |
| $subExecution->workflow = $workflow; |
| |
| $this->passVariables( |
| $execution, $subExecution, $this->configuration['variables']['in'] |
| ); |
| |
| $subExecution->start(); |
| } |
| // Sub Workflow is interactive. |
| else |
| { |
| // Sub Workflow is to be started. |
| if ( $this->state == 0 ) |
| { |
| $subExecution = $execution->getSubExecution(); |
| $subExecution->workflow = $workflow; |
| |
| $this->passVariables( |
| $execution, $subExecution, $this->configuration['variables']['in'] |
| ); |
| |
| $subExecution->start( $execution->getId() ); |
| |
| $this->state = $subExecution->getId(); |
| } |
| // Sub Workflow is to be resumed. |
| else |
| { |
| $subExecution = $execution->getSubExecution( $this->state ); |
| $subExecution->workflow = $workflow; |
| $subExecution->resume( $execution->getVariables() ); |
| } |
| } |
| |
| // Execution of Sub Workflow was cancelled. |
| if ( $subExecution->isCancelled() ) |
| { |
| $execution->cancel( $this ); |
| } |
| |
| // Execution of Sub Workflow has ended. |
| if ( $subExecution->hasEnded() ) |
| { |
| $this->passVariables( |
| $subExecution, $execution, $this->configuration['variables']['out'] |
| ); |
| |
| $this->activateNode( $execution, $this->outNodes[0] ); |
| |
| $this->state = 0; |
| |
| return parent::execute( $execution ); |
| } |
| |
| // Execution of Sub Workflow has been suspended. |
| foreach ( $subExecution->getWaitingFor() as $variableName => $data ) |
| { |
| $execution->addWaitingFor( $this, $variableName, $data['condition'] ); |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Generate node configuration from XML representation. |
| * |
| * @param DOMElement $element |
| * @return array |
| * @ignore |
| */ |
| public static function configurationFromXML( DOMElement $element ) |
| { |
| $configuration = array( |
| 'workflow' => $element->getAttribute( 'subWorkflowName' ), |
| 'variables' => array( |
| 'in' => array(), 'out' => array() |
| ) |
| ); |
| |
| $xpath = new DOMXPath( $element->ownerDocument ); |
| $in = $xpath->query( 'in/variable', $element ); |
| $out = $xpath->query( 'out/variable', $element ); |
| |
| foreach ( $in as $variable ) |
| { |
| $configuration['variables']['in'][$variable->getAttribute( 'name' )] = $variable->getAttribute( 'as' ); |
| } |
| |
| foreach ( $out as $variable ) |
| { |
| $configuration['variables']['out'][$variable->getAttribute( 'name' )] = $variable->getAttribute( 'as' ); |
| } |
| |
| return $configuration; |
| } |
| |
| /** |
| * Generate XML representation of this node's configuration. |
| * |
| * @param DOMElement $element |
| * @ignore |
| */ |
| public function configurationToXML( DOMElement $element ) |
| { |
| $element->setAttribute( 'subWorkflowName', $this->configuration['workflow'] ); |
| |
| if ( !empty( $this->configuration['variables']['in'] ) ) |
| { |
| $in = $element->appendChild( |
| $element->ownerDocument->createElement( 'in' ) |
| ); |
| |
| foreach ( $this->configuration['variables']['in'] as $fromName => $toName ) |
| { |
| $variable = $in->appendChild( |
| $in->ownerDocument->createElement( 'variable' ) |
| ); |
| |
| $variable->setAttribute( 'name', $fromName ); |
| $variable->setAttribute( 'as', $toName ); |
| } |
| } |
| |
| if ( !empty( $this->configuration['variables']['out'] ) ) |
| { |
| $out = $element->appendChild( |
| $element->ownerDocument->createElement( 'out' ) |
| ); |
| |
| foreach ( $this->configuration['variables']['out'] as $fromName => $toName ) |
| { |
| $variable = $out->appendChild( |
| $out->ownerDocument->createElement( 'variable' ) |
| ); |
| |
| $variable->setAttribute( 'name', $fromName ); |
| $variable->setAttribute( 'as', $toName ); |
| } |
| } |
| } |
| |
| /** |
| * Returns a textual representation of this node. |
| * |
| * @return string |
| * @ignore |
| */ |
| public function __toString() |
| { |
| return 'Sub Workflow: ' . $this->configuration['workflow']; |
| } |
| |
| /** |
| * Passes variables from one execution context to another. |
| * |
| * @param ezcWorkflowExecution $from The execution context the variables are passed from. |
| * @param ezcWorkflowExecution $to The execution context the variables are passed to. |
| * @param array $variables The names of the variables. |
| * @throws ezcWorkflowExecutionException if a variable that is to be passed does not exist. |
| * @ignore |
| */ |
| protected function passVariables( ezcWorkflowExecution $from, ezcWorkflowExecution $to, array $variables ) |
| { |
| foreach ( $variables as $fromName => $toName ) |
| { |
| $to->setVariable( $toName, $from->getVariable( $fromName ) ); |
| } |
| } |
| } |
| ?> |