oWorkflow = $oWorkflow;
parent::KTPortlet($sTitle);
}
function render() {
if (is_null($this->oWorkflow)) { return _kt('No Workflow Selected.'); }
$aAdminPages = array();
$aAdminPages[] = array('name' => _kt('Overview'), 'query' => 'action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId());
$aAdminPages[] = array('name' => _kt('States'), 'query' => 'action=manageStates&fWorkflowId=' . $this->oWorkflow->getId());
$aAdminPages[] = array('name' => _kt('Transitions'), 'query' => 'action=manageTransitions&fWorkflowId=' . $this->oWorkflow->getId());
$aAdminPages[] = array('name' => _kt('Actions'), 'query' => 'action=manageActions&fWorkflowId=' . $this->oWorkflow->getId());
$oTemplating =& KTTemplating::getSingleton();
$oTemplate = $oTemplating->loadTemplate("ktcore/workflow/admin_portlet");
$aTemplateData = array(
"context" => $this,
"aAdminPages" => $aAdminPages,
);
return $oTemplate->render($aTemplateData);
}
}
class KTWorkflowDispatcher extends KTAdminDispatcher {
var $bAutomaticTransaction = true;
var $sHelpPage = 'ktcore/admin/workflow.html';
var $aWorkflowInfo;
var $oWorkflow;
function check() {
$this->aBreadcrumbs[] = array(
'url' => $_SERVER['PHP_SELF'],
'name' => _kt('Workflows'),
);
$this->oWorkflow =& KTWorkflow::get($_REQUEST['fWorkflowId']);
if (!PEAR::isError($this->oWorkflow)) {
$this->aBreadcrumbs[] = array(
'url' => $_SERVER['PHP_SELF'],
'query' => 'action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId(),
'name' => $this->oWorkflow->getName(),
);
$this->oPage->addPortlet(new WorkflowNavigationPortlet(_kt('Workflow'), $this->oWorkflow));
}
return true;
}
// helper function to construct the set of workflow information
function buildWorkflowInfo($oWorkflow) {
if ($this->aWorkflowInfo != null) { return $this->aWorkflowInfo; }
$aInfo = array();
$aInfo['workflow'] = $oWorkflow;
// roles
$aRoles = Role::getList();
$aKeyRoles = array();
foreach ($aRoles as $oRole) { $aKeyRoles[$oRole->getId()] = $oRole; }
$aInfo['roles'] = $aKeyRoles;
// groups
$aGroups = Group::getList();
$aKeyGroups = array();
foreach ($aGroups as $oGroup) { $aKeyGroups[$oGroup->getId()] = $oGroup; }
$aInfo['groups'] = $aKeyGroups;
// states.
$aStates = KTWorkflowState::getByWorkflow($oWorkflow);
$aKeyStates = array();
foreach ($aStates as $oState) { $aKeyStates[$oState->getId()] = $oState; }
$aInfo['states'] = $aKeyStates;
// transitions
$aTransitions = KTWorkflowTransition::getByWorkflow($oWorkflow);
$aKeyTransitions = array();
foreach ($aTransitions as $oTransition) { $aKeyTransitions[$oTransition->getId()] = $oTransition; }
$aInfo['transitions'] = $aKeyTransitions;
// permissions
$aPermissions = KTPermission::getList();
$aKeyPermissions = array();
foreach ($aPermissions as $oPermission) { $aKeyPermissions[$oPermission->getId()] = $oPermission; }
$aInfo['permissions'] = $aKeyPermissions;
// actions
$aInfo['actions'] = KTDocumentActionUtil::getAllDocumentActions();
$aKeyActions = array();
foreach ($aInfo['actions'] as $oAction) { $aKeyActions[$oAction->getName()] = $oAction; }
$aInfo['actions_by_name'] = $aKeyActions;
$aInfo['controlled_actions'] = KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow);
/*
* now we need to do the crossmappings.
*/
$aActionsByState = array();
foreach ($aInfo['states'] as $oState) {
$aActionsByState[$oState->getId()] = KTWorkflowUtil::getEnabledActionsForState($oState);;
}
$aInfo['actions_by_state'] = $aActionsByState;
// FIXME handle notified users and groups
$aTransitionsFromState = array();
foreach ($aInfo['states'] as $oState) {
$aTransitionsFromState[$oState->getId()] = KTWorkflowUtil::getTransitionsFrom($oState);
}
$aInfo['transitions_from_state'] = $aTransitionsFromState;
$aTransitionsToState = array();
foreach ($aInfo['states'] as $oState) {
$aTransitionsToState[$oState->getId()] = KTWorkflowTransition::getByTargetState($oState);
}
$aInfo['transitions_to_state'] = $aTransitionsToState;
$aPerms = KTPermission::getList();
$aKeyPerms = array();
foreach ($aPerms as $oPerm) { $aKeyPerms[$oPerm->getName()] = $oPerm; }
$aInfo['permissions'] = $aKeyPerms;
// temporarily create a debug mapping.
$aPermissionsByState = array();
foreach ($aInfo['states'] as $oState) {
$aPerms = KTWorkflowStatePermissionAssignment::getByState($oState->getId());
$aPermsAssigned = array();
foreach ($aPerms as $oPermAlloc) {
$oPerm = KTPermission::get($oPermAlloc->getPermissionId());
$aPermsAssigned[$oPermAlloc->getId()] = $oPerm->getName();
}
$aPermissionsByState[$oState->getId()] = $aPermsAssigned;
}
$aInfo['permissions_by_state'] = $aPermissionsByState;
// finally, check if any documents are associated with this workflow,
// and set the "delete" toggle.
$sQuery = 'SELECT document_id FROM ' . KTUtil::getTableName('document_metadata_version');
$sQuery .= ' WHERE workflow_id = ? ';
$aParams = array($oWorkflow->getId());
$aDocList = DBUtil::getResultArray(array($sQuery, $aParams));
$aInfo['can_delete'] = (empty($aDocList));
$this->aWorkflowInfo = $aInfo;
return $aInfo;
}
function getPermissionAssignmentsForState($oState) {
$aAllocs = array();
foreach ($this->aWorkflowInfo['permissions_by_state'][$oState->getId()] as $iAllocId => $sPermName) {
$oAlloc = KTWorkflowStatePermissionAssignment::get($iAllocId);
$aAllocs[$sPermName] = $oAlloc->getAllowed();
}
$this->aWorkflowInfo['permission_allocations_for_state'] = array();
$this->aWorkflowInfo['permission_allocations_for_state'][$oState->getId()] = $aAllocs;
return $aAllocs;
}
function getRoleHasPermissionInState($oRole, $sPermName, $oState) {
$perms = $this->aWorkflowInfo['permission_allocations_for_state'][$oState->getId()];
if (is_null($perms)) { return false; }
$aAllowed = $perms[$sPermName];
if (is_null($aAllowed['role'])) { return false; }
$aRoles = $aAllowed['role'];
if (array_search($oRole->getId(), $aRoles) === false) { return false; }
else { return true; }
}
function getGroupHasPermissionInState($oGroup, $sPermName, $oState) {
$perms = $this->aWorkflowInfo['permission_allocations_for_state'][$oState->getId()];
if (is_null($perms)) { return false; }
$aAllowed = $perms[$sPermName];
if (is_null($aAllowed['group'])) { return false; }
$aGroups = $aAllowed['group'];
if (array_search($oGroup->getId(), $aGroups) === false) { return false; }
else { return true; }
}
function getActionStringForState($oState) {
$aInfo = $this->aWorkflowInfo;
// no controlled actions => all available
if (empty($aInfo['controlled_actions'])) { return _kt('All actions available.'); }
$aAlways = array();
/*
foreach ($aInfo['actions'] as $iActionId => $aAction) {
if (!array_key_exists($iActionId, $aInfo['controlled_actions'])) {
$aAlways[$iActionId] = $aAction;
}
}
*/
$aNamedActions = array();
foreach ($aInfo['actions_by_state'][$oState->getId()] as $sName) {
$aNamedActions[] = $aInfo['actions_by_name'][$sName];
}
$aThese = kt_array_merge($aAlways, $aNamedActions);
// some controlled. we need to be careful here: list actions that _are always_ available
if (empty($aThese)) { return _kt('No actions available.'); }
// else
$aActions = array();
foreach ($aThese as $oAction) { $aActions[] = $oAction->getDisplayName(); }
return implode(', ', $aActions);
}
function getTransitionToStringForState($oState) {
$aInfo = $this->aWorkflowInfo;
//var_dump($aInfo['transitions_to_state'][$oState->getId()]);
if (($aInfo['workflow']->getStartStateId() != $oState->getId()) && (empty($aInfo['transitions_to_state'][$oState->getId()]))) {
return '' . _kt('This state is unreachable.') . '';
}
if ($aInfo['workflow']->getStartStateId() == $oState->getId() && (empty($aInfo['transitions_to_state'][$oState->getId()]))) {
return '' . _kt('Documents start in this state') . '';
}
$aT = array();
if ($aInfo['workflow']->getStartStateId() == $oState->getId()) {
$aT[] = '' . _kt('Documents start in this state') . '';
}
foreach ($aInfo['transitions_to_state'][$oState->getId()] as $aTransition) {
$sUrl = KTUtil::addQueryStringSelf(sprintf('action=editTransition&fWorkflowId=%d&fTransitionId=%d', $aInfo['workflow']->getId(), $aTransition->getId()));
$aT[] = sprintf('%s', $sUrl, $aTransition->getName());
}
return implode(', ',$aT);
}
function getNotificationStringForState($oState) {
$aAllowed = KTWorkflowUtil::getInformedForState($oState);
$aUsers = array();
$aGroups = array();
$aRoles = array();
foreach (KTUtil::arrayGet($aAllowed,'user',array()) as $iUserId) {
$oU = User::get($iUserId);
if (PEAR::isError($oU) || ($oU == false)) {
continue;
} else {
$aUsers[] = $oU->getName();
}
}
foreach (KTUtil::arrayGet($aAllowed,'group',array()) as $iGroupId) {
$oG = Group::get($iGroupId);
if (PEAR::isError($oG) || ($oG == false)) {
continue;
} else {
$aGroups[] = $oG->getName();
}
}
foreach (KTUtil::arrayGet($aAllowed,'role',array()) as $iRoleId) {
$oR = Role::get($iRoleId);
if (PEAR::isError($oR) || ($oR == false)) {
continue;
} else {
$aRoles[] = $oR->getName();
}
}
$sNotify = '';
if (!empty($aUsers)) {
$sNotify .= '' . _kt('Users:') . ' ';
$sNotify .= implode(', ', $aUsers);
}
if (!empty($aGroups)) {
if (!empty($sNotify)) { $sNotify .= ' — '; }
$sNotify .= '' . _kt('Groups:') . ' ';
$sNotify .= implode(', ', $aGroups);
}
if (!empty($aRoles)) {
if (!empty($sNotify)) { $sNotify .= ' — '; }
$sNotify .= '' . _kt('Roles:') . ' ';
$sNotify .= implode(', ', $aRoles);
}
if (empty($sNotify)) { $sNotify = _kt('No users to be notified.'); }
return $sNotify;
}
function transitionAvailable($oTransition, $oState) {
$aInfo = $this->aWorkflowInfo;
$val = false;
foreach ($aInfo['transitions_from_state'][$oState->getId()] as $oT) {
if ($oTransition->getId() == $oT->getId()) { $val = true; }
}
return $val;
}
function actionAvailable($sAction, $oState) {
$aInfo = $this->aWorkflowInfo;
$val = false;
foreach ($aInfo['actions_by_state'][$oState->getId()] as $oA) {
if ($sAction == $oA) { $val = true; }
}
return $val;
}
function getTransitionFromStringForState($oState) {
$aInfo = $this->aWorkflowInfo;
if (empty($aInfo['transitions_from_state'][$oState->getId()])) {
return '' . _kt('No transitions available') . '';
}
$aT = array();
foreach ($aInfo['transitions_from_state'][$oState->getId()] as $aTransition) {
$sUrl = KTUtil::addQueryStringSelf(sprintf('action=editTransition&fWorkflowId=%d&fTransitionId=%d', $aInfo['workflow']->getId(), $aTransition->getId()));
$aT[] = sprintf('%s', $sUrl, $aTransition->getName());
}
return implode(', ', $aT);
}
function getPermissionStringForState($oState) {
$aStr = '';
$aInfo = $this->aWorkflowInfo;
$aPerms = (array) $aInfo['permissions_by_state'][$oState->getId()];
if (empty($aPerms)) {
$aStr = _kt('No permissions are changed in this state.');
return $aStr;
}
$aPermNames = array();
foreach ($aPerms as $sPerm) {
$aPermNames[] = $aInfo['permissions'][$sPerm]->getHumanName();
}
$aStr = implode(', ', $aPermNames);
return $aStr;
}
// {{{ WORKFLOW HANDLING
// {{{ do_main
function do_main () {
$add_fields = array();
$add_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the workflow.'), 'fName', null, $this->oPage, true);
$oTemplating =& KTTemplating::getSingleton();
$oTemplate =& $oTemplating->loadTemplate('ktcore/workflow/listWorkflows');
$oTemplate->setData(array(
'context' => $this,
'aWorkflow' => KTWorkflow::getList(),
'add_fields' => $add_fields,
));
return $oTemplate;
}
// }}}
// {{{ do_editWorkflow
function do_editWorkflow() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aPermissions = $aInfo['permissions'];
$aStates = $aInfo['states'];
$edit_fields = array();
$edit_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the workflow.'), 'fName', $oWorkflow->getName(), $this->oPage, true);
$aOptions = array();
$vocab = array();
$vocab[0] = _kt('None - documents cannot use this workflow.');
foreach($aStates as $state) {
$vocab[$state->getId()] = $state->getName();
}
$aOptions['vocab'] = $vocab;
$edit_fields[] = new KTLookupWidget(_kt('Starting State'), _kt('When a document has this workflow applied to it, to which state should it initially be set. Note that workflows without a starting state cannot be applied to documents.'), 'fStartStateId', $oWorkflow->getStartStateId(), $this->oPage, false, null, null, $aOptions);
if (is_null($oWorkflow->getStartStateId())) {
$this->oPage->addInfo(_kt('This workflow is currently disabled. To enable it, please assign a starting state in the "Edit workflow properties" box.'));
}
/*
$add_state_fields = array();
$add_state_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the state.'), 'fName', null, $this->oPage, true);
*/
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
'aStates' => $aStates,
'aTransitions' => $aInfo['transitions'],
'aPermissions' => $aPermissions,
'aActions' => $aInfo['actions'],
'aActionsSelected' => $aInfo['controlled_actions'],
// info
'workflow_info' => $aInfo,
// subform
'edit_fields' => $edit_fields,
));
return $oTemplate;
}
// }}}
// {{{ do_saveWorkflow
function do_saveWorkflow() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aOptions = array(
'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
);
$sName = $this->oValidator->validateString($_REQUEST['fName'], $aOptions);
$oWorkflow->setName($sName);
$oWorkflow->setHumanName($sName);
if (!empty($_REQUEST['fStartStateId'])) {
$oWorkflow->setStartStateId($_REQUEST['fStartStateId']);
} else {
$oWorkflow->setStartStateId(null);
}
$res = $oWorkflow->update();
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
'message' => _kt('Error saving workflow'),
));
$this->successRedirectTo('editWorkflow', _kt('Changes saved'), 'fWorkflowId=' . $oWorkflow->getId());
exit(0);
}
// }}}
// {{{ do_newWorkflow
function do_newWorkflow() {
$aErrorOptions = array(
'redirect_to' => array('main'),
);
$sName = KTUtil::arrayGet($_REQUEST, 'fName');
$sName = $this->oValidator->validateEntityName('KTWorkflow', $sName, $aErrorOptions);
/* if(!PEAR::isError(KTWorkflow::getByName($sName))) {
$this->errorRedirectToMain(_kt("A state with that name already exists"));
}*/
$res = KTWorkflow::createFromArray(array(
'name' => $sName,
'humanname' => $sName,
));
$this->oValidator->notError($res, array(
'redirect_to' => array('main'),
'message' => _kt('Could not create workflow'),
));
$this->successRedirectTo('editWorkflow', _kt('Workflow created'), 'fWorkflowId=' . $res->getId());
exit(0);
}
// }}}
// {{{ do_disableWorkflow
function do_disableWorkflow() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$this->startTransaction();
$oWorkflow->setStartStateId(null);
$res = $oWorkflow->update();
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('main'),
'message' => _kt('Error saving workflow'),
));
$this->commitTransaction();
$this->successRedirectToMain(_kt('Changes saved'));
exit(0);
}
// }}}
function do_manageActions() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageActions');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aActionsOrig = $aInfo['actions'];
$aActions = array();
foreach ($aActionsOrig as $oAction) {
if ($oAction->getName() != 'ktcore.actions.document.displaydetails') {
$aActions[] = $oAction;
}
}
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
'aActions' => $aActions,
'aActionsSelected' => $aInfo['controlled_actions'],
// info
'workflow_info' => $aInfo,
));
return $oTemplate;
}
function do_manageStates() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageStates');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
// info
'workflow_info' => $aInfo,
));
return $oTemplate;
}
function do_createState() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/createState');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$add_fields = array();
$add_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the state.'), 'fName', null, $this->oPage, true);
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
// info
'workflow_info' => $aInfo,
'aActions' => KTDocumentActionUtil::getDocumentActionsByNames(KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow)),
'aActionsSelected' => KTWorkflowUtil::getEnabledActionsForState($oState),
'aGroups' => Group::getList(),
'aRoles' => Role::getList('id NOT IN (-3,-4)'),
'aUsers' => User::getList(),
// subform
'add_fields' => $add_fields,
));
return $oTemplate;
}
function do_manageTransitions() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageTransitions');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
// info
'workflow_info' => $aInfo,
// subform
'add_fields' => $add_transition_fields,
));
return $oTemplate;
}
function do_createTransition() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/createTransition');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aPermissions = $aInfo['permissions'];
$aGroups = $aInfo['groups'];
$aRoles = $aInfo['roles'];
$aConditions = KTSavedSearch::getConditions();
$add_transition_fields = array();
$add_transition_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the transition.'), 'fName', null, $this->oPage, true);
$aOptions = array();
$vocab = array();
foreach($aInfo['states'] as $state) {
$vocab[$state->getId()] = $state->getName();
}
$aOptions['vocab'] = $vocab;
$add_transition_fields[] = new KTLookupWidget(_kt('Destination State'), _kt('Once this transition is complete, which state should the document be in?'), 'fTargetStateId', $oWorkflow->getStartStateId(), $this->oPage, true, null, null, $aOptions);
/*
$aOptions = array();
$vocab = array();
$vocab[0] = _kt('None');
foreach($aInfo['permissions'] as $permission) {
$vocab[$permission->getId()] = $permission->getHumanName();
}
$aOptions['vocab'] = $vocab;
$add_transition_fields[] = new KTLookupWidget(_kt('Guard Permission.'), _kt('Which permission must the user have in order to follow this transition?'), 'fPermissionId', NULL, $this->oPage, true, null, null, $aOptions);
$aOptions = array();
$vocab = array();
$vocab[0] = _kt('None');
foreach($aGroups as $group) {
$vocab[$group->getId()] = $group->getName();
}
$aOptions['vocab'] = $vocab;
$add_transition_fields[] = new KTLookupWidget(_kt('Guard Group.'), _kt('Which group must the user belong to in order to follow this transition?'), 'fGroupId', NULL, $this->oPage, false, null, null, $aOptions);
$aOptions = array();
$vocab = array();
$vocab[0] = _kt('None');
foreach($aRoles as $role) {
$vocab[$role->getId()] = $role->getName();
}
$aOptions['vocab'] = $vocab;
$add_transition_fields[] = new KTLookupWidget(_kt('Guard Role.'), _kt('Which role must the user have in order to follow this transition?'), 'fRoleId', NULL, $this->oPage, false, null, null, $aOptions);
if (!empty($aConditions)) {
$aOptions = array();
$vocab = array();
$vocab[0] = _kt('None');
foreach($aConditions as $condition) {
$vocab[$condition->getId()] = $condition->getName();
}
$aOptions['vocab'] = $vocab;
$edit_fields[] = new KTLookupWidget(_kt('Guard Condition.'), _kt('Which condition (stored search) must be satisfied before the transition can take place?'), 'fConditionId', NULL, $this->oPage, false, null, null, $aOptions);
}
*/
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
// info
'workflow_info' => $aInfo,
// subform
'add_fields' => $add_transition_fields,
));
return $oTemplate;
}
function do_setTransitionAvailability() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$transitionMap = (array) KTUtil::arrayGet($_REQUEST, 'fTransitionAvailability');
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$this->startTransaction();
foreach ($aInfo['states'] as $oState) {
$a = (array) $transitionMap[$oState->getId()];
$transitions = array();
foreach ($a as $tid => $on) { $transitions[] = $tid; }
$res = KTWorkflowUtil::saveTransitionsFrom($oState, $transitions);
if (PEAR::isError($res)) {
$this->errorRedirectTo('manageTransitions', _kt('Error updating transitions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
}
}
$this->commitTransaction();
$this->successRedirectTo('manageTransitions', _kt('Transition Availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
}
function do_updateActionAvailability() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$actionMap = (array) KTUtil::arrayGet($_REQUEST, 'fAvailableActions');
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$this->startTransaction();
foreach ($aInfo['states'] as $oState) {
$a = (array) $actionMap[$oState->getId()];
$actions = array_keys($a);
$res = KTWorkflowUtil::setEnabledActionsForState($oState, $actions);
if (PEAR::isError($res)) {
$this->errorRedirectTo('manageActions', _kt('Error updating actions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
}
}
$this->commitTransaction();
$this->successRedirectTo('manageActions', _kt('Action availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
}
// {{{ do_setWorkflowActions
function do_setWorkflowActions() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$res = KTWorkflowUtil::setControlledActionsForWorkflow($oWorkflow, $_REQUEST['fActions']);
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
'message' => _kt('Error saving workflow controlled actions'),
));
$this->successRedirectTo('manageActions', _kt('Controlled actions changed.'), 'fWorkflowId=' . $oWorkflow->getId());
exit(0);
}
// }}}
// }}}
// {{{ STATE HANDLING
//
// {{{ do_newState
function do_newState() {
$iWorkflowId = (int) $_REQUEST['fWorkflowId'];
$aErrorOptions = array(
'redirect_to' => array('editWorkflow', sprintf('fWorkflowId=%d', $iWorkflowId)),
);
$oWorkflow =& $this->oValidator->validateWorkflow($iWorkflowId);
// validate name
$sName = $this->oValidator->validateString($_REQUEST['fName'], $aErrorOptions);
// check there are no other states by that name in this workflow
$aStates = KTWorkflowState::getList(sprintf("workflow_id = %d and name = '%s'", $iWorkflowId, $sName));
if(count($aStates)) {
$this->errorRedirectTo(implode('&', $aErrorOptions['redirect_to']), _kt("A state by that name already exists"));
}
$oState = KTWorkflowState::createFromArray(array(
'workflowid' => $oWorkflow->getId(),
'name' => $sName,
'humanname' => $sName,
));
$this->oValidator->notError($oState, array(
'redirect_to' => array('createState', 'fWorkflowId=' . $oWorkflow->getId()),
'message' => _kt('Could not create workflow state'),
));
$res = KTWorkflowUtil::setEnabledActionsForState($oState, $_REQUEST['fActions']);
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editState', 'fWorkflowId=' . $oWorkflow->getId(), '&fStateId=' . $oState->getId()),
'message' => _kt('Error saving state enabled actions'),
));
$this->successRedirectTo('editState', _kt('Workflow state created'), 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId());
exit(0);
}
// }}}
// {{{ do_editState
function do_editState() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editState');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aTransitionsTo =& KTWorkflowTransition::getByTargetState($oState);
$aTransitionIdsTo = array();
foreach ($aTransitionsTo as $oTransition) {
$aTransitionIdsTo[] = $oTransition->getId();
}
$aAllTransitions =& KTWorkflowTransition::getByWorkflow($oWorkflow);
$aTransitions = array();
foreach ($aAllTransitions as $oTransition) {
if (!in_array($oTransition->getId(), $aTransitionIdsTo)) {
$aTransitions[] = $oTransition;
}
}
$aTransitionsSelected = KTWorkflowUtil::getTransitionsFrom($oState, array('ids' => true));
$this->oPage->setBreadcrumbDetails(_kt('State') . ': ' . $oState->getName());
$aInformed = KTWorkflowUtil::getInformedForState($oState);
$editForm = array();
$editForm[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for this state. This is shown on the "Browse" page, as well as on the user\'s workflow page.'), 'fName', $oState->getName(), $this->oPage, true);
$this->getPermissionAssignmentsForState($oState);
$aActionOrig = KTDocumentActionUtil::getDocumentActionsByNames(KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow));
$aActions = array();
foreach ($aActionOrig as $k => $oAction) {
if ($oAction->getName() == 'ktcore.actions.document.displaydetails') {
continue;
}
$aActions[] = $oAction;
}
$oTemplate->setData(array(
'context' => $this,
'oWorkflow' => $oWorkflow,
'oState' => $oState,
'oNotifyRole' => $oRole,
'aTransitionsTo' => $aTransitionsTo,
'aTransitions' => $aTransitions,
'aTransitionsSelected' => $aTransitionsSelected,
'aActions' => $aActions,
'aActionsSelected' => KTWorkflowUtil::getEnabledActionsForState($oState),
'aGroups' => Group::getList(),
'aRoles' => Role::getList('id NOT IN (-3,-4)'),
'aUsers' => User::getList(),
'aInformed' => $aInformed,
'editForm' => $editForm,
'permissions' => $aInfo['permissions'],
'state_permissions' => $aInfo['permissions_by_state'][$oState->getId()],
));
return $oTemplate;
}
// }}}
// {{{ do_saveState
function do_saveState() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$oState->setName($_REQUEST['fName']);
$oState->setHumanName($_REQUEST['fName']);
$res = $oState->update();
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editState', 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId()),
'message' => _kt('Error saving state'),
));
$this->successRedirectTo('editState', _kt('Changes saved'), 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId());
exit(0);
}
// }}}
function do_deleteState() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
if (!$aInfo['can_delete']) { $this->errorRedirectTo('manageStates', _kt('May not delete items from an active workflow'), 'fWorkflowId=' . $oWorkflow->getId()); }
$this->startTransaction();
// clearing for integrity
// transitions starting from that state.
$sTable = KTUtil::getTableName('workflow_state_transitions');
$aQuery = array(
"DELETE FROM $sTable WHERE state_id = ?",
array($oState->getId()),
);
$res = DBUtil::runQuery($aQuery);
if (PEAR::isError($res)) { $this->errorRedirectTo('manageStates', _kt('Unable to clear references to item'), 'fWorkflowId=' . $oWorkflow->getId()); }
// transitions ending in that state
$aTransitionNames = array();
$aTransitionsToDelete = KTWorkflowTransition::getList('target_state_id = ' . $oState->getId());
foreach ($aTransitionsToDelete as $oTransition) {
$sTable = KTUtil::getTableName('workflow_state_transitions');
$aQuery = array(
"DELETE FROM $sTable WHERE transition_id = ?",
array($oTransition->getId()),
);
$res = DBUtil::runQuery($aQuery);
if (PEAR::isError($res)) { $this->errorRedirectTo('manageStates', _kt('Unable to remove transition references for: ') . $oTransition->getName(), 'fWorkflowId=' . $oWorkflow->getId()); }
$res = $oTransition->delete();
if (PEAR::isError($res)) { $this->errorRedirectTo('manageStates', _kt('Unable to remove transition: ') . $oTransition->getName(), 'fWorkflowId=' . $oWorkflow->getId()); }
$aTransitionNames[] = $oTransition->getName();
}
// if its the default state, change.
if ($oState->getId() == $oWorkflow->getStartStateId()) {
$oWorkflow->setStartStateId(null);
$res = $oWorkflow->update();
if (PEAR::isError($res)) { $this->errorRedirectTo('manageStates', _kt('Unable to change workflow starting state: ') . $res->getMessage(), 'fWorkflowId=' . $oWorkflow->getId()); }
}
// finally, delete the state
$res = $oState->delete(); // does this handle referential integrity?
if (PEAR::isError($res)) { $this->errorRedirectTo('manageStates', _kt('Unable to delete item: ') . $res->getMessage(), 'fWorkflowId=' . $oWorkflow->getId()); }
$this->commitTransaction();
if (!empty($aTransitionNames)) {
$sTransitionNames = implode (', ', $aTransitionNames);
$msg = sprintf(_kt('State deleted. Also deleted transitions ending in that state: %s'), $sTransitionNames);
} else {
$msg = _kt('State deleted.');
}
$this->successRedirectTo('manageStates', $msg, 'fWorkflowId=' . $oWorkflow->getId());
}
function do_setStatePermissions() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aExistingAlloc = $aInfo['permissions_by_state'][$oState->getId()];
$aPermissions = (array) KTUtil::arrayGet($_REQUEST, 'fPermissions');
$doWork = false;
$aEmptyAllowed = array();
$this->startTransaction();
foreach ($aPermissions as $sPermName) {
// lets not do too much work here.
$id = array_search($sPermName, $aExistingAlloc);
if ($id === false) {
$doWork = true; // going to need to regen the perm array
$oDescriptor = KTPermissionUtil::getOrCreateDescriptor($aEmptyAllowed);
$aOpts = array(
'StateId' => $oState->getId(),
'PermissionId' => $aInfo['permissions'][$sPermName]->getId(),
'DescriptorId' => $oDescriptor->getId(),
);
$res = KTWorkflowStatePermissionAssignment::createFromArray($aOpts);
if (PEAR::isError($res)) {
$this->errorRedirectTo('editState', _kt('Failed to create permission assignment: ') . $res->getMessage(),sprintf('fStateId=%d&fWorkflowId=%d',$oState->getId(),$oWorkflow->getId()));
}
} else {
// now, _don't_ delete later
unset($aExistingAlloc[$id]);
}
}
// now remove the _old_ (unset) assignments.
foreach ($aExistingAlloc as $iAllocId => $sPerm) {
$oAlloc = KTWorkflowStatePermissionAssignment::get($iAllocId);
$oAlloc->delete();
}
// FIXME implement:
// $this->_regenStatePermissionLookups($oState);
KTPermissionUtil::updatePermissionLookupForState($oState);
$this->successRedirectTo('editState', _kt('Permissions for workflow assigned'),sprintf('fStateId=%d&fWorkflowId=%d',$oState->getId(),$oWorkflow->getId()));
}
function do_assignStatePermissions() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
$aAlloc = $aInfo['permissions_by_state'][$oState->getId()];
$aPermissionAllowed = (array) KTUtil::arrayGet($_REQUEST, 'fPermissions');
$exitQS = sprintf('fStateId=%d&fWorkflowId=%d',$oState->getId(),$oWorkflow->getId());
$this->startTransaction();
// we now walk the alloc'd perms, and go.
foreach ($aAlloc as $iAllocId => $sPermName) {
$aAllowed = (array) $aPermissionAllowed[$sPermName]; // is already role, group, etc.
$oAlloc = KTWorkflowStatePermissionAssignment::get($iAllocId);
//var_dump($aAllowed);
$oDescriptor = KTPermissionUtil::getOrCreateDescriptor($aAllowed);
if (PEAR::isError($oDescriptor)) { $this->errorRedirectTo('editState', _kt('Failed to allocate as specified.'), $exitQS); }
$oAlloc->setDescriptorId($oDescriptor->getId());
$res = $oAlloc->update();
if (PEAR::isError($res)) { $this->errorRedirectTo('editState', _kt('Failed to allocate as specified.'), $exitQS); }
}
KTPermissionUtil::updatePermissionLookupForState($oState);
$this->successRedirectTo('editState', _kt('Permissions Allocated.'), $exitQS);
}
// {{{ do_saveTransitions
function do_saveTransitions() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$res = KTWorkflowUtil::saveTransitionsFrom($oState, $_REQUEST['fTransitionIds']);
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editState', 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId()),
'message' => _kt('Error saving transitions'),
));
$this->successRedirectTo('editState', _kt('Changes saved'), 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId());
exit(0);
}
// }}}
function do_deleteTransition() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& KTWorkflowTransition::get($_REQUEST['fTransitionId']);
if (PEAR::isError($oTransition)) {
$this->errorRedirectTo('manageTransitions', _kt('Invalid transition'),'fWorkflowId=' . $oWorkflow->getId());
}
$aInfo = $this->buildWorkflowInfo($oWorkflow);
if (!$aInfo['can_delete']) { $this->errorRedirectTo('manageTransitions', _kt('May not delete items from an active workflow'), 'fWorkflowId=' . $oWorkflow->getId()); }
$this->startTransaction();
$sTable = KTUtil::getTableName('workflow_state_transitions');
$aQuery = array(
"DELETE FROM $sTable WHERE transition_id = ?",
array($oTransition->getId()),
);
$res = DBUtil::runQuery($aQuery);
if (PEAR::isError($res)) { $this->errorRedirectTo('manageTransitions', _kt('Unable to remove transition references for: ') . $oTransition->getName(), 'fWorkflowId=' . $oWorkflow->getId()); }
$res = $oTransition->delete(); // does this handle referential integrity?
if (PEAR::isError($res)) { $this->errorRedirectTo('manageTransitions', _kt('Unable to delete item'), 'fWorkflowId=' . $oWorkflow->getId()); }
$this->commitTransaction();
$this->successRedirectTo('manageTransitions', _kt('Transition deleted.'), 'fWorkflowId=' . $oWorkflow->getId());
}
// {{{ do_setStateActions
function do_setStateActions() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$res = KTWorkflowUtil::setEnabledActionsForState($oState, $_REQUEST['fActions']);
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editState', 'fWorkflowId=' . $oWorkflow->getId(), '&fStateId=' . $oState->getId()),
'message' => _kt('Error saving state enabled actions'),
));
$this->successRedirectTo('manageActions', _kt('Controlled Actions changed.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId());
exit(0);
}
// }}}
// {{{ do_saveInform
function do_saveInform() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$sTargetAction = 'editState';
$sTargetParams = 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId();
$aNotification = (array) KTUtil::arrayGet($_REQUEST, 'fNotification');
if (empty($aNotification['role'])) {
$aNotification['role'] = array();
}
if (!is_array($aNotification['role'])) {
$this->errorRedirectTo($sTargetAction, _kt('Invalid roles specified'), $sTargetParams);
}
if (empty($aNotification['group'])) {
$aNotification['group'] = array();
}
if (!is_array($aNotification['group'])) {
$this->errorRedirectTo($sTargetAction, _kt('Invalid groups specified'), $sTargetParams);
}
$aNotification['user'] = array(); // force override
$res = KTWorkflowUtil::setInformedForState($oState, $aNotification);
if (PEAR::isError($res)) {
$this->errorRedirectTo($sTargetAction, sprintf(_kt('Failed to update the notification lists: %s'),$res->getMessage()), $sTargetParams);
}
$this->successRedirectTo($sTargetAction, _kt('Changes saved'), $sTargetParams);
}
// }}}
// }}}
// {{{ TRANSITION HANDLING
//
// {{{ do_newTransition
function do_newTransition() {
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fTargetStateId']);
$aInfo = $this->buildWorkflowInfo($oWorkflow);
// setup error options for later
$aErrorOptions = array(
'redirect_to' => array('editWorkflow', sprintf('fWorkflowId=%d', $oWorkflow->getId())),
);
$iPermissionId = KTUtil::arrayGet($_REQUEST, 'fPermissionId');
$iGroupId = KTUtil::arrayGet($_REQUEST, 'fGroupId');
$iRoleId = KTUtil::arrayGet($_REQUEST, 'fRoleId');
$iConditionId = KTUtil::arrayGet($_REQUEST, 'fConditionId', null);
// validate name
$sName = $this->oValidator->validateString(KTUtil::arrayGet($_REQUEST, 'fName'), $aErrorOptions);
// check there are no other transitions by that name in this workflow
$aTransitions = KTWorkflowTransition::getList(sprintf("workflow_id = %d and name = '%s'", $oWorkflow->getId(), $sName));
if(count($aTransitions)) {
$this->errorRedirectTo(implode('&', $aErrorOptions['redirect_to']), _kt("A transition by that name already exists"));
}
// validate permissions, roles, and group
if ($iPermissionId) {
$this->oValidator->validatePermission($_REQUEST['fPermissionId']);
}
if ($iGroupId) {
$this->oValidator->validateGroup($_REQUEST['fGroupId']);
}
if ($iRoleId) {
$this->oValidator->validateRole($_REQUEST['fRoleId']);
}
if ($iConditionId) {
$this->oValidator->validateCondition($_REQUEST['fConditionId']);
}
$res = KTWorkflowTransition::createFromArray(array(
'workflowid' => $oWorkflow->getId(),
'name' => $_REQUEST['fName'],
'humanname' => $_REQUEST['fName'],
'targetstateid' => $oState->getId(),
'guardpermissionid' => $iPermissionId,
'guardgroupid' => $iGroupId,
'guardroleid' => $iRoleId,
));
$this->oValidator->notError($res, array(
'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
'message' => _kt('Could not create workflow transition'),
));
// now attach it to the appropriate states.
$aStateId = (array) KTUtil::arrayGet($_REQUEST, 'fStatesAvailableIn');
$aStateId = array_keys($aStateId);
$newTransition = $res;
foreach ($aStateId as $iStateId) {
if ($iStateId == ($newTransition->getTargetStateId())) { continue; }
$oState = $aInfo['states'][$iStateId];
$aTransitions = KTWorkflowTransition::getBySourceState($oState);
$aTransitions[] = $newTransition;
$aTransitionIds = array();
foreach ($aTransitions as $oTransition) {
$aTransitionIds[] = $oTransition->getId();
}
$res = KTWorkflowUtil::saveTransitionsFrom($oState, $aTransitionIds);
if (PEAR::isError($res)) {
$this->errorRedirectTo('manageTransitions',sprintf(_kt('Unable to assign new transition to state %s'),$oState->getName()), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
}
}
$this->successRedirectTo('manageTransitions', _kt('Workflow transition created'), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
exit(0);
}
// }}}
// {{{ do_editTransition
function do_editTransition() {
$oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editTransition');
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$aStates = KTWorkflowState::getByWorkflow($oWorkflow);
$aPermissions = KTPermission::getList();
$aGroups = Group::getList();
$aRoles = Role::getList();
$aConditions = KTSavedSearch::getConditions();
$edit_fields = array();
$edit_fields[] = new KTStringWidget(_kt('Name'), _kt('A human-readable name for the state.'), 'fName', $oTransition->getName(), $this->oPage, true);
$aOptions = array();
$vocab = array();
foreach($aStates as $state) {
$vocab[$state->getId()] = $state->getName();
}
$aOptions['vocab'] = $vocab;
$edit_fields[] = new KTLookupWidget(_kt('Destination State'), _kt('Once this transition is complete, which state should the document be in?'), 'fTargetStateId', $oTransition->getTargetStateId(), $this->oPage, true, null, null, $aOptions);
// triggers
$add_trigger_fields = array();
$vocab = array();
$vocab[0] = _kt('-- Please select a trigger --');
$oTriggerSingleton =& KTWorkflowTriggerRegistry::getSingleton();
$aTriggerList = $oTriggerSingleton->listWorkflowTriggers(); // only want registered triggers - no other kind exists.
foreach ($aTriggerList as $ns => $aTriggerInfo) {
$aInfo = $aTriggerInfo; // i am lazy.
//var_dump($aInfo);
$actions = array();
if ($aInfo['guard']) {
$actions[] = _kt('Guard');
}
if ($aInfo['action']) {
$actions[] = _kt('Action');
}
$sActStr = implode(', ', $actions);
$vocab[$ns] = sprintf(_kt("%s (%s)"), $aInfo['name'], $sActStr);
}
$aOptions['vocab'] = $vocab;
$add_trigger_fields[] = new KTLookupWidget(_kt('Trigger'), _kt('Select the trigger to add to this transition. Each trigger indicates whether it controls who can see this transition, what occurs when the transition is performed, or both.'), 'fTriggerId', '0', $this->oPage, true, null, null, $aOptions);
$aOptions = array();
// attached triggers.
$aGuardTriggers = KTWorkflowUtil::getGuardTriggersForTransition($oTransition);
$aActionTriggers = KTWorkflowUtil::getActionTriggersForTransition($oTransition);
$this->aBreadcrumbs[] = array(
'url' => $_SERVER['PHP_SELF'],
'query' => 'action=editTransition&fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId(),
'name' => $oTransition->getName(),
);
$oTemplate->setData(array(
'oWorkflow' => $oWorkflow,
'oTransition' => $oTransition,
'aStates' => $aStates,
'aPermissions' => $aPermissions,
'aGroups' => $aGroups,
'aRoles' => $aRoles,
'aConditions' => $aConditions,
'aGuardTriggers' => $aGuardTriggers,
'aActionTriggers' => $aActionTriggers,
// fields
'add_trigger_fields' => $add_trigger_fields,
'edit_fields' => $edit_fields,
));
return $oTemplate;
}
// }}}
// {{{ do_saveTransition
function do_saveTransition() {
$aRequest = $this->oValidator->validateDict($_REQUEST, array(
'fWorkflowId' => array('type' => 'workflow'),
'fTransitionId' => array('type' => 'workflowtransition'),
));
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fTargetStateId']);
$iPermissionId = KTUtil::arrayGet($_REQUEST, 'fPermissionId', null);
$iGroupId = KTUtil::arrayGet($_REQUEST, 'fGroupId', null);
$iRoleId = KTUtil::arrayGet($_REQUEST, 'fRoleId', null);
$iConditionId = KTUtil::arrayGet($_REQUEST, 'fConditionId', null);
if ($iPermissionId) {
$this->oValidator->validatePermission($_REQUEST['fPermissionId']);
}
if ($iGroupId) {
$this->oValidator->validateGroup($_REQUEST['fGroupId']);
}
if ($iRoleId) {
$this->oValidator->validateRole($_REQUEST['fRoleId']);
}
if ($iConditionId) {
$this->oValidator->validateCondition($_REQUEST['fConditionId']);
}
$oTransition->updateFromArray(array(
'workflowid' => $oWorkflow->getId(),
'name' => $_REQUEST['fName'],
'humanname' => $_REQUEST['fName'],
'targetstateid' => $oState->getId(),
'guardpermissionid' => $iPermissionId,
'guardgroupid' => $iGroupId,
'guardroleid' => $iRoleId,
'guardconditionid' => $iConditionId,
));
$res = $oTransition->update();
$this->oValidator->notErrorFalse($res, array(
'redirect_to' => array('editTransition', 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId()),
'message' => _kt('Error saving transition'),
));
// also grab the list of transitions for the dest state, and remove this one if application
$aDestTransitions = KTWorkflowUtil::getTransitionsFrom($oState, array('ids' => true));
$bClean = true;
$aNewTransitions = array();
foreach ($aDestTransitions as $iOldTransitionId) {
if ($oTransition->getId() == $iOldTransitionId) {
$bClean = false;
} else {
$aNewTransitions[] = $iOldTransitionId;
}
}
if (!$bClean) {
KTWorkflowUtil::saveTransitionsFrom($oState, $aNewTransitions);
}
$this->successRedirectTo('editTransition', _kt('Changes saved'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
// }}}
function do_addTrigger() {
$aRequest = $this->oValidator->validateDict($_REQUEST, array(
'fWorkflowId' => array('type' => 'workflow'),
'fTransitionId' => array('type' => 'workflowtransition'),
));
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
// grab the transition ns from the request.
$KTWFTriggerReg =& KTWorkflowTriggerRegistry::getSingleton();
$this->startTransaction();
$oTrigger = $KTWFTriggerReg->getWorkflowTrigger(KTUtil::arrayGet($_REQUEST, 'fTriggerId'));
if (PEAR::isError($oTrigger)) {
$this->errorRedirectTo('editTransition', _kt('Unable to add trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$oTriggerConfig = KTWorkflowTriggerInstance::createFromArray(array(
'transitionid' => KTUtil::getId($oTransition),
'namespace' => KTUtil::arrayGet($_REQUEST, 'fTriggerId'),
'config' => array(),
));
if (PEAR::isError($oTriggerConfig)) {
$this->errorRedirectTo('editTransition', _kt('Unable to add trigger.' . $oTriggerConfig->getMessage()), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$this->successRedirectTo('editTransition', _kt('Trigger added.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
function do_editTrigger() {
$this->oPage->setBreadcrumbDetails(_kt('editing trigger'));
$aRequest = $this->oValidator->validateDict($_REQUEST, array(
'fWorkflowId' => array('type' => 'workflow'),
'fTransitionId' => array('type' => 'workflowtransition'),
));
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$oTriggerInstance =& KTWorkflowTriggerInstance::get($_REQUEST['fTriggerInstanceId']);
if (PEAR::isError($oTriggerInstance)) {
$this->errorRedirectTo('editTransition', _kt('Unable to load trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
// grab the transition ns from the request.
$KTWFTriggerReg =& KTWorkflowTriggerRegistry::getSingleton();
$this->startTransaction();
$oTrigger = $KTWFTriggerReg->getWorkflowTrigger($oTriggerInstance->getNamespace());
if (PEAR::isError($oTrigger)) {
$this->errorRedirectTo('editTransition', _kt('Unable to add trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$oTrigger->loadConfig($oTriggerInstance);
// simplify our 'config' stuff.
$args = array();
$args['fWorkflowId'] = $_REQUEST['fWorkflowId'];
$args['fTriggerInstanceId'] = $_REQUEST['fTriggerInstanceId'];
$args['fTransitionId'] = $_REQUEST['fTransitionId'];
$args['action'] = 'saveTrigger';
return $oTrigger->displayConfiguration($args);
}
// }}}
function do_saveTrigger() {
$this->oPage->setBreadcrumbDetails(_kt('editing trigger'));
$aRequest = $this->oValidator->validateDict($_REQUEST, array(
'fWorkflowId' => array('type' => 'workflow'),
'fTransitionId' => array('type' => 'workflowtransition'),
));
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$oTriggerInstance =& KTWorkflowTriggerInstance::get($_REQUEST['fTriggerInstanceId']);
if (PEAR::isError($oTriggerInstance)) {
$this->errorRedirectTo('editTransition', _kt('Unable to load trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
// grab the transition ns from the request.
$KTWFTriggerReg =& KTWorkflowTriggerRegistry::getSingleton();
$this->startTransaction();
$oTrigger = $KTWFTriggerReg->getWorkflowTrigger($oTriggerInstance->getNamespace());
if (PEAR::isError($oTrigger)) {
$this->errorRedirectTo('editTransition', _kt('Unable to load trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$oTrigger->loadConfig($oTriggerInstance);
$res = $oTrigger->saveConfiguration();
if (PEAR::isError($res)) {
$this->errorRedirectTo('editTransition', _kt('Unable to save trigger: ') . $res->getMessage(), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$this->successRedirectTo('editTransition', _kt('Trigger saved.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
function do_deleteTrigger() {
$aRequest = $this->oValidator->validateDict($_REQUEST, array(
'fWorkflowId' => array('type' => 'workflow'),
'fTransitionId' => array('type' => 'workflowtransition'),
));
$oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
$oTransition =& $this->oValidator->validateWorkflowTransition($_REQUEST['fTransitionId']);
$oTriggerInstance =& KTWorkflowTriggerInstance::get($_REQUEST['fTriggerInstanceId']);
if (PEAR::isError($oTriggerInstance)) {
$this->errorRedirectTo('editTransition', _kt('Unable to load trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
// grab the transition ns from the request.
$KTWFTriggerReg =& KTWorkflowTriggerRegistry::getSingleton();
$this->startTransaction();
$oTrigger = $KTWFTriggerReg->getWorkflowTrigger($oTriggerInstance->getNamespace());
if (PEAR::isError($oTrigger)) {
$this->errorRedirectTo('editTransition', _kt('Unable to load trigger.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$oTrigger->loadConfig($oTriggerInstance);
$res = $oTriggerInstance->delete();
if (PEAR::isError($res)) {
$this->errorRedirectTo('editTransition', _kt('Unable to delete trigger: ') . $res->getMessage(), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
$this->successRedirectTo('editTransition', _kt('Trigger deleted.'), 'fWorkflowId=' . $oWorkflow->getId() . '&fTransitionId=' . $oTransition->getId());
exit(0);
}
// }}}
}
?>