Perforce Chronicle 2012.2/486814
API Documentation

Workflow_Model_Transition Class Reference

Model for a transition (permits moving from one state to another). More...

Inheritance diagram for Workflow_Model_Transition:
P4Cms_Model P4Cms_ModelInterface

List of all members.

Public Member Functions

 areConditionsMetFor (P4Cms_Record $record, array $pending=null)
 Determine if conditions are satisfied for this transition and record.
 getActions ()
 Get the actions to invoke when this transition occurs.
 getConditions ()
 Get the conditions placed on this transition.
 getFromState ()
 Return state model that this transition moves from.
 getLabel ()
 Get the current label.
 getToState ()
 Return state model that this transition moves to.
 getWorkflow ()
 Get a workflow that this transition is part of.
 invokeActionsOn (P4Cms_Record $record)
 Invoke actions for this transition on the given record.
 setFromState (Workflow_Model_State $state)
 Set state this transition moves from.
 setToState (Workflow_Model_State $state)
 Set state this transition moves to.

Protected Member Functions

 _getPlugins ($type)
 Get the defined plugins of the given type for this transition.
 _setWorkflowFromState (Workflow_Model_State $state)
 Set a workflow governing this transition from the given state.

Static Protected Attributes

static $_fields

Detailed Description

Model for a transition (permits moving from one state to another).

Transitions are defined by the workflow. Each state may have zero or more transitions to other states. Transitions can also define conditions that govern whether or not the transition is allowed.

See Workflow_Model_Workflow for more details.

Copyright:
2011-2012 Perforce Software. All rights reserved
License:
Please see LICENSE.txt in top-level folder of this distribution.
Version:
2012.2/486814

Member Function Documentation

Workflow_Model_Transition::_getPlugins ( type) [protected]

Get the defined plugins of the given type for this transition.

Parameters:
string$typethe type of plugins to get
Returns:
array instances of the defined plugins of the given type
    {
        $definitions = $this->_getValue($type . 's');
        if (!is_array($definitions)) {
            return array();
        }
        
        $plugins = array();
        $loader  = Workflow_Module::getPluginLoader($type);
        foreach ($definitions as $key => $definition) {
            
            // get the short name of the plugin class - four cases:
            //  1. definition is a string, we take that to be the name.
            //  2. definition is an array with an explicit $type element
            //     (e.g. 'condition' or 'action'), we use this value.
            //  3. definition is an array without an explicit $type element 
            //     and key is a string, we take the key to be the name.
            //  4. none of the above - we skip it.
            if (is_string($definition)) {
                $name = $definition;
            } else if (isset($definition[$type])) {
                $name = $definition[$type];
            } else if (is_array($definition) && is_string($key)) {
                $name = $key;
            } else {
                continue;
            }

            // attempt to resolve the condition class.
            $class = $loader->load($name, false);
            
            // skip invalid plugin classes
            $interface = 'Workflow_' . ucfirst($type) . 'Interface';
            if (!$class 
                || !class_exists($class) 
                || !in_array($interface, class_implements($class))
            ) {
                continue;
            }
            
            // pull options from the definition - options can be specified at
            // the top-level of the definition, or under 'options' (latter wins)
            $options = array();
            if (is_array($definition)) {
                $definition['options'] = isset($definition['options'])
                    ? (array) $definition['options']
                    : array();
                
                $exclude = array($type => null, 'options' => null);
                $options = array_diff_key($definition, $exclude);
                $options = array_merge($options, $definition['options']);
            }
            
            // make the plugin object
            $plugins[] = new $class($options);
        }
        
        return $plugins;
    }
Workflow_Model_Transition::_setWorkflowFromState ( Workflow_Model_State state) [protected]

Set a workflow governing this transition from the given state.

If workflow has been already set to this model, it also checks if given state is goverened by this workflow.

Parameters:
Workflow_Model_State$statestate to get workflow from.
Exceptions:
Workflow_Exceptionif workflow governing the state and this transition are not same.
    {
        // get workflow from the state model and check if it is the same
        // as workflow set to this transition (if applicable)
        $workflow = $state->getWorkflow();
        if ($this->_getValue('workflow') instanceof Workflow_Model_Workflow
            && $this->_getValue('workflow') !== $workflow
        ) {
            throw new Workflow_Exception(
                "State must refer to the same workflow as the transition."
            );
        }

        return $this->_setValue('workflow', $workflow);
    }
Workflow_Model_Transition::areConditionsMetFor ( P4Cms_Record record,
array $  pending = null 
)

Determine if conditions are satisfied for this transition and record.

If this transition has no conditions specified it evaluates as true, except for content records for which we also verify that the user has permission to publish content if to-state is 'published'

There is the option of passing an array of pending values to consider when evaluating conditions. These would typically come from a request as the user makes changes to the record.

