From 2e73f774fe6dddafd09791e362a06b774e2dda77 Mon Sep 17 00:00:00 2001
From: bshuttle
Date: Tue, 31 Jan 2006 15:11:59 +0000
Subject: [PATCH] Workflow can now generate notifications (tentative)
---
lib/dashboard/Notification.inc.php | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/roles/roleallocation.inc.php | 4 ++--
lib/workflow/workflowutil.inc.php | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
plugins/ktcore/admin/workflows.php | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
templates/ktcore/workflow/editState.smarty | 13 +++++++++----
templates/ktcore/workflow/workflow_notification.smarty | 10 ++++++++++
6 files changed, 272 insertions(+), 28 deletions(-)
create mode 100644 templates/ktcore/workflow/workflow_notification.smarty
diff --git a/lib/dashboard/Notification.inc.php b/lib/dashboard/Notification.inc.php
index b861066..48406a0 100644
--- a/lib/dashboard/Notification.inc.php
+++ b/lib/dashboard/Notification.inc.php
@@ -9,6 +9,10 @@ require_once(KT_LIB_DIR . '/users/User.inc');
require_once(KT_LIB_DIR . '/documentmanagement/Document.inc');
require_once(KT_LIB_DIR . '/foldermanagement/Folder.inc');
+require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php');
+
+require_once(KT_LIB_DIR . '/templating/templating.inc.php');
+
/**
* class Notification
*
@@ -71,6 +75,9 @@ class KTNotification extends KTEntity {
function render() {
$notificationRegistry =& KTNotificationRegistry::getSingleton();
$handler = $notificationRegistry->getHandler($this->sType);
+
+ if (is_null($handler)) { return null; }
+
return $handler->handleNotification($this);
}
@@ -313,4 +320,59 @@ class KTSubscriptionNotification extends KTNotificationHandler {
$notificationRegistry->registerNotificationHandler("ktcore/subscriptions","KTSubscriptionNotification");
+class KTWorkflowNotification extends KTNotificationHandler {
+
+ function & clearNotificationsForDocument($oDocument) {
+ $aNotifications = KTNotification::getList('data_int_1 = ' . $oDocument->getId());
+ foreach ($aNotifications as $oNotification) {
+ $oNotification->delete();
+ }
+
+ }
+
+ function & newNotificationForDocument($oDocument, $oUser, $oState, $oActor, $sComments) {
+ $aInfo = array();
+ $aInfo['sData1'] = $oState->getName();
+ $aInfo['sData2'] = $sComments;
+ $aInfo['iData1'] = $oDocument->getId();
+ $aInfo['iData2'] = $oActor->getId();
+ $aInfo['sType'] = 'ktcore/workflow';
+ $aInfo['dCreationDate'] = getCurrentDateTime();
+ $aInfo['iUserId'] = $oUser->getId();
+ $aInfo['sLabel'] = $oDocument->getName();
+
+ return KTNotification::createFromArray($aInfo);
+ }
+
+ function handleNotification($oKTNotification) {
+ $oTemplating =& KTTemplating::getSingleton();
+ $oTemplate =& $oTemplating->loadTemplate('ktcore/workflow/workflow_notification');
+ $oTemplate->setData(array(
+ 'context' => $this,
+ 'document_id' => $oKTNotification->getIntData1(),
+ 'state_name' => $oKTNotification->getStrData1(),
+ 'actor' => User::get($oKTNotification->getIntData2()),
+ 'document_name' => $oKTNotification->getLabel(),
+ 'notify_id' => $oKTNotification->getId(),
+ ));
+ return $oTemplate->render();
+ }
+
+ function resolveNotification($oKTNotification) {
+ $notify_action = KTUtil::arrayGet($_REQUEST, 'notify_action', null);
+ if ($notify_action == 'clear') {
+ $_SESSION['KTInfoMessage'][] = _('Workflow Notification cleared.');
+ $oKTNotification->delete();
+ exit(redirect(generateControllerLink('dashboard')));
+ }
+
+ $params = 'fDocumentId=' . $oKTNotification->getIntData1();
+ $url = generateControllerLink('viewDocument', $params);
+ $oKTNotification->delete(); // clear the alert.
+ exit(redirect($url));
+ }
+}
+
+$notificationRegistry->registerNotificationHandler("ktcore/workflow","KTWorkflowNotification");
+
?>
diff --git a/lib/roles/roleallocation.inc.php b/lib/roles/roleallocation.inc.php
index 57cbf38..07b82b5 100644
--- a/lib/roles/roleallocation.inc.php
+++ b/lib/roles/roleallocation.inc.php
@@ -121,7 +121,7 @@ class RoleAllocation extends KTEntity {
foreach ($aUsers as $iUserId) {
$oUser = User::get($iUserId);
if (!(PEAR::isError($oUser) || ($oUser == false))) {
- $aFullUsers[] = $oUser;
+ $aFullUsers[$iUserId] = $oUser;
}
}
@@ -144,7 +144,7 @@ class RoleAllocation extends KTEntity {
foreach ($aGroups as $iGroupId) {
$oGroup = Group::get($iGroupId);
if (!(PEAR::isError($oGroup) || ($oGroup == false))) {
- $aFullGroups[] = $oGroup;
+ $aFullGroups[$iGroupId] = $oGroup;
}
}
diff --git a/lib/workflow/workflowutil.inc.php b/lib/workflow/workflowutil.inc.php
index 88e3886..4e4fcfe 100644
--- a/lib/workflow/workflowutil.inc.php
+++ b/lib/workflow/workflowutil.inc.php
@@ -10,6 +10,13 @@ require_once(KT_LIB_DIR . '/documentmanagement/DocumentTransaction.inc');
require_once(KT_LIB_DIR . '/search/searchutil.inc.php');
require_once(KT_LIB_DIR . '/roles/roleallocation.inc.php');
+require_once(KT_LIB_DIR . '/groups/Group.inc');
+require_once(KT_LIB_DIR . '/users/User.inc');
+require_once(KT_LIB_DIR . '/roles/Role.inc');
+
+require_once(KT_LIB_DIR . '/dashboard/Notification.inc.php');
+
+
class KTWorkflowUtil {
// {{{ saveTransitionsFrom
/**
@@ -102,7 +109,16 @@ class KTWorkflowUtil {
'state_id' => $iStartStateId,
);
$sTable = KTUtil::getTableName('workflow_documents');
- return DBUtil::autoInsert($sTable, $aValues, $aOptions);
+ $res = DBUtil::autoInsert($sTable, $aValues, $aOptions);
+
+ // FIXME does this function as expected?
+ $oUser = User::get($_SESSION['userID']);
+
+ $oTargetState = KTWorkflowState::get($iStartStateId);
+ KTWorkflowUtil::informUsersForState($oTargetState,
+ KTWorkflowUtil::getInformedForState($oTargetState), $oDocument, $oUser, '');
+
+ return $res;
}
// }}}
@@ -142,6 +158,14 @@ class KTWorkflowUtil {
'state_id' => $iStartStateId,
);
$sTable = KTUtil::getTableName('workflow_documents');
+
+ $oUser = User::get($_SESSION['userID']);
+ $oTargetState = KTWorkflowState::get($iStartStateId);
+
+ KTWorkflowUtil::informUsersForState($oTargetState,
+ KTWorkflowUtil::getInformedForState($oTargetState), $oDocument, $oUser, '');
+
+
return DBUtil::autoInsert($sTable, $aValues, $aOptions);
}
// }}}
@@ -457,10 +481,103 @@ class KTWorkflowUtil {
$oDocumentTransaction = & new DocumentTransaction($oDocument, $sTransactionComments, 'ktcore.transactions.workflow_state_transition');
$oDocumentTransaction->create();
+ KTWorkflowUtil::informUsersForState($oTargetState, KTWorkflowUtil::getInformedForState($oTargetState), $oDocument, $oUser, $sComments);
+
return true;
}
// }}}
+ // {{{ informUsersForState
+ function informUsersForState($oState, $aInformed, $oDocument, $oUser, $sComments) {
+ // say no to duplicates.
+
+ KTWorkflowNotification::clearNotificationsForDocument($oDocument);
+
+ $aUsers = array();
+ $aGroups = array();
+ $aRoles = array();
+
+ foreach (KTUtil::arrayGet($aInformed,'user',array()) as $iUserId) {
+ $oU = User::get($iUserId);
+ if (PEAR::isError($oU) || ($oU == false)) {
+ continue;
+ } else {
+ $aUsers[$oU->getId()] = $oU();
+ }
+ }
+
+ foreach (KTUtil::arrayGet($aInformed,'group',array()) as $iGroupId) {
+ $oG = Group::get($iGroupId);
+ if (PEAR::isError($oG) || ($oG == false)) {
+ continue;
+ } else {
+ $aGroups[$oG->getId()] = $oG();
+ }
+ }
+
+ foreach (KTUtil::arrayGet($aInformed,'role',array()) as $iRoleId) {
+ $oR = Role::get($iRoleId);
+ if (PEAR::isError($oR) || ($oR == false)) {
+ continue;
+ } else {
+ $aRoles[] = $oR;
+ }
+ }
+
+
+
+ // FIXME extract this into a util - I see us using this again and again.
+ // start with roles ... roles _only_ ever contain groups.
+ foreach ($aRoles as $oRole) {
+ $oRoleAllocation = RoleAllocation::getAllocationsForFolderAndRole($oDocument->getFolderID(), $oRole->getId());
+ $aRoleUsers = $oRoleAllocation->getUsers();
+ $aRoleGroups = $oRoleAllocation->getGroups();
+
+ foreach ($aRoleUsers as $id => $oU) {
+ $aUsers[$id] = $oU;
+ }
+ foreach ($aRoleGroups as $id => $oGroup) {
+ $aGroups[$id] = $oGroup;
+ }
+ }
+
+
+
+ // we now have a (potentially overlapping) set of groups, which may
+ // have subgroups.
+ //
+ // what we need to do _now_ is build a canonical set of groups, and then
+ // generate the singular user-base.
+
+ $aGroupMembershipSet = GroupUtil::buildGroupArray();
+ $aAllIds = array_keys($aGroups);
+ foreach ($aGroups as $id => $oGroup) {
+ $aAllIds = array_merge($aGroupMembershipSet[$id], $aAllIds);
+ }
+
+ foreach ($aAllIds as $id) {
+ if (!array_key_exists($id, $aGroups)) {
+ $aGroups[$id] = Group::get($id);
+ }
+ }
+
+ // now, merge this (again) into the user-set.
+ foreach ($aGroups as $oGroup) {
+ $aNewUsers = $oGroup->getUsers();
+ foreach ($aNewUsers as $id => $oU) {
+ if (!array_key_exists($id, $aUsers)) {
+ $aUsers[$id] = $oU;
+ }
+ }
+ }
+
+ // and done.
+ foreach ($aUsers as $oU) {
+ KTWorkflowNotification::newNotificationForDocument($oDocument, $oU, $oState, $oUser, $sComments);
+ }
+ }
+ // }}}
+
// {{{ setInformedForState
/**
* Sets which users/groups/roles are to be informed when a state is
diff --git a/plugins/ktcore/admin/workflows.php b/plugins/ktcore/admin/workflows.php
index 00472af..a106277 100755
--- a/plugins/ktcore/admin/workflows.php
+++ b/plugins/ktcore/admin/workflows.php
@@ -20,6 +20,10 @@ require_once(KT_LIB_DIR . '/actions/documentaction.inc.php');
require_once(KT_LIB_DIR . '/widgets/portlet.inc.php');
+require_once(KT_LIB_DIR . '/users/User.inc');
+require_once(KT_LIB_DIR . '/groups/Group.inc');
+require_once(KT_LIB_DIR . '/roles/Role.inc');
+
class WorkflowNavigationPortlet extends KTPortlet {
var $oWorkflow;
@@ -202,7 +206,58 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
}
function getNotificationStringForState($oState) {
- return _('No roles and groups notified.');
+ $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 .= '' . _('Users:') . '';
+ $sNotify .= implode(', ', $aUsers);
+ }
+
+ if (!empty($aGroups)) {
+ $sNotify .= '' . _('Groups:') . '';
+ $sNotify .= implode(', ', $aGroups);
+ }
+
+ if (!empty($aRoles)) {
+ $sNotify .= '' . _('Roles:') . '';
+ $sNotify .= implode(', ', $aRoles);
+ }
+
+ if (empty($sNotify)) { $sNotify = _('No users to be notified.'); }
+
+ return $sNotify;
}
function transitionAvailable($oTransition, $oState) {
@@ -735,33 +790,28 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
$oState =& $this->oValidator->validateWorkflowState($_REQUEST['fStateId']);
$sTargetAction = 'editState';
$sTargetParams = 'fWorkflowId=' . $oWorkflow->getId() . '&fStateId=' . $oState->getId();
- $aRoleIds = KTUtil::arrayGet($_REQUEST, 'fRoleIds');
- if (empty($aRoleIds)) {
- $aRoleIds = array();
+ $aNotification = (array) KTUtil::arrayGet($_REQUEST, 'fNotification');
+
+ if (empty($aNotification['role'])) {
+ $aNotification['role'] = array();
}
- if (!is_array($aRoleIds)) {
+ if (!is_array($aNotification['role'])) {
$this->errorRedirectTo($sTargetAction, _('Invalid roles specified'), $sTargetParams);
}
- $aGroupIds = KTUtil::arrayGet($_REQUEST, 'fGroupIds');
- if (empty($aGroupIds)) {
- $aGroupIds = array();
+
+ if (empty($aNotification['group'])) {
+ $aNotification['group'] = array();
}
- if (!is_array($aGroupIds)) {
+ if (!is_array($aNotification['group'])) {
$this->errorRedirectTo($sTargetAction, _('Invalid groups specified'), $sTargetParams);
}
- $aUserIds = KTUtil::arrayGet($_REQUEST, 'fUserIds');
- if (empty($aUserIds)) {
- $aUserIds = array();
- }
- if (!is_array($aUserIds)) {
- $this->errorRedirectTo($sTargetAction, _('Invalid users specified'), $sTargetParams);
+
+ $aNotification['user'] = array(); // force override
+
+ $res = KTWorkflowUtil::setInformedForState($oState, $aNotification);
+ if (PEAR::isError($res)) {
+ $this->errorRedirectTo($sTargetAction, sprintf(_('Failed to update the notification lists: %s'),$res->getMessage()), $sTargetParams);
}
- $aAllowed = array(
- 'role' => $aRoleIds,
- 'group' => $aGroupIds,
- 'user' => $aUserIds,
- );
- KTWorkflowUtil::setInformedForState($oState, $aAllowed);
$this->successRedirectTo($sTargetAction, _('Changes saved'), $sTargetParams);
}
// }}}
diff --git a/templates/ktcore/workflow/editState.smarty b/templates/ktcore/workflow/editState.smarty
index 0589ce0..c672649 100644
--- a/templates/ktcore/workflow/editState.smarty
+++ b/templates/ktcore/workflow/editState.smarty
@@ -19,7 +19,8 @@ the "sent" transition has been performed by a user.
-{*
+
+
{*
{i18n}Assigned Permissions{/i18n}
diff --git a/templates/ktcore/workflow/workflow_notification.smarty b/templates/ktcore/workflow/workflow_notification.smarty
new file mode 100644
index 0000000..56d84f8
--- /dev/null
+++ b/templates/ktcore/workflow/workflow_notification.smarty
@@ -0,0 +1,10 @@
+{$document_name}
+
+ {i18n arg_name=$document_name arg_state=$state_name}The document #name# has changed to
+ state #state#, and you are specified as one of the users to inform
+ about documents in this state.{/i18n}
+
+
--
libgit2 0.21.4