From dc4be67e96df79b2f6fa5512a9d7e5793ab4e15e Mon Sep 17 00:00:00 2001
From: Brad Shuttleworth
Date: Thu, 8 Jun 2006 14:26:58 +0000
Subject: [PATCH] Basic workflow triggers + UI.
---
lib/plugins/plugin.inc.php | 12 ++++++++++++
lib/workflow/workflowtrigger.inc.php | 21 +++++++++++++++++++++
lib/workflow/workflowtriggerinstance.inc.php | 1 +
lib/workflow/workflowutil.inc.php | 12 +++++++-----
plugins/ktcore/KTCorePlugin.php | 4 ++++
plugins/ktcore/KTDocumentActions.php | 14 +++++++-------
plugins/ktcore/admin/workflows.php | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
templates/ktcore/workflow/editTransition.smarty | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
templates/ktcore/workflowtriggers/permissions.smarty | 26 ++++++++++++++++++++++++++
9 files changed, 277 insertions(+), 44 deletions(-)
create mode 100644 templates/ktcore/workflowtriggers/permissions.smarty
diff --git a/lib/plugins/plugin.inc.php b/lib/plugins/plugin.inc.php
index 3167ec0..0f95342 100644
--- a/lib/plugins/plugin.inc.php
+++ b/lib/plugins/plugin.inc.php
@@ -51,6 +51,7 @@ class KTPlugin {
var $_ai18nLang = array();
var $_aLanguage = array();
var $_aHelpLanguage = array();
+ var $_aWFTriggers = array();
function KTPlugin($sFilename = null) {
$this->sFilename = $sFilename;
@@ -80,6 +81,11 @@ class KTPlugin {
$sWebPath = sprintf("%s/%s", $this->sNamespace, $sWebPath);
$this->_aPages[$sWebPath] = array($sWebPath, $sPageClassName, $sFilename, $this->sNamespace);
}
+
+ function registerWorkflowTrigger($sNamespace, $sTriggerClassName, $sFilename = null) {
+ $sFilename = $this->_fixFilename($sFilename);
+ $this->_aWFTriggers[$sNamespace] = array($sNamespace, $sTriggerClassName, $sFilename);
+ }
function getPagePath($sPath) {
$sExt = ".php";
@@ -191,6 +197,7 @@ class KTPlugin {
require_once(KT_LIB_DIR . "/dashboard/dashletregistry.inc.php");
require_once(KT_LIB_DIR . "/i18n/i18nregistry.inc.php");
require_once(KT_LIB_DIR . "/help/help.inc.php");
+ require_once(KT_LIB_DIR . "/workflow/workflowutil.inc.php");
$oPRegistry =& KTPortletRegistry::getSingleton();
$oTRegistry =& KTTriggerRegistry::getSingleton();
@@ -201,6 +208,7 @@ class KTPlugin {
$oDashletRegistry =& KTDashletRegistry::getSingleton();
$oi18nRegistry =& KTi18nRegistry::getSingleton();
$oKTHelpRegistry =& KTHelpRegistry::getSingleton();
+ $oWFTriggerRegistry =& KTWorkflowTriggerRegistry::getSingleton();
foreach ($this->_aPortlets as $k => $v) {
call_user_func_array(array(&$oPRegistry, 'registerPortlet'), $v);
@@ -249,6 +257,10 @@ class KTPlugin {
foreach ($this->_aHelpLanguage as $k => $v) {
call_user_func_array(array(&$oKTHelpRegistry, 'registerHelp'), $v);
}
+
+ foreach ($this->_aWFTriggers as $k => $v) {
+ call_user_func_array(array(&$oWFTriggerRegistry, 'registerWorkflowTrigger'), $v);
+ }
}
function setup() {
diff --git a/lib/workflow/workflowtrigger.inc.php b/lib/workflow/workflowtrigger.inc.php
index 8e3020c..a669719 100644
--- a/lib/workflow/workflowtrigger.inc.php
+++ b/lib/workflow/workflowtrigger.inc.php
@@ -50,6 +50,7 @@ class KTWorkflowTrigger {
function loadConfig($oTriggerInstance) {
$this->oTriggerInstance = $oTriggerInstance;
+ $this->aConfig = $oTriggerInstance->getConfig();
}
function isLoaded() { return (!is_null($this->oTriggerInstance)); }
@@ -64,6 +65,10 @@ class KTWorkflowTrigger {
);
}
+ function getName() { return $this->sFriendlyName; }
+ function getNamespace() { return $this->sNamespace; }
+ function getConfigId() { return $this->oTriggerInstance->getId(); }
+
// return true for transition allowed on doc, false for transition not allowed on doc.
function allowTransition($oDocument, $oUser) {
return true; // abstract base class
@@ -85,6 +90,22 @@ class KTWorkflowTrigger {
return true;
}
+ // display the configuration page for this plugin
+ // will be called -after- loadConfig, so it can prepopulate the options.
+ function displayConfiguration($args) {
+ return _kt('No configuration has been implemented for this plugin.');
+ }
+
+ // dispatched - again, after loadConfig, so it can set the config.
+ // throw an error to redispatch displayConfiguration, or return true to cause a db commit (probably).
+ function saveConfiguration() {
+ return true;
+ }
+
+ // give a brief, friendly description of what we are and what we do.
+ function getConfigDescription() {
+ return '';
+ }
}
?>
diff --git a/lib/workflow/workflowtriggerinstance.inc.php b/lib/workflow/workflowtriggerinstance.inc.php
index 41752dd..e1fdf79 100644
--- a/lib/workflow/workflowtriggerinstance.inc.php
+++ b/lib/workflow/workflowtriggerinstance.inc.php
@@ -59,6 +59,7 @@ class KTWorkflowTriggerInstance extends KTEntity {
function &get($iId) { return KTEntityUtil::get('KTWorkflowTriggerInstance', $iId); }
function &createFromArray($aOptions) {
$aOptions['configarraytext'] = serialize($aOptions['config']);
+ unset($aOptions['config']);
return KTEntityUtil::createFromArray('KTWorkflowTriggerInstance', $aOptions);
}
function &getList($sWhereClause = null) { return KTEntityUtil::getList2('KTWorkflowTriggerInstance', $sWhereClause); }
diff --git a/lib/workflow/workflowutil.inc.php b/lib/workflow/workflowutil.inc.php
index 38ef8b1..ad2872d 100644
--- a/lib/workflow/workflowutil.inc.php
+++ b/lib/workflow/workflowutil.inc.php
@@ -745,6 +745,10 @@ class KTWorkflowUtil {
class KTWorkflowTriggerRegistry {
var $triggers;
+ function KTWorkflowTriggerRegistry() {
+ $this->triggers = array();
+ }
+
// {{{ getSingleton
function &getSingleton () {
if (!KTUtil::arrayGet($GLOBALS['_KT_PLUGIN'], 'oKTWorkflowTriggerRegistry')) {
@@ -764,11 +768,9 @@ class KTWorkflowTriggerRegistry {
return PEAR::raiseError(sprintf(_kt("Unable to find workflow trigger: %s"), $sNamespace));
}
- if (file_exists($aInfo['path'])) {
- require_once($aInfo['path']);
- }
-
- return new $sClassname;
+ require_once($aInfo['path']);
+
+ return new $aInfo['class'];
}
// get a keyed list of workflow triggers
diff --git a/plugins/ktcore/KTCorePlugin.php b/plugins/ktcore/KTCorePlugin.php
index a27d8e9..ec39eb0 100644
--- a/plugins/ktcore/KTCorePlugin.php
+++ b/plugins/ktcore/KTCorePlugin.php
@@ -29,6 +29,7 @@
require_once(KT_LIB_DIR . '/plugins/pluginregistry.inc.php');
require_once(KT_LIB_DIR . '/plugins/plugin.inc.php');
+
class KTCorePlugin extends KTPlugin {
var $bAlwaysInclude = true;
var $sNamespace = "ktcore.plugin";
@@ -179,6 +180,9 @@ class KTCorePlugin extends KTPlugin {
'admin/manageCleanup.php', null);
// plugins
+
+ // workflow triggers
+ $this->registerWorkflowTrigger('ktcore.workflowtriggers.permissionguard', 'PermissionGuardTrigger', 'KTWorkflowTriggers.inc.php');
}
}
diff --git a/plugins/ktcore/KTDocumentActions.php b/plugins/ktcore/KTDocumentActions.php
index eba38b0..e58dd45 100644
--- a/plugins/ktcore/KTDocumentActions.php
+++ b/plugins/ktcore/KTDocumentActions.php
@@ -996,14 +996,14 @@ class KTDocumentWorkflowAction extends KTDocumentAction {
$oUser =& User::get($_SESSION['userID']);
$res = KTWorkflowUtil::performTransitionOnDocument($oTransition, $oDocument, $oUser, $sComments);
- if(!Permission::userHasDocumentReadPermission($oDocument)) {
- $this->commitTransaction();
+ if(!Permission::userHasDocumentReadPermission($oDocument)) {
+ $this->commitTransaction();
$_SESSION['KTInfoMessage'][] = _kt('Transition performed') . '. ' . _kt('You no longer have permission to view this document');
- controllerRedirect('browse', sprintf('fFolderId=%d', $oDocument->getFolderId()));
- } else {
- $this->successRedirectToMain(_kt('Transition performed'),
- array('fDocumentId' => $oDocument->getId()));
- }
+ controllerRedirect('browse', sprintf('fFolderId=%d', $oDocument->getFolderId()));
+ } else {
+ $this->successRedirectToMain(_kt('Transition performed'),
+ array('fDocumentId' => $oDocument->getId()));
+ }
}
}
// }}}
diff --git a/plugins/ktcore/admin/workflows.php b/plugins/ktcore/admin/workflows.php
index 01385b5..46eb8ae 100755
--- a/plugins/ktcore/admin/workflows.php
+++ b/plugins/ktcore/admin/workflows.php
@@ -1224,41 +1224,35 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
}
$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);
- $aOptions = array();
- $vocab = array();
- $vocab[0] = _kt('None');
- foreach($aPermissions as $permission) {
- $vocab[$permission->getId()] = $permission->getHumanName();
- }
- $aOptions['vocab'] = $vocab;
- $edit_fields[] = new KTLookupWidget(_kt('Guard Permission.'), _kt('Which permission must the user have in order to follow this transition?'), 'fPermissionId', $oTransition->getGuardPermissionId(), $this->oPage, true, null, null, $aOptions);
- $aOptions = array();
+
+ // triggers
+ $add_trigger_fields = array();
$vocab = array();
- $vocab[0] = _kt('None');
- foreach($aGroups as $group) {
- $vocab[$group->getId()] = $group->getName();
- }
+ $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;
- $edit_fields[] = new KTLookupWidget(_kt('Guard Group.'), _kt('Which group must the user belong to in order to follow this transition?'), 'fGroupId', $oTransition->getGuardGroupId(), $this->oPage, false, null, null, $aOptions);
+ $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();
- $vocab = array();
- $vocab[0] = _kt('None');
- foreach($aRoles as $role) {
- $vocab[$role->getId()] = $role->getName();
- }
- $aOptions['vocab'] = $vocab;
- $edit_fields[] = new KTLookupWidget(_kt('Guard Role.'), _kt('Which role must the user have in order to follow this transition?'), 'fRoleId', $oTransition->getGuardRoleId(), $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', $oTransition->getGuardConditionId(), $this->oPage, false, null, null, $aOptions);
- }
+
+ // attached triggers.
+ $aGuardTriggers = KTWorkflowUtil::getGuardTriggersForTransition($oTransition);
+ $aActionTriggers = KTWorkflowUtil::getActionTriggersForTransition($oTransition);
$this->aBreadcrumbs[] = array(
'url' => $_SERVER['PHP_SELF'],
@@ -1273,9 +1267,11 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
'aGroups' => $aGroups,
'aRoles' => $aRoles,
'aConditions' => $aConditions,
+ 'aGuardTriggers' => $aGuardTriggers,
+ 'aActionTriggers' => $aActionTriggers,
// fields
-
+ 'add_trigger_fields' => $add_trigger_fields,
'edit_fields' => $edit_fields,
));
return $oTemplate;
@@ -1343,6 +1339,115 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
}
// }}}
+ 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);
+ }
+
// }}}
}
diff --git a/templates/ktcore/workflow/editTransition.smarty b/templates/ktcore/workflow/editTransition.smarty
index 46dd3f8..c2e365a 100644
--- a/templates/ktcore/workflow/editTransition.smarty
+++ b/templates/ktcore/workflow/editTransition.smarty
@@ -25,3 +25,65 @@ requirement.{/i18n}
+
+
diff --git a/templates/ktcore/workflowtriggers/permissions.smarty b/templates/ktcore/workflowtriggers/permissions.smarty
new file mode 100644
index 0000000..6259952
--- /dev/null
+++ b/templates/ktcore/workflowtriggers/permissions.smarty
@@ -0,0 +1,26 @@
+{i18n}Guard permissions for Transition{/i18n}
+
+
\ No newline at end of file
--
libgit2 0.21.4