Perforce Chronicle 2012.2/486814
API Documentation

Workflow_Model_Workflow Class Reference

Provides storage of workflow definitions. More...

Inheritance diagram for Workflow_Model_Workflow:
P4Cms_Record P4Cms_Record_Connected P4Cms_Model P4Cms_ModelInterface

List of all members.

Public Member Functions

 detectTransitionOn (P4Cms_Record $record)
 Check for a transition on the given record.
 getDefaultState ()
 The first state defined is (by convention) the default state.
 getDescription ()
 Get the current description.
 getLabel ()
 Get the current label.
 getScheduledStateOf (P4Cms_Record $record)
 Return scheduled workflow state of the given record or null if record doesn't have any scheduled transition.
 getScheduledTimeOf (P4Cms_Record $record)
 Return timestamp for the scheduled transition or null if record doesn't have any scheduled transition.
 getState ($name)
 Get specified state from the states making up this workflow.
 getStateModel ($name)
 Get specified state from this workflow as model.
 getStateModels ()
 Get the states in this workflow as models.
 getStateOf (P4Cms_Record $record)
 Return workflow state of the given record.
 getStates ()
 Get the states making up this workflow.
 getStatesAsIni ()
 Get the states in INI format.
 hasState ($name)
 Determine if this workflow has the given state.
 setDescription ($description)
 Set a new description.
 setLabel ($label)
 Set a new label.
 setScheduledStateOf (P4Cms_Record $record, $state, $time)
 Set the target state and the time of the scheduled transition for the given record.
 setStateOf (P4Cms_Record $record, $state)
 Sets the state of the given record.
 setStates ($states)
 Set the states making up this workflow.
 setStatesFromIni ($states)
 Set the states in the INI format.

Static Public Member Functions

static fetchByContent (P4Cms_Content $entry)
 Return workflow model for the given content entry or throw an exception if entry has no workflow.
static fetchTypeMap (P4Cms_Record_Adapter $adapter=null)
 Return array iterator with content types mapped to their associated workflows.
static installDefaultWorkflows (P4Cms_Record_Adapter $adapter=null)
 Collect all of the default workflows and install them.
static installPackageDefaults (P4Cms_PackageAbstract $package, P4Cms_Record_Adapter $adapter=null)
 Install the default workflows contributed by a package.
static makePublishedContentFilter ($scheduled=false, P4Cms_Record_Adapter $adapter=null)
 Creates record filter to allow only entries in a published state.
static makeScheduledContentFilter ($timestamp=null, P4Cms_Record_Adapter $adapter=null)
 Creates record filter to allow only entries with scheduled transitions, where the scheduled time is older than the given timestamp.
static makeStatesContentFilter (array $workflowFilterStates, $scheduled=false, P4Cms_Record_Adapter $adapter=null)
 Creates record filter to keep only entries having states specified in $states parameter.
static makeUnpublishedContentFilter ($scheduled=false, P4Cms_Record_Adapter $adapter=null)
 Creates record filter to allow only entries in an unpublished state.
static removePackageDefaults (P4Cms_PackageAbstract $package, P4Cms_Record_Adapter $adapter=null)
 Remove workflows contributed by a package.

Protected Member Functions

 _getStateId ($state)
 Helper method to get state id from any valid state representation (string or object).

Protected Attributes

 $_states = null

Static Protected Attributes

static $_fields
 Specifies the array of fields that the current Record class wishes to use.
static $_fileContentField = 'states'
 Specifies the name of the record field which will be persisted in the file used to store the records.
static $_storageSubPath = 'workflows'
 Specifies the sub-path to use for storage of records.

Detailed Description

Provides storage of workflow definitions.

The important part of the workflow is defined in the states field in INI format. Each state may define a label and zero or more transitions.

Transitions permit movement from one state to another. Each transition may define a label, conditions and actions.

Conditions are special classes that, when evaluated, control whether or not a transition should be allowed for the given record at that time.

Actions are special classes that, when invoked, perform automated tasks in response to a transition occurring on a record under workflow.

For example:

