Commit 542d5f308442279531ccc0946afcd72fd1664141
1 parent
7cb036ce
merge in new workflow + type<->workflow mapping work.
Brad Shuttleworth 2006-01-30 type allocator <-> workflow map. closes KTS...
Brad Shuttleworth 2006-01-30 very core: edit, add, move all hook into t...
Brad Shuttleworth 2006-01-30 add a postvalidate trigger to documentutil.
Brad Shuttleworth 2006-01-30 standard workflow association basics.
Brad Shuttleworth 2006-01-30 i accidentally broke half of checkout.
Brad Shuttleworth 2006-01-30 workflow association basic.
git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4711 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
14 changed files
with
519 additions
and
2 deletions
config/tableMappings.inc
| @@ -146,4 +146,6 @@ $default->role_allocations_table = "role_allocations"; | @@ -146,4 +146,6 @@ $default->role_allocations_table = "role_allocations"; | ||
| 146 | $default->plugins_table = "plugins"; | 146 | $default->plugins_table = "plugins"; |
| 147 | $default->document_metadata_version_table = "document_metadata_version"; | 147 | $default->document_metadata_version_table = "document_metadata_version"; |
| 148 | $default->document_content_version_table = "document_content_version"; | 148 | $default->document_content_version_table = "document_content_version"; |
| 149 | +$default->trigger_selection_table = "trigger_selection"; | ||
| 150 | +$default->type_workflow_map_table = "type_workflow_map"; | ||
| 149 | ?> | 151 | ?> |
edit.php
| @@ -29,6 +29,8 @@ require_once(KT_LIB_DIR . "/widgets/FieldsetDisplayRegistry.inc.php"); | @@ -29,6 +29,8 @@ require_once(KT_LIB_DIR . "/widgets/FieldsetDisplayRegistry.inc.php"); | ||
| 29 | require_once(KT_LIB_DIR . "/actions/documentaction.inc.php"); | 29 | require_once(KT_LIB_DIR . "/actions/documentaction.inc.php"); |
| 30 | require_once(KT_LIB_DIR . "/browse/browseutil.inc.php"); | 30 | require_once(KT_LIB_DIR . "/browse/browseutil.inc.php"); |
| 31 | 31 | ||
| 32 | +require_once(KT_LIB_DIR . '/triggers/triggerregistry.inc.php'); | ||
| 33 | + | ||
| 32 | 34 | ||
| 33 | class KTEditDocumentDispatcher extends KTStandardDispatcher { | 35 | class KTEditDocumentDispatcher extends KTStandardDispatcher { |
| 34 | var $bAutomaticTransaction = true; | 36 | var $bAutomaticTransaction = true; |
| @@ -317,7 +319,7 @@ class KTEditDocumentDispatcher extends KTStandardDispatcher { | @@ -317,7 +319,7 @@ class KTEditDocumentDispatcher extends KTStandardDispatcher { | ||
| 317 | // FIXME handle md versions. | 319 | // FIXME handle md versions. |
| 318 | //return '<pre>' . print_r($field_values, true) . '</pre>'; | 320 | //return '<pre>' . print_r($field_values, true) . '</pre>'; |
| 319 | $this->startTransaction(); | 321 | $this->startTransaction(); |
| 320 | - | 322 | + $iPreviousMetadataVersionId = $oDocument->getMetadataVersionId(); |
| 321 | $oDocument->startNewMetadataVersion($this->oUser); | 323 | $oDocument->startNewMetadataVersion($this->oUser); |
| 322 | if (PEAR::isError($res)) { | 324 | if (PEAR::isError($res)) { |
| 323 | $this->errorRedirectToMain('Unable to create a metadata version of the document.'); | 325 | $this->errorRedirectToMain('Unable to create a metadata version of the document.'); |
| @@ -427,6 +429,21 @@ class KTEditDocumentDispatcher extends KTStandardDispatcher { | @@ -427,6 +429,21 @@ class KTEditDocumentDispatcher extends KTStandardDispatcher { | ||
| 427 | 429 | ||
| 428 | 430 | ||
| 429 | } else { | 431 | } else { |
| 432 | + | ||
| 433 | + // post-triggers. | ||
| 434 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | ||
| 435 | + $aTriggers = $oKTTriggerRegistry->getTriggers('edit', 'postValidate'); | ||
| 436 | + | ||
| 437 | + foreach ($aTriggers as $aTrigger) { | ||
| 438 | + $sTrigger = $aTrigger[0]; | ||
| 439 | + $oTrigger = new $sTrigger; | ||
| 440 | + $aInfo = array( | ||
| 441 | + "document" => $oDocument, | ||
| 442 | + ); | ||
| 443 | + $oTrigger->setInfo($aInfo); | ||
| 444 | + $ret = $oTrigger->postValidate(); | ||
| 445 | + } | ||
| 446 | + | ||
| 430 | $this->commitTransaction(); | 447 | $this->commitTransaction(); |
| 431 | 448 | ||
| 432 | // now we need to say we're ok. | 449 | // now we need to say we're ok. |
lib/documentmanagement/documentutil.inc.php
| @@ -43,6 +43,9 @@ require_once(KT_LIB_DIR . "/subscriptions/subscriptions.inc.php"); | @@ -43,6 +43,9 @@ require_once(KT_LIB_DIR . "/subscriptions/subscriptions.inc.php"); | ||
| 43 | require_once(KT_LIB_DIR . '/triggers/triggerregistry.inc.php'); | 43 | require_once(KT_LIB_DIR . '/triggers/triggerregistry.inc.php'); |
| 44 | require_once(KT_LIB_DIR . "/foldermanagement/Folder.inc"); | 44 | require_once(KT_LIB_DIR . "/foldermanagement/Folder.inc"); |
| 45 | 45 | ||
| 46 | +// WORKFLOW | ||
| 47 | +require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php'); | ||
| 48 | + | ||
| 46 | class KTDocumentUtil { | 49 | class KTDocumentUtil { |
| 47 | function createMetadataVersion($oDocument) { | 50 | function createMetadataVersion($oDocument) { |
| 48 | if (is_numeric($oDocument)) { | 51 | if (is_numeric($oDocument)) { |
| @@ -76,7 +79,7 @@ class KTDocumentUtil { | @@ -76,7 +79,7 @@ class KTDocumentUtil { | ||
| 76 | $oVersionDFL->setDocumentID($iVersionDocumentID); | 79 | $oVersionDFL->setDocumentID($iVersionDocumentID); |
| 77 | $res = $oVersionDFL->create(); | 80 | $res = $oVersionDFL->create(); |
| 78 | } | 81 | } |
| 79 | - | 82 | + |
| 80 | return $oVersionDocument; | 83 | return $oVersionDocument; |
| 81 | } | 84 | } |
| 82 | 85 | ||
| @@ -317,6 +320,7 @@ class KTDocumentUtil { | @@ -317,6 +320,7 @@ class KTDocumentUtil { | ||
| 317 | $aRow['metadata_version_id'] = $iNewMetadataVersion; | 320 | $aRow['metadata_version_id'] = $iNewMetadataVersion; |
| 318 | DBUtil::autoInsert($sTable, $aRow); | 321 | DBUtil::autoInsert($sTable, $aRow); |
| 319 | } | 322 | } |
| 323 | + | ||
| 320 | } | 324 | } |
| 321 | 325 | ||
| 322 | // {{{ setIncomplete | 326 | // {{{ setIncomplete |
| @@ -445,6 +449,20 @@ class KTDocumentUtil { | @@ -445,6 +449,20 @@ class KTDocumentUtil { | ||
| 445 | $oSubscriptionEvent = new SubscriptionEvent(); | 449 | $oSubscriptionEvent = new SubscriptionEvent(); |
| 446 | $oFolder = Folder::get($oDocument->getFolderID()); | 450 | $oFolder = Folder::get($oDocument->getFolderID()); |
| 447 | $oSubscriptionEvent->AddDocument($oDocument, $oFolder); | 451 | $oSubscriptionEvent->AddDocument($oDocument, $oFolder); |
| 452 | + | ||
| 453 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | ||
| 454 | + $aTriggers = $oKTTriggerRegistry->getTriggers('add', 'postValidate'); | ||
| 455 | + | ||
| 456 | + foreach ($aTriggers as $aTrigger) { | ||
| 457 | + $sTrigger = $aTrigger[0]; | ||
| 458 | + $oTrigger = new $sTrigger; | ||
| 459 | + $aInfo = array( | ||
| 460 | + "document" => $oDocument, | ||
| 461 | + ); | ||
| 462 | + $oTrigger->setInfo($aInfo); | ||
| 463 | + $ret = $oTrigger->postValidate(); | ||
| 464 | + | ||
| 465 | + } | ||
| 448 | 466 | ||
| 449 | $oUploadChannel->sendMessage(new KTUploadGenericMessage(_("All done..."))); | 467 | $oUploadChannel->sendMessage(new KTUploadGenericMessage(_("All done..."))); |
| 450 | 468 |
lib/workflow/workflowutil.inc.php
| @@ -87,6 +87,10 @@ class KTWorkflowUtil { | @@ -87,6 +87,10 @@ class KTWorkflowUtil { | ||
| 87 | $iDocumentId = KTUtil::getId($oDocument); | 87 | $iDocumentId = KTUtil::getId($oDocument); |
| 88 | $iWorkflowId = KTUtil::getId($oWorkflow); | 88 | $iWorkflowId = KTUtil::getId($oWorkflow); |
| 89 | $oWorkflow =& KTWorkflow::get($iWorkflowId); | 89 | $oWorkflow =& KTWorkflow::get($iWorkflowId); |
| 90 | + // null workflow == remove workflow. | ||
| 91 | + if (is_null($oWorkflow) || PEAR::isError($oWorkflow) || ($oWorkflow == false)) { | ||
| 92 | + return true; // delete and no-act. | ||
| 93 | + } | ||
| 90 | $iStartStateId = $oWorkflow->getStartStateId(); | 94 | $iStartStateId = $oWorkflow->getStartStateId(); |
| 91 | if (empty($iStartStateId)) { | 95 | if (empty($iStartStateId)) { |
| 92 | return PEAR::raiseError('Cannot assign workflow with no starting state set'); | 96 | return PEAR::raiseError('Cannot assign workflow with no starting state set'); |
| @@ -101,6 +105,46 @@ class KTWorkflowUtil { | @@ -101,6 +105,46 @@ class KTWorkflowUtil { | ||
| 101 | return DBUtil::autoInsert($sTable, $aValues, $aOptions); | 105 | return DBUtil::autoInsert($sTable, $aValues, $aOptions); |
| 102 | } | 106 | } |
| 103 | // }}} | 107 | // }}} |
| 108 | + | ||
| 109 | + | ||
| 110 | + // {{{ changeWorkflowOnDocument | ||
| 111 | + /** | ||
| 112 | + * Starts the workflow process on a document, placing it into the | ||
| 113 | + * starting workflow state for the given workflow. | ||
| 114 | + */ | ||
| 115 | + function changeWorkflowOnDocument ($oWorkflow, $oDocument) { | ||
| 116 | + $iDocumentId = KTUtil::getId($oDocument); | ||
| 117 | + $iWorkflowId = KTUtil::getId($oWorkflow); | ||
| 118 | + $oWorkflow =& KTWorkflow::get($iWorkflowId); | ||
| 119 | + | ||
| 120 | + if (empty($iStartStateId)) { | ||
| 121 | + return PEAR::raiseError('Cannot assign workflow with no starting state set'); | ||
| 122 | + } | ||
| 123 | + $oOldWorkflow = KTWorkflowUtil::getWorkflowForDocument($oDocument); | ||
| 124 | + if ((!(PEAR::isError($oOldWorkflow) || ($oOldWorkflow == false))) && ($oOldWorkflow->getId() == $oWorkflow->getId())) { | ||
| 125 | + return true; // all fine - no change required. | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + $sQuery = 'DELETE FROM ' . KTUtil::getTableName('workflow_documents'); | ||
| 129 | + $sQuery .= ' WHERE document_id = ?'; | ||
| 130 | + $aParams = array($iDocumentId); | ||
| 131 | + DBUtil::runQuery(array($sQuery, $aParams)); | ||
| 132 | + | ||
| 133 | + if (is_null($oWorkflow) || PEAR::isError($oWorkflow) || ($oWorkflow == false)) { | ||
| 134 | + return true; // delete and no-act. | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + $iStartStateId = $oWorkflow->getStartStateId(); | ||
| 138 | + $aOptions = array('noid' => true); | ||
| 139 | + $aValues = array( | ||
| 140 | + 'document_id' => $iDocumentId, | ||
| 141 | + 'workflow_id' => $iWorkflowId, | ||
| 142 | + 'state_id' => $iStartStateId, | ||
| 143 | + ); | ||
| 144 | + $sTable = KTUtil::getTableName('workflow_documents'); | ||
| 145 | + return DBUtil::autoInsert($sTable, $aValues, $aOptions); | ||
| 146 | + } | ||
| 147 | + // }}} | ||
| 104 | 148 | ||
| 105 | // {{{ getControlledActionsForWorkflow | 149 | // {{{ getControlledActionsForWorkflow |
| 106 | /** | 150 | /** |
plugins/ktcore/KTDocumentActions.php
| @@ -70,6 +70,12 @@ class KTDocumentCheckOutAction extends KTDocumentAction { | @@ -70,6 +70,12 @@ class KTDocumentCheckOutAction extends KTDocumentAction { | ||
| 70 | if ($res !== true) { | 70 | if ($res !== true) { |
| 71 | return $res; | 71 | return $res; |
| 72 | } | 72 | } |
| 73 | + // since we actually check the doc out, then download it ... | ||
| 74 | + if (($_REQUEST[$this->event_var] == 'checkout_final') && ($this->oDocument->getCheckedOutUserID() == $_SESSION['userID'])) { | ||
| 75 | + return true; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + // "normal". | ||
| 73 | if ($this->oDocument->getIsCheckedOut()) { | 79 | if ($this->oDocument->getIsCheckedOut()) { |
| 74 | $_SESSION['KTErrorMessage'][] = _("This document is already checked out"); | 80 | $_SESSION['KTErrorMessage'][] = _("This document is already checked out"); |
| 75 | controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId()); | 81 | controllerRedirect('viewDocument', 'fDocumentId=' . $this->oDocument->getId()); |
plugins/ktstandard/KTStandardPlugin.php
| @@ -6,3 +6,4 @@ require_once('KTDiscussion.php'); | @@ -6,3 +6,4 @@ require_once('KTDiscussion.php'); | ||
| 6 | require_once('KTEmail.php'); | 6 | require_once('KTEmail.php'); |
| 7 | 7 | ||
| 8 | require_once('KTIndexer.php'); | 8 | require_once('KTIndexer.php'); |
| 9 | +require_once('KTWorkflowAssociation.php'); | ||
| 9 | \ No newline at end of file | 10 | \ No newline at end of file |
plugins/ktstandard/KTWorkflowAssociation.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +require_once(KT_LIB_DIR . '/workflow/workflowutil.inc.php'); | ||
| 4 | +require_once(KT_LIB_DIR . '/triggers/triggerregistry.inc.php'); | ||
| 5 | + | ||
| 6 | +require_once(KT_LIB_DIR . '/database/dbutil.inc'); | ||
| 7 | +require_once(KT_LIB_DIR . '/util/ktutil.inc'); | ||
| 8 | + | ||
| 9 | +class KTWorkflowAssociationPlugin extends KTPlugin { | ||
| 10 | + var $sNamespace = "ktstandard.workflowassociation.plugin"; | ||
| 11 | + | ||
| 12 | + function setup() { | ||
| 13 | + $this->registerTrigger('add', 'postValidate', 'KTWADAddTrigger', | ||
| 14 | + 'ktstandard.triggers.workflowassociation.addDocument'); | ||
| 15 | + $this->registerTrigger('moveDocument', 'postValidate', 'KTWADMoveTrigger', | ||
| 16 | + 'ktstandard.triggers.workflowassociation.moveDocument'); | ||
| 17 | + $this->registerTrigger('edit', 'postValidate', 'KTWADEditTrigger', | ||
| 18 | + 'ktstandard.triggers.workflowassociation.editDocument'); | ||
| 19 | + $this->registerAdminPage('workflow_allocation', 'WorkflowAllocationSelection', | ||
| 20 | + 'documents', _('Automatic Workflow Assignments'), | ||
| 21 | + _('Configure how documents are allocated to workflows.'), 'workflow/adminpage.php'); | ||
| 22 | + $this->registeri18n('knowledgeTree', KT_DIR . '/i18n'); | ||
| 23 | + } | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +// base class for delegation. | ||
| 27 | +class KTWorkflowAssociationDelegator { | ||
| 28 | + var $_handler; | ||
| 29 | + var $_document; | ||
| 30 | + | ||
| 31 | + function KTWorkflowAssociationDelegator() { | ||
| 32 | + | ||
| 33 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | ||
| 34 | + $aTriggers = $oKTTriggerRegistry->getTriggers('workflow', 'objectModification'); | ||
| 35 | + | ||
| 36 | + // if we have _some_ triggers. | ||
| 37 | + if (!empty($aTriggers)) { | ||
| 38 | + $sQuery = 'SELECT selection_ns FROM ' . KTUtil::getTableName('trigger_selection'); | ||
| 39 | + $sQuery .= ' WHERE event_ns = ?'; | ||
| 40 | + $aParams = array('ktstandard.workflowassociation.handler'); | ||
| 41 | + $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'selection_ns'); | ||
| 42 | + | ||
| 43 | + if (PEAR::isError($res)) { $this->_handler = new KTWorkflowAssociationHandler(); } | ||
| 44 | + | ||
| 45 | + if (array_key_exists($res, $aTriggers)) { | ||
| 46 | + $this->_handler = new $aTriggers[$res][0]; | ||
| 47 | + } | ||
| 48 | + else { | ||
| 49 | + global $default; | ||
| 50 | + $default->log->debug('KTWorkflowAssociationDelegator failed to acquire trigger selection'); | ||
| 51 | + $this->_handler = new KTWorkflowAssociationHandler(); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + else { | ||
| 55 | + $this->_handler = new KTWorkflowAssociationHandler(); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + function applyWorkflow($oWorkflow) { | ||
| 60 | + return true; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + function setInfo($aOptions) { | ||
| 64 | + $this->_document = $aOptions['document']; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + function postValidate() { | ||
| 68 | + return KTWorkflowUtil::getWorkflowForDocument($this->_document); | ||
| 69 | + } | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +// Add | ||
| 73 | +class KTWADAddTrigger extends KTWorkflowAssociationDelegator { | ||
| 74 | + function postValidate() { | ||
| 75 | + $oWorkflow = $this->_handler->addTrigger($this->_document); | ||
| 76 | + $ret = KTWorkflowUtil::startWorkflowOnDocument($oWorkflow, $this->_document); | ||
| 77 | + } | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +// Edit | ||
| 81 | +class KTWADEditTrigger extends KTWorkflowAssociationDelegator { | ||
| 82 | + function postValidate() { | ||
| 83 | + $oWorkflow = $this->_handler->editTrigger($this->_document); | ||
| 84 | + $ret = KTWorkflowUtil::changeWorkflowOnDocument($oWorkflow, $this->_document); | ||
| 85 | + } | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +// Move | ||
| 89 | +class KTWADMoveTrigger extends KTWorkflowAssociationDelegator { | ||
| 90 | + function postValidate() { | ||
| 91 | + $oWorkflow = $this->_handler->moveTrigger($this->_document); | ||
| 92 | + $ret = KTWorkflowUtil::changeWorkflowOnDocument($oWorkflow, $this->_document); | ||
| 93 | + } | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +// "base class" for fallback. should be subclassed and cross-referenced, otherwise | ||
| 97 | +// has no impact when called. | ||
| 98 | +class KTWorkflowAssociationHandler { | ||
| 99 | + function addTrigger($oDocument) { return KTWorkflowUtil::getWorkflowForDocument($oDocument); } | ||
| 100 | + function editTrigger($oDocument) { return KTWorkflowUtil::getWorkflowForDocument($oDocument); } | ||
| 101 | + function moveTrigger($oDocument) { return KTWorkflowUtil::getWorkflowForDocument($oDocument); } | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | + | ||
| 105 | +$oPluginRegistry =& KTPluginRegistry::getSingleton(); | ||
| 106 | +$oPluginRegistry->registerPlugin('KTWorkflowAssociationPlugin', 'ktstandard.workflowassociation.plugin', __FILE__); | ||
| 107 | + | ||
| 108 | + | ||
| 109 | +/* include others */ | ||
| 110 | + | ||
| 111 | +require_once('workflow/TypeAssociator.php'); | ||
| 112 | + | ||
| 113 | +?> |
plugins/ktstandard/workflow/TypeAssociator.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +require_once(KT_DIR . '/plugins/ktstandard/KTWorkflowAssociation.php'); | ||
| 4 | +require_once(KT_LIB_DIR . '/workflow/workflow.inc.php'); | ||
| 5 | +require_once(KT_LIB_DIR . '/dispatcher.inc.php'); | ||
| 6 | + | ||
| 7 | +class KTDocTypeWorkflowAssociationPlugin extends KTPlugin { | ||
| 8 | + var $sNamespace = "ktstandard.workflowassociation.documenttype.plugin"; | ||
| 9 | + | ||
| 10 | + function setup() { | ||
| 11 | + $this->registerTrigger('workflow', 'objectModification', 'DocumentTypeWorkflowAssociator', | ||
| 12 | + 'ktstandard.triggers.workflowassociation.documenttype.handler'); | ||
| 13 | + | ||
| 14 | + $sQuery = 'SELECT selection_ns FROM ' . KTUtil::getTableName('trigger_selection'); | ||
| 15 | + $sQuery .= ' WHERE event_ns = ?'; | ||
| 16 | + $aParams = array('ktstandard.workflowassociation.handler'); | ||
| 17 | + $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'selection_ns'); | ||
| 18 | + | ||
| 19 | + if ($res == 'ktstandard.triggers.workflowassociation.documenttype.handler') { | ||
| 20 | + $this->registerAdminPage('workflow_type_allocation', 'WorkflowTypeAllocationDispatcher', | ||
| 21 | + 'documents', _('Workflow Allocation by Document Types'), | ||
| 22 | + _('This installation assigns workflows by Document Type. Configure this process here.'), __FILE__); | ||
| 23 | + $this->registeri18n('knowledgeTree', KT_DIR . '/i18n'); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + } | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +class DocumentTypeWorkflowAssociator extends KTWorkflowAssociationHandler { | ||
| 30 | + function addTrigger($oDocument) { | ||
| 31 | + return $oW = $this->getWorkflowForType($oDocument->getDocumentTypeID()); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + function editTrigger($oDocument) { | ||
| 35 | + return $oW = $this->getWorkflowForType($oDocument->getDocumentTypeID()); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + function getWorkflowForType($iDocTypeId) { | ||
| 39 | + if (is_null($iDocTypeId)) { return null; } | ||
| 40 | + | ||
| 41 | + $sQuery = 'SELECT `workflow_id` FROM ' . KTUtil::getTableName('type_workflow_map'); | ||
| 42 | + $sQuery .= ' WHERE `document_type_id` = ?'; | ||
| 43 | + $aParams = array($iDocTypeId); | ||
| 44 | + $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'workflow_id'); | ||
| 45 | + if (PEAR::isError($res)) { | ||
| 46 | + return null; | ||
| 47 | + } | ||
| 48 | + return KTWorkflow::get($res); | ||
| 49 | + } | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +class WorkflowTypeAllocationDispatcher extends KTAdminDispatcher { | ||
| 53 | + var $bAutomaticTransaction = true; | ||
| 54 | + var $sSection = 'administration'; | ||
| 55 | + | ||
| 56 | + function check() { | ||
| 57 | + $res = parent::check(); | ||
| 58 | + if (!$res) { return false; } | ||
| 59 | + | ||
| 60 | + $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name'=>_('Workflow Allocation by Document Types')); | ||
| 61 | + | ||
| 62 | + return true; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + function do_main() { | ||
| 66 | + $sQuery = 'SELECT document_type_id, workflow_id FROM ' . KTUtil::getTableName('type_workflow_map'); | ||
| 67 | + $aParams = array(); | ||
| 68 | + $res = DBUtil::getResultArray(array($sQuery, $aParams)); | ||
| 69 | + $aWorkflows = KTWorkflow::getList(); | ||
| 70 | + $aTypes = DocumentType::getList(); | ||
| 71 | + | ||
| 72 | + $aTypeMapping = array(); | ||
| 73 | + if (PEAR::isError($res)) { | ||
| 74 | + $this->oPage->addError(_('Failed to get type mapping: ') . $res->getMessage()); | ||
| 75 | + } else { | ||
| 76 | + foreach ($res as $aRow) { | ||
| 77 | + $aTypeMapping[$aRow['document_type_id']] = $aRow['workflow_id']; | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + $oTemplate =& $this->oValidator->validateTemplate('ktstandard/workflow/type_allocation'); | ||
| 82 | + $oTemplate->setData(array( | ||
| 83 | + 'context' => $this, | ||
| 84 | + 'types_mapping' => $aTypeMapping, | ||
| 85 | + 'types' => $aTypes, | ||
| 86 | + 'workflows' => $aWorkflows, | ||
| 87 | + )); | ||
| 88 | + return $oTemplate->render(); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + function isActiveWorkflow($oType, $oWorkflow, $types_mapping) { | ||
| 92 | + if (!array_key_exists($oType->getId(), $types_mapping)) { return false; } | ||
| 93 | + else { | ||
| 94 | + return $types_mapping[$oType->getId()] == $oWorkflow->getId(); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + function do_update() { | ||
| 99 | + $types_mapping = (array) KTUtil::arrayGet($_REQUEST, 'fDocumentTypeAssignment'); | ||
| 100 | + | ||
| 101 | + $aWorkflows = KTWorkflow::getList(); | ||
| 102 | + $aTypes = DocumentType::getList(); | ||
| 103 | + | ||
| 104 | + $sQuery = 'DELETE FROM ' . KTUtil::getTableName('type_workflow_map'); | ||
| 105 | + $aParams = array(); | ||
| 106 | + DBUtil::runQuery(array($sQuery, $aParams)); | ||
| 107 | + | ||
| 108 | + $aOptions = array('noid' => true); | ||
| 109 | + $sTable = KTUtil::getTableName('type_workflow_map'); | ||
| 110 | + foreach ($aTypes as $oType) { | ||
| 111 | + $t = $types_mapping[$oType->getId()]; | ||
| 112 | + if ($t == null) { $t = null; } | ||
| 113 | + $res = DBUtil::autoInsert($sTable, array( | ||
| 114 | + 'document_type_id' => $oType->getId(), | ||
| 115 | + 'workflow_id' => $t, | ||
| 116 | + ), $aOptions); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + $this->successRedirectToMain(_('Type mapping updated.')); | ||
| 120 | + } | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | + | ||
| 124 | +$oPluginRegistry =& KTPluginRegistry::getSingleton(); | ||
| 125 | +$oPluginRegistry->registerPlugin('KTDocTypeWorkflowAssociationPlugin', 'ktstandard.workflowassociation.documenttype.plugin', __FILE__); | ||
| 126 | + | ||
| 127 | + | ||
| 128 | +?> | ||
| 0 | \ No newline at end of file | 129 | \ No newline at end of file |
plugins/ktstandard/workflow/adminpage.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +require_once(KT_LIB_DIR . "/templating/templating.inc.php"); | ||
| 4 | +require_once(KT_LIB_DIR . "/dispatcher.inc.php"); | ||
| 5 | + | ||
| 6 | +require_once(KT_LIB_DIR . '/widgets/fieldWidgets.php'); | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +class WorkflowAllocationSelection extends KTAdminDispatcher { | ||
| 10 | + var $bAutomaticTransaction = true; | ||
| 11 | + var $sSection = 'administration'; | ||
| 12 | + | ||
| 13 | + function check() { | ||
| 14 | + $res = parent::check(); | ||
| 15 | + if (!$res) { return false; } | ||
| 16 | + | ||
| 17 | + $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name'=> _('Automatic Workflow Assignments')); | ||
| 18 | + | ||
| 19 | + return true; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + function do_main() { | ||
| 23 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | ||
| 24 | + $aTriggers = $oKTTriggerRegistry->getTriggers('workflow', 'objectModification'); | ||
| 25 | + | ||
| 26 | + $aFields = array(); | ||
| 27 | + $aVocab = array(); | ||
| 28 | + $aVocab[] = 'No automatic assignment'; | ||
| 29 | + foreach ($aTriggers as $aTrigger) { | ||
| 30 | + $aVocab[$aTrigger[2]] = $aTrigger[0]; | ||
| 31 | + } | ||
| 32 | + $aFields[] = new KTLookupWidget(_('Workflow Plugins'), _('Plugins providing workflow allocators.'),'selection_ns', $this->getHandler(), $this->oPage, true, null, null, array('vocab' => $aVocab)); | ||
| 33 | + | ||
| 34 | + $oTemplate =& $this->oValidator->validateTemplate('ktstandard/workflow/allocator_selection'); | ||
| 35 | + $oTemplate->setData(array( | ||
| 36 | + 'context' => $this, | ||
| 37 | + 'trigger_fields' => $aFields, | ||
| 38 | + )); | ||
| 39 | + return $oTemplate->render(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + function getHandler() { | ||
| 43 | + $sQuery = 'SELECT selection_ns FROM ' . KTUtil::getTableName('trigger_selection'); | ||
| 44 | + $sQuery .= ' WHERE event_ns = ?'; | ||
| 45 | + $aParams = array('ktstandard.workflowassociation.handler'); | ||
| 46 | + $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'selection_ns'); | ||
| 47 | + return $res; | ||
| 48 | + | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + function do_assign_handler() { | ||
| 52 | + $oKTTriggerRegistry = KTTriggerRegistry::getSingleton(); | ||
| 53 | + $aTriggers = $oKTTriggerRegistry->getTriggers('workflow', 'objectModification'); | ||
| 54 | + | ||
| 55 | + $selection_ns = KTUtil::arrayGet($_REQUEST, 'selection_ns'); | ||
| 56 | + if (empty($selection_ns)) { | ||
| 57 | + $sQuery = 'DELETE FROM ' . KTUtil::getTableName('trigger_selection'); | ||
| 58 | + $sQuery .= ' WHERE event_ns = ?'; | ||
| 59 | + $aParams = array('ktstandard.workflowassociation.handler'); | ||
| 60 | + DBUtil::runQuery(array($sQuery, $aParams)); | ||
| 61 | + $this->successRedirectToMain(_('Handler removed.')); | ||
| 62 | + } else { | ||
| 63 | + if (!array_key_exists($selection_ns, $aTriggers)) { | ||
| 64 | + $this->errorRedirectToMain(_('Invalid assignment')); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + // clear | ||
| 69 | + $sQuery = 'DELETE FROM ' . KTUtil::getTableName('trigger_selection'); | ||
| 70 | + $sQuery .= ' WHERE event_ns = ?'; | ||
| 71 | + $aParams = array('ktstandard.workflowassociation.handler'); | ||
| 72 | + DBUtil::runQuery(array($sQuery, $aParams)); | ||
| 73 | + | ||
| 74 | + // set | ||
| 75 | + $sQuery = 'INSERT INTO ' . KTUtil::getTableName('trigger_selection'); | ||
| 76 | + $sQuery .= ' (event_ns, selection_ns)'; | ||
| 77 | + $sQuery .= ' VALUES ("ktstandard.workflowassociation.handler",?)'; | ||
| 78 | + $aParams = array($selection_ns); | ||
| 79 | + DBUtil::runQuery(array($sQuery, $aParams)); | ||
| 80 | + $this->successRedirectToMain(_('Handler set.')); | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +?> |
sql/mysql/install/structure.sql
| @@ -1091,6 +1091,29 @@ CREATE TABLE `time_unit_lookup` ( | @@ -1091,6 +1091,29 @@ CREATE TABLE `time_unit_lookup` ( | ||
| 1091 | -- -------------------------------------------------------- | 1091 | -- -------------------------------------------------------- |
| 1092 | 1092 | ||
| 1093 | -- | 1093 | -- |
| 1094 | +-- Table structure for table `trigger_selection` | ||
| 1095 | +-- | ||
| 1096 | + | ||
| 1097 | +CREATE TABLE `trigger_selection` ( | ||
| 1098 | + `event_ns` varchar(255) not null default '' UNIQUE, | ||
| 1099 | + PRIMARY KEY (`event_ns`), | ||
| 1100 | + `selection_ns` varchar(255) not null default '' | ||
| 1101 | +) TYPE=InnoDB; | ||
| 1102 | + | ||
| 1103 | +CREATE TABLE `type_workflow_map` ( | ||
| 1104 | + `document_type_id` INT(11) NOT NULL DEFAULT 0 UNIQUE, | ||
| 1105 | + PRIMARY KEY (`document_type_id`), | ||
| 1106 | + `workflow_id` INT UNSIGNED -- can be null. | ||
| 1107 | + ) TYPE=InnoDB; | ||
| 1108 | + | ||
| 1109 | +CREATE TABLE `folder_workflow_map` ( | ||
| 1110 | + `folder_id` INT(11) NOT NULL DEFAULT 0 UNIQUE, | ||
| 1111 | + PRIMARY KEY (`folder_id`), | ||
| 1112 | + `workflow_id` INT(11) -- can be null. | ||
| 1113 | + ) TYPE=InnoDB; | ||
| 1114 | + | ||
| 1115 | +-- -------------------------------------------------------- | ||
| 1116 | +-- | ||
| 1094 | -- Table structure for table `units_lookup` | 1117 | -- Table structure for table `units_lookup` |
| 1095 | -- | 1118 | -- |
| 1096 | 1119 |
sql/mysql/upgrade/2.99.8/trigger_selection.sql
0 → 100644
sql/mysql/upgrade/2.99.8/type_workflow_map.sql
0 → 100644
| 1 | +CREATE TABLE `type_workflow_map` ( | ||
| 2 | + `document_type_id` INT(11) NOT NULL DEFAULT 0 UNIQUE, | ||
| 3 | + PRIMARY KEY (`document_type_id`), | ||
| 4 | + `workflow_id` INT UNSIGNED -- can be null. | ||
| 5 | + ) TYPE=InnoDB; | ||
| 6 | + | ||
| 7 | +CREATE TABLE `folder_workflow_map` ( | ||
| 8 | + `folder_id` INT(11) NOT NULL DEFAULT 0 UNIQUE, | ||
| 9 | + PRIMARY KEY (`folder_id`), | ||
| 10 | + `workflow_id` INT(11) -- can be null. | ||
| 11 | + ) TYPE=InnoDB; | ||
| 0 | \ No newline at end of file | 12 | \ No newline at end of file |
templates/ktstandard/workflow/allocator_selection.smarty
0 → 100644
| 1 | +<h2>{i18n}Automatic Workflow Selection{/i18n}</h2> | ||
| 2 | + | ||
| 3 | +<form action="{$smarty.server.php_self}" method="POST"> | ||
| 4 | +<fieldset> | ||
| 5 | +<legend>{i18n}Workflow Allocation Plugins{/i18n}</legend> | ||
| 6 | +<p class="descriptiveText">{i18n}In order to have documents be automatically associated | ||
| 7 | +with a workflow on creation or modification (as appropriate), please select the | ||
| 8 | +plugin that should handle allocation from the list below.{/i18n}</p> | ||
| 9 | + | ||
| 10 | +{foreach item=oWidget from=$trigger_fields} | ||
| 11 | + {$oWidget->render()} | ||
| 12 | +{/foreach} | ||
| 13 | +<div class="form_actions"> | ||
| 14 | + <input type="submit" value="{i18n}Update{/i18n}" /> | ||
| 15 | + <input type="hidden" name="action" value="assign_handler" /> | ||
| 16 | +</div> | ||
| 17 | +</fieldset> | ||
| 18 | +</form> | ||
| 0 | \ No newline at end of file | 19 | \ No newline at end of file |
templates/ktstandard/workflow/type_allocation.smarty
0 → 100644
| 1 | +<h2>{i18n}Workflow Allocation by Document Type{/i18n}</h2> | ||
| 2 | + | ||
| 3 | +<p class="descriptiveText">{i18n}Workflow types are allocated by Document Type in this | ||
| 4 | +KnowledgeTree installation. Documents will be assigned workflow based on their document | ||
| 5 | +type, and will have their allocated workflows changed if their types change. Naturally, | ||
| 6 | +if the workflows change then the documents will lose any "progress" in the old | ||
| 7 | +workflow.{/i18n}</p> | ||
| 8 | + | ||
| 9 | +<p class="descriptiveText">{i18n}Document Types with no pre-allocated workflow will | ||
| 10 | +either have no workflow set (for new documents) or keep their old workflow (for | ||
| 11 | +documents which have had their type changed.{/i18n}</p> | ||
| 12 | + | ||
| 13 | +<form action="{$smarty.server.PHP_SELF}" method="POST"> | ||
| 14 | +<fieldset> | ||
| 15 | +<legend>{i18n}Workflow Allocations{/i18n}</legend> | ||
| 16 | +<p class="descriptiveText">{i18n}Please select the appropriate workflows for each document type.{/i18n}</p> | ||
| 17 | + | ||
| 18 | +<table class="listing" cellspacing="0"> | ||
| 19 | +<thead> | ||
| 20 | + <tr> | ||
| 21 | + <th>{i18n}Document Type{/i18n}</th> | ||
| 22 | + <th>{i18n}Workflow{/i18n}</th> | ||
| 23 | + </tr> | ||
| 24 | +</thead> | ||
| 25 | +<tbody> | ||
| 26 | +{foreach item=oType from=$types} | ||
| 27 | + <tr> | ||
| 28 | + <td>{$oType->getName()}</td> | ||
| 29 | + <td> | ||
| 30 | + <select name="fDocumentTypeAssignment[{$oType->getId()}]"> | ||
| 31 | + <option value="" >No automatic workflow</option> | ||
| 32 | + {foreach item=oWorkflow from=$workflows} | ||
| 33 | + <option value="{$oWorkflow->getId()}" {if ($context->isActiveWorkflow($oType, $oWorkflow, $types_mapping))}selected="true"{/if}>{$oWorkflow->getName()}</option> | ||
| 34 | + {/foreach} | ||
| 35 | + </select> | ||
| 36 | + </td> | ||
| 37 | + </tr> | ||
| 38 | +{/foreach} | ||
| 39 | +</tbody> | ||
| 40 | +</table> | ||
| 41 | +<div class="form_actions"> | ||
| 42 | + <input type='submit' value="{i18n}Apply{/i18n}" /> | ||
| 43 | + <input type="hidden" name="action" value="update" /> | ||
| 44 | +</div> | ||
| 45 | +</fieldset> | ||
| 46 | +</form> | ||
| 0 | \ No newline at end of file | 47 | \ No newline at end of file |