Commit 544414ff0b2c8abf436fcc7070d484af8a2dbdd1
1 parent
bffdbb9c
Finished off discussion plugin
git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5483 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
7 changed files
with
118 additions
and
30 deletions
lib/discussions/DiscussionThread.inc
| ... | ... | @@ -68,7 +68,7 @@ class DiscussionThread extends KTEntity{ |
| 68 | 68 | function getDocumentId(){ return $this->iDocumentId; } |
| 69 | 69 | function getCreatorId(){ return $this->iCreatorId; } |
| 70 | 70 | function getFirstCommentId(){ return $this->iFirstCommentId; } |
| 71 | - function setFirstCommentId($NewFirstCommentId){ $this->iFirstCommentId = $NewFirstCommentId; } | |
| 71 | + function setFirstCommentId($NewFirstCommentId){ $this->iFirstCommentId = $NewFirstCommentId; } | |
| 72 | 72 | function getLastCommentId(){ return $this->iLastCommentId; } |
| 73 | 73 | function setLastCommentId($iNewLastComment){ $this->iLastCommentId = $iNewLastComment; } |
| 74 | 74 | function getNumberOfViews(){ return $this->iNumberOfViews; } |
| ... | ... | @@ -77,12 +77,12 @@ class DiscussionThread extends KTEntity{ |
| 77 | 77 | function getNumberOfReplies(){ return $this->iNumberOfReplies; } |
| 78 | 78 | function incrementNumberOfReplies(){ $this->iNumberOfReplies += 1; } |
| 79 | 79 | function setNumberOfReplies($iValue){ $this->iNumberOfReplies = $iValue; } |
| 80 | - function getState(){ return $this->iState; } | |
| 81 | - function setState($iValue){ $this->iState = $iValue; } | |
| 82 | - function getCloseMetadataVersion(){ return $this->iCloseMetadataVersion; } | |
| 83 | - function setCloseMetadataVersion($iValue){ $this->iCloseMetadataVersion = $iValue; } | |
| 84 | - function getCloseReason(){ return $this->sCloseReason; } | |
| 85 | - function setCloseReason($sValue){ $this->sCloseReason = $sValue; } | |
| 80 | + function getState(){ return $this->iState; } | |
| 81 | + function setState($iValue){ $this->iState = $iValue; } | |
| 82 | + function getCloseMetadataVersion(){ return $this->iCloseMetadataVersion; } | |
| 83 | + function setCloseMetadataVersion($iValue){ $this->iCloseMetadataVersion = $iValue; } | |
| 84 | + function getCloseReason(){ return $this->sCloseReason; } | |
| 85 | + function setCloseReason($sValue){ $this->sCloseReason = $sValue; } | |
| 86 | 86 | |
| 87 | 87 | |
| 88 | 88 | /** | ... | ... |
lib/documentmanagement/Document.inc
| ... | ... | @@ -197,7 +197,7 @@ class Document { |
| 197 | 197 | // {{{ get |
| 198 | 198 | function &get($iId, $iMetadataVersion=null) { |
| 199 | 199 | $oDocument = new Document(); |
| 200 | - if (!is_numeric($iId)) { print "<pre>Document.inc: 162: "; var_dump($iId); print "</pre>"; } | |
| 200 | + // if (!is_numeric($iId)) { print "<pre>Document.inc: 162: "; var_dump($iId); print "</pre>"; } | |
| 201 | 201 | $res = $oDocument->load($iId, $iMetadataVersion); |
| 202 | 202 | if (PEAR::isError($res)) { |
| 203 | 203 | return $res; | ... | ... |
lib/email/Email.inc
| ... | ... | @@ -51,7 +51,7 @@ class Email { |
| 51 | 51 | $this->oMailer->FromName = (strlen($sFromName) == 0) ? $default->emailFromName : $sFromName; |
| 52 | 52 | $this->oMailer->WordWrap = 100; |
| 53 | 53 | $this->oMailer->IsHTML(true); |
| 54 | - $this->oMailer->SetLanguage('en', KT_DIR . '/phpmailer/language/'); | |
| 54 | + $this->oMailer->SetLanguage('en', KT_DIR . '/thirdparty/phpmailer/language/'); | |
| 55 | 55 | $this->bEmailDisabled = false; |
| 56 | 56 | |
| 57 | 57 | $oConfig =& KTConfig::getSingleton(); | ... | ... |
plugins/ktstandard/KTDiscussion.php
| ... | ... | @@ -30,10 +30,18 @@ require_once(KT_LIB_DIR . '/widgets/fieldWidgets.php'); |
| 30 | 30 | require_once(KT_LIB_DIR . '/discussions/DiscussionThread.inc'); |
| 31 | 31 | require_once(KT_LIB_DIR . '/discussions/DiscussionComment.inc'); |
| 32 | 32 | |
| 33 | + | |
| 34 | +define('DISCUSSION_NEW', 0); | |
| 35 | +define('DISCUSSION_OPEN', 1); | |
| 36 | +define('DISCUSSION_FINALISED', 2); | |
| 37 | +define('DISCUSSION_IMPLEMENTED', 3); | |
| 38 | +define('DISCUSSION_CLOSED', 4); | |
| 39 | + | |
| 40 | + | |
| 33 | 41 | class KTDiscussionPlugin extends KTPlugin { |
| 34 | 42 | var $sNamespace = "ktstandard.discussion.plugin"; |
| 35 | 43 | var $autoRegister = true; |
| 36 | - | |
| 44 | + | |
| 37 | 45 | function KTDiscussionPlugin($sFilename = null) { |
| 38 | 46 | $res = parent::KTPlugin($sFilename); |
| 39 | 47 | $this->sFriendlyName = _kt('Document Discussions Plugin'); |
| ... | ... | @@ -95,6 +103,18 @@ class KTCommentListRenderer { |
| 95 | 103 | |
| 96 | 104 | class KTDocumentDiscussionAction extends KTDocumentAction { |
| 97 | 105 | var $sName = 'ktcore.actions.document.discussion'; |
| 106 | + var $aTransitions = array(DISCUSSION_NEW => array(DISCUSSION_OPEN), | |
| 107 | + DISCUSSION_OPEN => array(DISCUSSION_FINALISED), | |
| 108 | + DISCUSSION_FINALISED => array(DISCUSSION_OPEN, DISCUSSION_IMPLEMENTED), | |
| 109 | + DISCUSSION_IMPLEMENTED => array(DISCUSSION_CLOSED, DISCUSSION_OPEN), | |
| 110 | + DISCUSSION_CLOSED => array()); | |
| 111 | + | |
| 112 | + var $aStateNames = array(DISCUSSION_NEW => 'New', | |
| 113 | + DISCUSSION_OPEN => 'Under discussion', | |
| 114 | + DISCUSSION_FINALISED => 'Finalised - To be implemented', | |
| 115 | + DISCUSSION_IMPLEMENTED => 'Finalised - Implemented', | |
| 116 | + DISCUSSION_CLOSED => 'Closed'); | |
| 117 | + | |
| 98 | 118 | |
| 99 | 119 | function getDisplayName() { |
| 100 | 120 | return _kt('Discussion'); |
| ... | ... | @@ -109,7 +129,14 @@ class KTDocumentDiscussionAction extends KTDocumentAction { |
| 109 | 129 | $fields[] = new KTStringWidget(_kt("Subject"), _kt("The topic of discussion in this thread"), "subject", "", $this->oPage, true); |
| 110 | 130 | $fields[] = new KTTextWidget(_kt("Body"), _kt("Your contribution to the discussion in this thread"), "body", "", $this->oPage, true, null, null, array("cols" => 50, "rows" => 10)); |
| 111 | 131 | |
| 112 | - $threads = DiscussionThread::getList(array('document_id=?', array($this->oDocument->getId()))); | |
| 132 | + $bIncludeClosed = KTUtil::arrayGet($_REQUEST, 'fIncludeClosed', false); | |
| 133 | + | |
| 134 | + $sQuery = sprintf('document_id = %d', $this->oDocument->getId()); | |
| 135 | + if(!$bIncludeClosed) { | |
| 136 | + $sQuery .= sprintf(' AND state != %d', DISCUSSION_CLOSED); | |
| 137 | + } | |
| 138 | + | |
| 139 | + $threads = DiscussionThread::getList($sQuery); | |
| 113 | 140 | |
| 114 | 141 | $aTemplateData = array( |
| 115 | 142 | 'context' => &$this, |
| ... | ... | @@ -205,9 +232,11 @@ class KTDocumentDiscussionAction extends KTDocumentAction { |
| 205 | 232 | $closeFields = array(); |
| 206 | 233 | |
| 207 | 234 | $oPermission =& KTPermission::getByName('ktcore.permissions.write'); |
| 208 | - if (PEAR::isError($oPermission) || | |
| 209 | - KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $this->oDocument)) { | |
| 210 | - $closeFields[] = new KTTextWidget(_kt("Reason"), _kt("Describe the reason for closing this thread"), "reason", "", $this->oPage, true, null, null, array("cols" => 50, "rows" => 5)); | |
| 235 | + | |
| 236 | + if (!PEAR::isError($oPermission) && KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $this->oDocument) && $oThread->getState() != DISCUSSION_CLOSED) { | |
| 237 | + $aOptions = array('vocab' => $this->_buildStates($oThread)); | |
| 238 | + $closeFields[] = new KTLookupWidget(_kt("State"), _kt("Select the state to move this discussion into"), "state", "", $this->oPage, true, null, null, $aOptions); | |
| 239 | + $closeFields[] = new KTTextWidget(_kt("Reason"), _kt("Describe the reason for the state change, or the conclusion reached through discussion"), "reason", "", $this->oPage, true, null, null, array("cols" => 50, "rows" => 5)); | |
| 211 | 240 | } |
| 212 | 241 | |
| 213 | 242 | // increment views |
| ... | ... | @@ -289,14 +318,13 @@ class KTDocumentDiscussionAction extends KTDocumentAction { |
| 289 | 318 | exit(0); |
| 290 | 319 | } |
| 291 | 320 | |
| 292 | - function do_closethread() { | |
| 321 | + function do_changestate() { | |
| 293 | 322 | $aErrorOptions = array( |
| 294 | 323 | 'redirect_to' => array('main', sprintf('fDocumentId=%d', $this->oDocument->getId())), |
| 295 | 324 | ); |
| 296 | 325 | |
| 297 | 326 | $iThreadId = KTUtil::arrayGet($_REQUEST, 'fThreadId'); |
| 298 | 327 | $oThread = DiscussionThread::get($iThreadId); |
| 299 | - | |
| 300 | 328 | $this->oValidator->notError($oThread, $aErrorOptions); |
| 301 | 329 | |
| 302 | 330 | $aErrorOptions = array( |
| ... | ... | @@ -304,24 +332,45 @@ class KTDocumentDiscussionAction extends KTDocumentAction { |
| 304 | 332 | ); |
| 305 | 333 | |
| 306 | 334 | $oPermission =& KTPermission::getByName('ktcore.permissions.write'); |
| 335 | + $sRedirectTo = implode('&', $aErrorOptions['redirect_to']); | |
| 307 | 336 | |
| 308 | 337 | if (PEAR::isError($oPermission)) { |
| 309 | - $this->errorRedirectTo(implode('&', $aErrorOptions['redirect_to']), _kt("Error getting permission")); | |
| 338 | + $this->errorRedirectTo($sRedirectTo, _kt("Error getting permission")); | |
| 339 | + exit(0); | |
| 310 | 340 | } |
| 311 | 341 | if (!KTPermissionUtil::userHasPermissionOnItem($this->oUser, $oPermission, $this->oDocument)) { |
| 312 | - $this->errorRedirectTo(implode('&', $aErrorOptions['redirect_to']), _kt("You do not have permission to close this thread")); | |
| 342 | + $this->errorRedirectTo($sRedirectTo, _kt("You do not have permission to close this thread")); | |
| 343 | + exit(0); | |
| 313 | 344 | } |
| 314 | 345 | |
| 315 | - $aErrorOptions['message'] = _kt("No reason provided"); | |
| 316 | - $sReason = KTUtil::arrayGet($_REQUEST, 'reason'); | |
| 317 | - $sReason = $this->oValidator->validateString($sReason, $aErrorOptions); | |
| 346 | + $iStateId = KTUtil::arrayGet($_REQUEST, 'state'); | |
| 347 | + if(!in_array($iStateId, $this->aTransitions[$oThread->getState()])) { | |
| 348 | + $this->errorRedirectTo($sRedirectTo, _kt("Invalid transition")); | |
| 349 | + exit(0); | |
| 350 | + } | |
| 351 | + | |
| 352 | + $aErrorOptions['message'] = _kt("No reason provided"); | |
| 353 | + $sReason = $this->oValidator->validateString(KTUtil::arrayGet($_REQUEST, 'reason'), $aErrorOptions); | |
| 354 | + | |
| 355 | + if($iStateId > $oThread->getState()) { | |
| 356 | + $sTransactionNamespace = 'ktcore.transactions.collaboration_step_approve'; | |
| 357 | + } else { | |
| 358 | + $sTransactionNamespace = 'ktcore.transactions.collaboration_step_rollback'; | |
| 359 | + } | |
| 318 | 360 | |
| 319 | 361 | // Start the transaction comment creation |
| 320 | 362 | $this->startTransaction(); |
| 321 | 363 | |
| 322 | - $oThread->setState(1); | |
| 323 | - $oThread->setCloseMetadataVersion($this->oDocument->getMetadataVersion()); | |
| 324 | - $oThread->setCloseReason($sReason); | |
| 364 | + $oThread->setState($iStateId); | |
| 365 | + if($iStateId == DISCUSSION_CLOSED) { | |
| 366 | + $oThread->setCloseMetadataVersion($this->oDocument->getMetadataVersion()); | |
| 367 | + } else if($iStateId == DISCUSSION_FINALISED) { | |
| 368 | + $oThread->setCloseReason($sReason); | |
| 369 | + } | |
| 370 | + | |
| 371 | + $oDocumentTransaction = & new DocumentTransaction($this->oDocument, $sReason, $sTransactionNamespace); | |
| 372 | + $oDocumentTransaction->create(); | |
| 373 | + | |
| 325 | 374 | $res = $oThread->update(); |
| 326 | 375 | |
| 327 | 376 | $aErrorOptions['message'] = _kt("There was an error updating the thread with the new comment"); |
| ... | ... | @@ -330,8 +379,28 @@ class KTDocumentDiscussionAction extends KTDocumentAction { |
| 330 | 379 | // Thread closed correctly, so commit |
| 331 | 380 | $this->commitTransaction(); |
| 332 | 381 | |
| 333 | - $this->successRedirectTo('viewThread', _kt("Thread closed"), sprintf('fDocumentId=%d&fThreadId=%d', $this->oDocument->getId(), $oThread->getId())); | |
| 382 | + $this->successRedirectTo('viewThread', _kt("Thread state changed"), sprintf('fDocumentId=%d&fThreadId=%d', $this->oDocument->getId(), $oThread->getId())); | |
| 334 | 383 | exit(0); |
| 335 | 384 | } |
| 336 | 385 | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + function &_buildStates(&$oThread) { | |
| 390 | + $iCurState = $oThread->getState(); | |
| 391 | + $aTransitions = $this->aTransitions[$iCurState]; | |
| 392 | + | |
| 393 | + $aVocab = array(); | |
| 394 | + | |
| 395 | + foreach($aTransitions as $iTransition) { | |
| 396 | + $aVocab[$iTransition] = $this->aStateNames[$iTransition]; | |
| 397 | + } | |
| 398 | + return $aVocab; | |
| 399 | + } | |
| 400 | + | |
| 401 | + function _getStateName($iStateId) { | |
| 402 | + return KTUtil::arrayGet($this->aStateNames, $iStateId, 'Unnamed state'); | |
| 403 | + } | |
| 404 | + | |
| 405 | + | |
| 337 | 406 | } | ... | ... |
templates/ktstandard/action/discussion.smarty
| ... | ... | @@ -34,3 +34,15 @@ |
| 34 | 34 | </div> |
| 35 | 35 | </fieldset> |
| 36 | 36 | </form> |
| 37 | + | |
| 38 | +<form method="POST" action="{$smarty.server.PHP_SELF}"> | |
| 39 | +<input type="hidden" name="fDocumentId" value="{$context->oDocument->getId()}" /> | |
| 40 | +<input type="hidden" name="fIncludeClosed" value="1" /> | |
| 41 | +<fieldset><legend>{i18n}View all threads{/i18n}</legend> | |
| 42 | +<p class="descriptiveText">Click below to view all discussion threads on this document, including those that are closed.</p> | |
| 43 | + | |
| 44 | +<div class="form_actions "> | |
| 45 | + <input type="submit" name="submit" value="{i18n}View threads{/i18n}" /> | |
| 46 | +</div> | |
| 47 | +</fieldset> | |
| 48 | +</form> | ... | ... |
templates/ktstandard/action/discussion_thread.smarty
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | {$commentrenderer->render($context, $oComment, $thread)} |
| 3 | 3 | {/foreach} |
| 4 | 4 | |
| 5 | -{if not $thread->getState()} | |
| 5 | +{if ($thread->getState()!=DISCUSSION_CLOSED)} | |
| 6 | 6 | <form method="POST" action="{$smarty.server.PHP_SELF}"> |
| 7 | 7 | <input type="hidden" name="action" value="postreply" /> |
| 8 | 8 | <input type="hidden" name="fDocumentId" value="{$context->oDocument->getId()}" /> |
| ... | ... | @@ -23,16 +23,16 @@ |
| 23 | 23 | {if $closefields} |
| 24 | 24 | |
| 25 | 25 | <form method="POST" action="{$smarty.server.PHP_SELF}"> |
| 26 | -<input type="hidden" name="action" value="closethread" /> | |
| 26 | +<input type="hidden" name="action" value="changestate" /> | |
| 27 | 27 | <input type="hidden" name="fDocumentId" value="{$context->oDocument->getId()}" /> |
| 28 | 28 | <input type="hidden" name="fThreadId" value="{$thread->getId()}" /> |
| 29 | -<fieldset><legend>{i18n}Close this thread{/i18n}</legend> | |
| 29 | +<fieldset><legend>{i18n}Change the state of this thread{/i18n}</legend> | |
| 30 | 30 | {foreach from=$closefields item=oWidget} |
| 31 | 31 | {$oWidget->render()} |
| 32 | 32 | {/foreach} |
| 33 | 33 | |
| 34 | 34 | <div class="form_actions "> |
| 35 | - <input type="submit" name="submit" value="{i18n}Close this thread{/i18n}" /> | |
| 35 | + <input type="submit" name="submit" value="{i18n}Change state{/i18n}" /> | |
| 36 | 36 | </div> |
| 37 | 37 | </fieldset> |
| 38 | 38 | </form> | ... | ... |
templates/ktstandard/action/discussion_thread_list_item.smarty
| ... | ... | @@ -4,5 +4,12 @@ |
| 4 | 4 | <td>{$thread->getNumberOfViews()}</td> |
| 5 | 5 | <td>{$thread->getNumberOfReplies()}</td> |
| 6 | 6 | <td>{$last_comment->getDate()}</td> |
| 7 | - <td>{if $thread->getState()}Closed at metadata version {$thread->getCloseMetadataVersion()}. <br /><strong>Reason:</strong> {$thread->getCloseReason()}{else}Open{/if}</td> | |
| 7 | + <td> | |
| 8 | + {assign var=iStateId value=$thread->getState()} | |
| 9 | + {assign var=sStateName value=$context->_getStateName($iStateId)} | |
| 10 | + {$sStateName}<br/> | |
| 11 | + {if ($iStateId==DISCUSSION_FINALISED || $iStateId==DISCUSSION_IMPLEMENTED || $iStateId==DISCUSSION_CLOSED)} | |
| 12 | + <strong>{i18n}Conclusion{/i18n}:</strong> {$thread->getCloseReason()}{/if} | |
| 13 | + {if ($iStateId==DISCUSSION_CLOSED)}<br/>(Closed at metadata version: {$thread->getCloseMetadataVersion()}){/if} | |
| 14 | + </td> | |
| 8 | 15 | </tr> | ... | ... |