[draft] label = Draft transitions.review.label = Promote to Review transitions.review.actions.email.action = SendEmail transitions.review.actions.email.toRole = reviewers transitions.published.label = Publish

[review] label = Review transitions.draft.label = Demote to Draft transitions.published.label = Publish transitions.published.conditions[] = IsCategorized

[published] label = Published transitions.review.label = Demote to Review transitions.draft.label = Demote to Draft

Conditions may be specified a couple of different ways. Each condition can be specified as a simple string (as above), in which case the string will be taken to be the short-form name of the condition class (resolved via the condition loader).

Conditions can also be specified in a longer form that permits the inclusion of options. For example:

transitions.published.conditions.IsCategorized.maxDepth = 5

In the above example, the key of the condition is taken to be the short-form name of the condition class. If you need to use the same condition class more than once, you can specify a 'condition' key and that will be used instead. For example:

transitions.published.conditions.categorized.condition = IsCategorized transitions.published.conditions.categorized.maxDepth = 5

Just like conditions, actions can be specified as a string (with no options) or as an array that permits options (see the SendEmail action in the example workflow definition above).

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_Workflow::_getStateId ( state) [protected]

Helper method to get state id from any valid state representation (string or object).

It also checks if state is valid for this workflow.

Parameters:
string | Workflow_Model_State$staterepresentation of a workflow state.
Exceptions:
InvalidArgumentExceptionif $state is neither string nor instance of Workflow_Model_State.
Workflow_Exceptionif state is not governed by this workflow.
Returns:
string state id id of the given state.
    {
        if ($state instanceof Workflow_Model_State) {
            $state = $state->getId();
        } else if (!is_string($state)) {
            throw new InvalidArgumentException(
                "State must be a string or instance of Workflow_Model_State class."
            );
        }

        // check if given state is governed by this workflow
        if (!$this->hasState($state)) {
            throw new Workflow_Exception(
                "Cannot set state on the given record. State is undefined or governed by other workflow."
            );
        }

        return $state;
    }
Workflow_Model_Workflow::detectTransitionOn ( P4Cms_Record record)

Check for a transition on the given record.

Record must be in an opened/pending state to detect the transition. If the record is in transition, returns the appropriate transition model.

Parameters:
P4Cms_Record$recordrecord to detect transition on.
Returns:
null|Workflow_Model_Transition the appropriate transition model or null if the given record is not in transition.
    {
        // try to get the associated p4 file - we need the file to
        // know if a transition is underway vs. already committed.
        try {
            $file = $record->toP4File();
        } catch (Exception $e) {
            throw new Workflow_Exception(
                "Cannot detect transition on record. Unable to get required file object."
            );
        }

        $field     = Workflow_Model_State::RECORD_FIELD;
        $fromState = $file->hasAttribute($field) ? $file->getAttribute($field) : null;
        $toState   = $file->hasOpenAttribute($field) ? $file->getOpenAttribute($field) : null;

        // if no valid from state, assume previous state is default state.
        if (!$this->hasState($fromState)) {
            $fromState = $this->getDefaultState()->getId();
        }

        // if no valid to state, assume to state is default state.
        if (!$this->hasState($toState)) {
            $toState = $this->getDefaultState()->getId();
        }

        // no transition if from-state and to-state are the same.
        if ($fromState == $toState) {
            return;
        }

        // no transition if from-state has no transition for to-state.
        // could arguably throw an exception here (how did this happen?)
        // but we don't throw because the caller didn't ask us to validate
        // the state of the record, just to see if we could detect a
        // transition and return the appropriate transition model.
        $fromStateModel = $this->getStateModel($fromState);
        if (!$fromStateModel->hasTransition($toState)) {
            return;
        }

        return $fromStateModel->getTransitionModel($toState);
    }
static Workflow_Model_Workflow::fetchByContent ( P4Cms_Content entry) [static]

Return workflow model for the given content entry or throw an exception if entry has no workflow.

Parameters:
P4Cms_Content$entrycontent entry to get workflow for.
Returns:
Workflow_Model_Workflow workflow model for the given entry.
Exceptions:
Workflow_Exceptionif entry has no workflow.
    {
        // get content type
        try {
            $type = $entry->getContentType();
        } catch (P4Cms_Content_Exception $e) {
            $type = null;
        }

        if (!$type || !$type->workflow || !static::exists($type->workflow, null, $entry->getAdapter())) {
            throw new Workflow_Exception(
                "Cannot fetch workflow for the content entry '" + $entry->getId() . "'."
            );
        }

        return static::fetch($type->workflow, null, $entry->getAdapter());
    }
static Workflow_Model_Workflow::fetchTypeMap ( P4Cms_Record_Adapter adapter = null) [static]

Return array iterator with content types mapped to their associated workflows.

Content types that have no worfklow associated are not present in the map.

Parameters:
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Model_Iterator list with content type ids (keys) mapped to associated workflow models (values).
    {
        // get array with workflow_id => workflow_model mappings
        $workflows = array();
        foreach (static::fetchAll(null, $adapter) as $workflow) {
            $workflows[$workflow->getId()] = $workflow;
        }

        // assemble array iterator with content_type_id => workflow_model mappings
        $map = new P4Cms_Model_Iterator;
        foreach (P4Cms_Content_Type::fetchAll(null, $adapter) as $type) {
            if (array_key_exists($type->workflow, $workflows)) {
                $map[$type->getId()] = $workflows[$type->workflow];
            }
        }

        return $map;
    }
Workflow_Model_Workflow::getDefaultState ( )

The first state defined is (by convention) the default state.

Returns:
Workflow_Model_State the default state for content using this workflow
    {
        return $this->getStateModels()->first();
    }
Workflow_Model_Workflow::getDescription ( )

Get the current description.

Returns:
string|null the current description or null.
    {
        return $this->_getValue('description');
    }
Workflow_Model_Workflow::getLabel ( )

Get the current label.

Returns:
string|null the current label or null.
    {
        return $this->_getValue('label');
    }
Workflow_Model_Workflow::getScheduledStateOf ( P4Cms_Record record)

Return scheduled workflow state of the given record or null if record doesn't have any scheduled transition.

Parameters:
P4Cms_Record$recordrecord to determine scheduled state for.
Returns:
Workflow_Model_State|null workflow target state of the scheduled transition for the given record or null if no scheduled transition.
    {
        $recordState = $record->getValue(Workflow_Model_State::RECORD_SCHEDULED_FIELD);
        return ($recordState && $this->hasState($recordState))
            ? $this->getStateModel($recordState)
            : null;
    }
Workflow_Model_Workflow::getScheduledTimeOf ( P4Cms_Record record)

Return timestamp for the scheduled transition or null if record doesn't have any scheduled transition.

Parameters:
P4Cms_Record$recordrecord to determine time of the scheduled transition.
Returns:
int|null timestamp of the scheduled transition or null if record doesn't have any scheduled transition.
    {
        $time = $record->getValue(Workflow_Model_State::RECORD_TIME_FIELD);
        return $time ? (int) $time : null;
    }
Workflow_Model_Workflow::getState ( name)

Get specified state from the states making up this workflow.

Parameters:
string$namestate name.
Returns:
array field details for the named state.
Exceptions:
Workflow_Exceptionif state is not found between states making up this workflow.
    {
        $states = $this->getStates();

        // return an empty array if invalid state specified
        if (!array_key_exists($name, $states)) {
            throw new Workflow_Exception(
                "State '$name' not found between the states making up this workflow."
            );
        }

        return $states[$name];
    }
Workflow_Model_Workflow::getStateModel ( name)

Get specified state from this workflow as model.

Parameters:
string$namestate name.
Returns:
Workflow_Model_State workflow state model.
    {
        $state = new Workflow_Model_State($this->getState($name));
        $state->setId($name)
              ->setWorkflow($this);

        return $state;
    }
Workflow_Model_Workflow::getStateModels ( )

Get the states in this workflow as models.

Returns:
P4Cms_Model_Iterator states making up this workflow.
    {
        $states = new P4Cms_Model_Iterator();
        foreach ($this->getStates() as $name => $values) {
            $states[] = $this->getStateModel($name);
        }

        return $states;
    }
Workflow_Model_Workflow::getStateOf ( P4Cms_Record record)

Return workflow state of the given record.

Returns state model (defined by this workflow) whose key matches the record's workflowState field value. If record doesn't have workflowState field or workflowState value doesn't match any of state keys defined by this workflow, default state of this workflow is returned.

Its user's responsibility to call this method on a correct workflow object in relation to the provided record.

Parameters:
P4Cms_Record$recordrecord to determine state for.
Returns:
Workflow_Model_State workflow state of given record.
    {
        $recordState = $record->getValue(Workflow_Model_State::RECORD_FIELD);
        return ($recordState && $this->hasState($recordState))
            ? $this->getStateModel($recordState)
            : $this->getDefaultState();
    }
Workflow_Model_Workflow::getStates ( )

Get the states making up this workflow.

Returns:
array the list of states (state definitions).
    {
        if ($this->_states === null) {
            // convert states INI string to an array using Zend_Config_Ini
            // write states to a temp file to facilitate Zend_Config_Ini parsing
            $tempFile = tempnam(sys_get_temp_dir(), 'workflow');
            file_put_contents($tempFile, $this->_getValue('states'));
            $config   = new Zend_Config_Ini($tempFile);
            $states   = $config->toArray();
            unlink($tempFile);

            $this->_states = is_array($states) ? $states : array();
        }

        return $this->_states;
    }
Workflow_Model_Workflow::getStatesAsIni ( )

Get the states in INI format.

Returns:
string List of workflow states in INI format.
    {
        return $this->_getValue('states');
    }
Workflow_Model_Workflow::hasState ( name)

Determine if this workflow has the given state.

Parameters:
string$namethe name of the state to check for.
Returns:
bool true if the given state is one of those making up this workflow, false otherwise.
    {
        return array_key_exists($name, $this->getStates());
    }
static Workflow_Model_Workflow::installDefaultWorkflows ( P4Cms_Record_Adapter adapter = null) [static]

Collect all of the default workflows and install them.

Parameters:
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
    {
        // clear the module/theme cache
        P4Cms_Module::clearCache();
        P4Cms_Theme::clearCache();

        // get all enabled modules.
        $packages = P4Cms_Module::fetchAllEnabled();

        // add current theme to packages since it may provide workflows.
        if (P4Cms_Theme::hasActive()) {
            $packages[] = P4Cms_Theme::fetchActive();
        }

        // install default workflows for each package.
        foreach ($packages as $package) {
            static::installPackageDefaults($package, $adapter);
        }
    }
static Workflow_Model_Workflow::installPackageDefaults ( P4Cms_PackageAbstract package,
P4Cms_Record_Adapter adapter = null 
) [static]

Install the default workflows contributed by a package.

Parameters:
P4Cms_PackageAbstract$packagethe package whose workflows will be installed
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
    {
        // if no adapter given, use default.
        $adapter = $adapter ?: static::getDefaultAdapter();

        $info = $package->getPackageInfo();

        // get the default workflows provided by the package
        $workflows = isset($info['workflows']) && is_array($info['workflows'])
               ? $info['workflows']
               : array();

        foreach ($workflows as $id => $workflow) {
            // skip existing workflows
            if (static::exists($id, null, $adapter)) {
                continue;
            }

            // associate with content types (only if the content
            // type doesn't already have a workflow specified)
            $types = isset($workflow['types'])
                ? (array) $workflow['types']
                : array();
            unset($workflow['types']);
            foreach ($types as $type) {
                if (P4Cms_Content_Type::exists($type, null, $adapter)) {
                    $type = P4Cms_Content_Type::fetch($type, null, $adapter);
                    if (!$type->getValue('workflow')) {
                        $type->setValue('workflow', $id)
                             ->save();
                    }
                }
            }

            // make and save the workflow
            $workflow['id'] = $id;
            $workflow       = new static($workflow, $adapter);
            $workflow->save();
        }
    }
static Workflow_Model_Workflow::makePublishedContentFilter ( scheduled = false,
P4Cms_Record_Adapter adapter = null 
) [static]

Creates record filter to allow only entries in a published state.

If filters are applied to the current status then entry is considered as published if and only if: 1. entry is not under any workflow OR 2. entry is under workflow (lets denote it W) AND has workflowState attribute equals to 'published' which is a valid state of the workflow W.

If filters are applied to the scheduled status, then entry is considered as published if and only if: 1. entry is under workflow AND 2. workflowScheduledState attribute is equal to 'published'.

Parameters:
boolean$scheduled(optional) if true, then filter will be applied to the scheduled state, otherwise to the current state; false by default
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Record_Filter record filter that only content entries in published state can pass.
    {
        // collect all content types which are either under no workflow
        // (implicitly published) or have a valid workflow which has a
        // published state
        $types       = P4Cms_Content_Type::fetchAll(null, $adapter);
        $workflows   = static::fetchAll(null, $adapter);
        $noWorkflow  = array();
        $publishable = array();
        foreach ($types as $type) {
            // if this type isn't under workflow; collect the id and continue
            if (!$type->workflow) {
                $noWorkflow[] = $type->getId();
                continue;
            }

            // if this type has an invalid workflow or lacks a published state skip it
            $workflow = isset($workflows[$type->workflow]) ? $workflows[$type->workflow] : null;
            if (!$workflow || !$workflow->hasState(Workflow_Model_State::PUBLISHED)) {
                continue;
            }

            $publishable[] = $type->getId();
        }

        // create a filter which whitelists in the known publishable and
        // implicitly published content types. we do it this way to ensure
        // any unknown content types or workflows don't show as published.
        $filter = new P4Cms_Record_Filter;

        // get name of the record field where the filter will be applied to
        $field = $scheduled
            ? Workflow_Model_State::RECORD_SCHEDULED_FIELD
            : Workflow_Model_State::RECORD_FIELD;

        // deal with filtering for types that have a published state
        if ($publishable) {
            $filter->addSubFilter(
                P4Cms_Record_Filter::create()
                ->add($field, array(Workflow_Model_State::PUBLISHED))
                ->add(P4Cms_Content::TYPE_FIELD, $publishable)
            );
        }

        // capture types that have no workflow
        // so long as we aren't looking for a scheduled transition
        if (!$scheduled && $noWorkflow) {
            $filter->addSubFilter(
                P4Cms_Record_Filter::create()->add(P4Cms_Content::TYPE_FIELD, $noWorkflow),
                $filter::CONNECTIVE_OR
            );
        }

        // if there are no candidates return a fixed false expression
        if ($filter->getExpression() === '') {
            return new P4Cms_Record_Filter(P4Cms_Record_Filter::FALSE_EXPRESSION);
        }

        return $filter;
    }
static Workflow_Model_Workflow::makeScheduledContentFilter ( timestamp = null,
P4Cms_Record_Adapter adapter = null 
) [static]

Creates record filter to allow only entries with scheduled transitions, where the scheduled time is older than the given timestamp.

Parameters:
int | string$timestampoptional - timestamp to determine if scheduled transition is in the past; current time will be used if not set
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Record_Filter record filter to keep only content entries with scheduled transitions to happen before the time specified by the timestamp
    {
        $timestamp       = $timestamp ?: time();
        $workflowsByType = static::fetchTypeMap($adapter);

        // if no types are under workflow; nothing matches
        if (!$workflowsByType->count()) {
            return new P4Cms_Record_Filter(P4Cms_Record_Filter::FALSE_EXPRESSION);
        }

        $filter = P4Cms_Record_Filter::create()
            ->add(
                Workflow_Model_State::RECORD_TIME_FIELD,
                (string) $timestamp,
                P4Cms_Record_Filter::COMPARE_LTE
            )
            ->add(
                Workflow_Model_State::RECORD_SCHEDULED_FIELD,
                '.+',
                P4Cms_Record_Filter::COMPARE_REGEX
            )
            ->add(
                'contentType',
                $workflowsByType->keys(),
                P4Cms_Record_Filter::COMPARE_EQUAL
            );

        return $filter;
    }
static Workflow_Model_Workflow::makeStatesContentFilter ( array $  workflowFilterStates,
scheduled = false,
P4Cms_Record_Adapter adapter = null 
) [static]

Creates record filter to keep only entries having states specified in $states parameter.

States array assumes to have workflow ids in keys and selected state ids in values.

Entry is considered having given state (W denotes the workflow that given state is defined under):

entry is under workflow W AND status attribute matches the given state OR state is default state for the workflow W AND status attribute is unset or not equal to any of the states defined by the workflow W.

if applied to the current state, and

entry is under workflow W AND S matches the given state

if applied to the scheduled state.

Parameters:
array$workflowFilterStatesarray with states organized by workflows
boolean$scheduled(optional) if true, then filter will be applied to the scheduled state, otherwise to the current state; false by default
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Record_Filter record filter to keep only content entries that are under one of the specified states.
    {
        // early exit if no states provided
        if (!count($workflowFilterStates)) {
            return new P4Cms_Record_Filter;
        }

        // get name of the record field where the filter will be applied to
        $field = $scheduled
            ? Workflow_Model_State::RECORD_SCHEDULED_FIELD
            : Workflow_Model_State::RECORD_FIELD;

        // get arrays with default workflow states and all states keyed by governing workflow
        $defaultStates = array();
        $allStates     = array();
        foreach (static::fetchAll(null, $adapter) as $workflow) {
            $workflowId                 = $workflow->getId();
            $defaultStates[$workflowId] = $workflow->getDefaultState()->getId();
            $allStates[$workflowId]     = $workflow->getStateModels()->invoke('getId');
        }

        // get the workflows keyed by content type
        $workflowsByType = static::fetchTypeMap($adapter);

        // get content types keyed by associated workflows
        $typesByWorkflow = array();
        foreach ($workflowsByType as $type => $workflow) {
            if (!isset($typesByWorkflow[$workflow->getId()])) {
                $typesByWorkflow[$workflow->getId()] = array();
            }
            $typesByWorkflow[$workflow->getId()][] = $type;
        }

        // construct record filter for given workflow states
        $filter = new P4Cms_Record_Filter;
        foreach ($workflowFilterStates as $workflow => $states) {

            // skip if workflow is not associated with any content type
            // or unknown workflow
            if (!array_key_exists($workflow, $typesByWorkflow)
                || !array_key_exists($workflow, $defaultStates)
            ) {
                continue;
            }

            // create filter to keep entries having given states
            $stateFilter = P4Cms_Record_Filter::create()
                ->add(
                    $field,
                    $states,
                    P4Cms_Record_Filter::COMPARE_EQUAL
                );

            // if applied to a current state then for default states include
            // entries having invalid state as they automatically become default
            // state
            if (!$scheduled && in_array($defaultStates[$workflow], $states)) {
                $stateFilter->add(
                    $field,
                    $allStates[$workflow],
                    P4Cms_Record_Filter::COMPARE_NOT_EQUAL,
                    P4Cms_Record_Filter::CONNECTIVE_OR
                );
            }

            // add a subfilter limiting the content types governed by
            // this workflow to the state filter created above
            $filter->addSubFilter(
                P4Cms_Record_Filter::create()
                ->add(
                    'contentType',
                    $typesByWorkflow[$workflow],
                    P4Cms_Record_Filter::COMPARE_EQUAL
                )
                ->addSubFilter(
                    $stateFilter,
                    P4Cms_Record_Filter::CONNECTIVE_AND
                ),
                P4Cms_Record_Filter::CONNECTIVE_OR
            );
        }

        // don't let pass any entry if filter is empty (e.g. if selection
        // contains states that are not used by any content types)
        if ($filter->getExpression() == '') {
            $filter = new P4Cms_Record_Filter(P4Cms_Record_Filter::FALSE_EXPRESSION);
        }

        return $filter;
    }
static Workflow_Model_Workflow::makeUnpublishedContentFilter ( scheduled = false,
P4Cms_Record_Adapter adapter = null 
) [static]

Creates record filter to allow only entries in an unpublished state.

If applied to current state, entry is unpublished if and only if its not published.

If applied to the scheduled state, entry must be also under a workflow.

Parameters:
boolean$scheduled(optional) if true, then filter will be applied to the scheduled state, otherwise to the current state; false by default
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Record_Filter record filter to keep only content entries not being published.
    {
        $publishedFilter = static::makePublishedContentFilter($scheduled, $adapter);

        // if filter for published entries is empty, i.e. all entries
        // are published, return filter that no entry can pass
        if ($publishedFilter->getExpression() === '') {
            return new P4Cms_Record_Filter(P4Cms_Record_Filter::FALSE_EXPRESSION);
        }

        // get filter inverted to publishedFilter
        $filter = P4Cms_Record_Filter::create()
            ->addSubfilter(
                $publishedFilter,
                P4Cms_Record_Filter::CONNECTIVE_AND_NOT
            );

        // if filter is applied to a scheduled state, exclude entries with unset
        // scheduled state field and also exclude entries not under workflow
        if ($scheduled) {
            $workflowsByType = static::fetchTypeMap($adapter);
            $filter
                ->add(
                    Workflow_Model_State::RECORD_SCHEDULED_FIELD,
                    '.+',
                    P4Cms_Record_Filter::COMPARE_REGEX
                )
                ->add(
                    'contentType',
                    $workflowsByType->keys(),
                    P4Cms_Record_Filter::COMPARE_EQUAL
                );
        }

        return $filter;
    }
static Workflow_Model_Workflow::removePackageDefaults ( P4Cms_PackageAbstract package,
P4Cms_Record_Adapter adapter = null 
) [static]

Remove workflows contributed by a package.

The workflows are only removed if they have not been edited.

Parameters:
P4Cms_PackageAbstract$packagethe package whose workflows are to be removed
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
    {
        // if no adapter given, use default.
        $adapter = $adapter ?: static::getDefaultAdapter();

        $info = $package->getPackageInfo();

        // get the default workflows provided by the package
        $workflows = isset($info['workflows']) && is_array($info['workflows'])
               ? $info['workflows']
               : array();

        foreach ($workflows as $id => $workflow) {
            // skip workflows that don't exist
            if (!static::exists($id, null, $adapter)) {
                continue;
            }

            // skip workflows that have been edited.
            $storedWorkflow = static::fetch($id, null, $adapter);
            $workflow['id'] = $id;
            unset($workflow['types']);
            $workflow       = new static($workflow, $adapter);
            if ($workflow->getValues() != $storedWorkflow->getValues()) {
                continue;
            }

            // skip workflows that are in use.
            // @todo    get associated content types and get list of state
            //          ids in this workflow - then, count content where
            //          content-type is in types and workflow-state is in
            //          defined states - if count > 0, continue.

            $storedWorkflow->delete("Package '" . $package->getName() . "' disabled.");
        }
    }
Workflow_Model_Workflow::setDescription ( description)

Set a new description.

Parameters:
string | null$descriptionthe new description to use.
Returns:
Workflow_Model_Workflow provides fluent interface.
    {
        if (!is_string($description) && !is_null($description)) {
            throw new InvalidArgumentException("Description must be a string or null.");
        }

        return $this->_setValue('description', $description);
    }
Workflow_Model_Workflow::setLabel ( label)

Set a new label.

Parameters:
string | null$labelthe new label to use.
Returns:
Workflow_Model_Workflow provides fluent interface.
    {
        if (!is_string($label) && !is_null($label)) {
            throw new InvalidArgumentException("Label must be a string or null.");
        }

        return $this->_setValue('label', $label);
    }
Workflow_Model_Workflow::setScheduledStateOf ( P4Cms_Record record,
state,
time 
)

Set the target state and the time of the scheduled transition for the given record.

Parameters:
P4Cms_Record$recordrecord to set scheduled state and time for.
Workflow_Model_State | string$statetarget state of the scheduled transition.
int$timetimestamp of the scheduled transition.
Returns:
Workflow_Model_Workflow provides fluent interface
    {
        $state = $this->_getStateId($state);

        // ensure date is in the future
        if (!is_int($time) || $time < time()) {
            throw new InvalidArgumentException(
                "Cannot schedule transition. Time must be an integer timestamp in the future."
            );
        }

        // ensure we have a valid current state
        $record->setValue(Workflow_Model_State::RECORD_FIELD, $this->getStateOf($record)->getId());

        // set schedule values
        $record->setValue(Workflow_Model_State::RECORD_SCHEDULED_FIELD, $state);
        $record->setValue(Workflow_Model_State::RECORD_TIME_FIELD, $time);

        return $this;
    }
Workflow_Model_Workflow::setStateOf ( P4Cms_Record record,
state 
)

Sets the state of the given record.

Parameters:
P4Cms_Record$recordrecord to set state to.
Workflow_Model_State | string$statestate to set for the given record.
Returns:
Workflow_Model_Workflow provides fluent interface.
    {
        $state = $this->_getStateId($state);

        // ensure transition is valid, but only if a transition is happening.
        $fromState = $this->getStateOf($record);
        if ($state !== $fromState->getId()) {
            $transitions   = $fromState->getValidTransitionsFor($record);
            $validToStates = new P4Cms_Model_Iterator($transitions->invoke('getToState'));
            if (!in_array($state, $validToStates->invoke('getId'))) {
                throw new Workflow_Exception(
                    "Cannot set state on the given record. Not a valid transition."
                );
            }
        }

        // set record field
        $record->setValue(Workflow_Model_State::RECORD_FIELD, $state);

        // clear schedule values
        $record->setValue(Workflow_Model_State::RECORD_SCHEDULED_FIELD, null);
        $record->setValue(Workflow_Model_State::RECORD_TIME_FIELD, null);

        return $this;
    }
Workflow_Model_Workflow::setStates ( states)

Set the states making up this workflow.

Parameters:
array | string | null$statesthe list of states (assumed to be in INI format. if given as a string) making up this workflow.
Returns:
Workflow_Model_Workflow provides fluent interface.
    {
        if (!is_null($states) && !is_array($states) && !is_string($states)) {
            throw new InvalidArgumentException(
                "Cannot set states. States must be given as an array, string or null."
            );
        }

        // if states given as string, assumed to be in INI format
        if (is_string($states)) {
            return $this->setStatesFromIni($states);
        }

        // if states given as non-null, convert to INI
        if (!is_null($states)) {
            // convert elements array to INI format
            $config = new Zend_Config($states);
            $writer = new Zend_Config_Writer_Ini();
            $states = $writer->setConfig($config)->render();
        }

        // reset states
        $this->_states = null;

        return $this->_setValue('states', $states);
    }
Workflow_Model_Workflow::setStatesFromIni ( states)

Set the states in the INI format.

Parameters:
string$statesthe list of states in the INI format.
    {
        if (!is_string($states)) {
            throw new InvalidArgumentException(
                "Cannot set states. States must be a string."
            );
        }

        // reset states
        $this->_states = null;

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

Member Data Documentation

Workflow_Model_Workflow::$_fields [static, protected]
Initial value:
 array(
        'label'         => array(
            'accessor'  => 'getLabel',
            'mutator'   => 'setLabel'
        ),
        'description'   => array(
            'accessor'  => 'getDescription',
            'mutator'   => 'setDescription'
        ),
        'states'        => array(
            'accessor'  => 'getStates',
            'mutator'   => 'setStates'
        )
    )

Specifies the array of fields that the current Record class wishes to use.

The implementing class MUST set this property.

Reimplemented from P4Cms_Record.

Workflow_Model_Workflow::$_fileContentField = 'states' [static, protected]

Specifies the name of the record field which will be persisted in the file used to store the records.

If desired, the implementing class needs to set this property to match an entry defined in the $_fields array. If left null, all fields will persist as file attributes.

Reimplemented from P4Cms_Record.

Workflow_Model_Workflow::$_states = null [protected]
Workflow_Model_Workflow::$_storageSubPath = 'workflows' [static, protected]

Specifies the sub-path to use for storage of records.

This is used in combination with the records path (provided by the storage adapter) to construct the full storage path. The implementing class MUST set this property.

Reimplemented from P4Cms_Record.


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