Parameters:
P4Cms_Record$recordthe record to evaluate for context.
array | null$pendingoptional - updated values to consider.
Returns:
bool true if conditions for this transition are satisfied for given record, false otherwise.
    {
        // perform special checks for content type records
        if ($record instanceof P4Cms_Content) {

            // deny if no active user
            if (!P4Cms_User::hasActive()) {
                return false;
            }

            $user      = P4Cms_User::fetchActive();
            $toPublish = $this->getToState()->getId() === Workflow_Model_State::PUBLISHED;

            // deny if to-state is published and user doesn't have permission to publish
            if ($toPublish && !$user->isAllowed('content', 'publish')) {
                return false;
            }

            // deny if to-state is not published and user doesn't have access
            // to unpublished content
            // limit this check to only those entries having the owner, as otherwise
            // some of valid transitions will be filtered out when adding a new content
            // (assuming that current user will become the owner of an 'un-owned' content
            // after save)
            if (!$toPublish
                && strlen($record->getOwner())
                && !$user->isAllowed('content', 'access-unpublished')
                && $record->getOwner() !== $user->getId()
            ) {
                return false;
            }
        }

        // loop through all conditions and evaluate them in context
        foreach ($this->getConditions() as $condition) {
            // early exit if condition is not met
            if (!$condition->evaluate($this, $record, $pending)) {
                return false;
            }
        }

        // all conditions are met (or this transition has no conditions)
        return true;
    }
Workflow_Model_Transition::getActions ( )

Get the actions to invoke when this transition occurs.

Returns:
array a list of action objects
    {
        return $this->_getPlugins('action');
    }
Workflow_Model_Transition::getConditions ( )

Get the conditions placed on this transition.

Returns:
array a list of condition objects
    {
        return $this->_getPlugins('condition');
    }
Workflow_Model_Transition::getFromState ( )

Return state model that this transition moves from.

Returns:
Workflow_Model_State state that this transition moves from.
    {
        if (!$this->_getValue('fromState') instanceof Workflow_Model_State) {
            throw new Workflow_Exception(
                "Cannot get state the transition moves from. No 'from' state has been set."
            );
        }

        return $this->_getValue('fromState');
    }
Workflow_Model_Transition::getLabel ( )

Get the current label.

Returns:
string the current label or id if label is empty or not a string.
    {
        $label = $this->_getValue('label');
        return is_string($label) && strlen($label) ? $label : (string) $this->getId();
    }
Workflow_Model_Transition::getToState ( )

Return state model that this transition moves to.

Returns:
Workflow_Model_State state that this transition moves to.
    {
        if (!$this->_getValue('toState') instanceof Workflow_Model_State) {
            throw new Workflow_Exception(
                "Cannot get state the transition moves to. No 'to' state has been set."
            );
        }

        return $this->_getValue('toState');
    }
Workflow_Model_Transition::getWorkflow ( )

Get a workflow that this transition is part of.

Returns:
Workflow_Model_Workflow workflow this transition is part of.
Exceptions:
Workflow_Exceptionif no valid workflow has been set.
    {
        if (!$this->_getValue('workflow') instanceof Workflow_Model_Workflow) {
            throw new Workflow_Exception(
                "Cannot get workflow for transition. No workflow has been set."
            );
        }

        return $this->_getValue('workflow');
    }
Workflow_Model_Transition::invokeActionsOn ( P4Cms_Record record)

Invoke actions for this transition on the given record.

Parameters:
P4Cms_Record$recordthe record to invoke actions on.
Returns:
Workflow_Model_Transition provides fluent interface.
    {
        // loop through all actions and invoke them in context
        foreach ($this->getActions() as $action) {
            $action->invoke($this, $record);
        }

        return $this;
    }
Workflow_Model_Transition::setFromState ( Workflow_Model_State state)

Set state this transition moves from.

Parameters:
Workflow_Model_State$statestate model this transition moves from.
    {
        // set workflow from the state model
        $this->_setWorkflowFromState($state);

        return $this->_setValue('fromState', $state);
    }
Workflow_Model_Transition::setToState ( Workflow_Model_State state)

Set state this transition moves to.

Parameters:
Workflow_Model_State$statestate model this transition moves to.
    {
        // set workflow from the state model
        $this->_setWorkflowFromState($state);

        return $this->_setValue('toState', $state);
    }

Member Data Documentation

Workflow_Model_Transition::$_fields [static, protected]
Initial value:
 array(
        'label'         => array(
            'accessor'  => 'getLabel'
        ),
        'workflow'      => array(
            'accessor'  => 'getWorkflow'
        ),
        'fromState'     => array(
            'accessor'  => 'getFromState',
            'mutator'   => 'setFromState'
        ),
        'toState'       => array(
            'accessor'  => 'getToState',
            'mutator'   => 'setToState'
        ),
        'conditions'    => array(
            'accessor'  => 'getConditions'
        ),
        'actions'    => array(
            'accessor'  => 'getActions'
        ),
    )

Reimplemented from P4Cms_Model.


The documentation for this class was generated from the following file: