From 5950be6292a632ce5cef1e527505e03c7f9320e9 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 6 May 2022 09:52:00 +0200 Subject: [PATCH] backport __removeFromProcesses from 6.0.x --- SeedDMS_Core/Core/inc.ClassUser.php | 83 +++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/SeedDMS_Core/Core/inc.ClassUser.php b/SeedDMS_Core/Core/inc.ClassUser.php index c655d333c..54eba4daf 100644 --- a/SeedDMS_Core/Core/inc.ClassUser.php +++ b/SeedDMS_Core/Core/inc.ClassUser.php @@ -662,44 +662,108 @@ class SeedDMS_Core_User { /* {{{ */ * * This method adds another log entry to the reviews and approvals * which indicates the user has been deleted from the process. By default it will - * do so for each review/approval regardless of its current state. So even + * do so for each review/approval regardless of its current state unles + * the user has been removed already (status=-2). So even * reviews/approvals already processed by the user will be added the log - * entry. Only if the last log entry was a removal already, it will not be + * entry. Only, if the last log entry was a removal already, it will not be * added a second time. * + * This removal from processes will also take place for older versions of a document. + * + * This methode was initialy added to remove a user (which is going to be deleted + * afterwards) from all processes he or she is still involved in. + * + * If a new user is passed, then this user will be added as a new reviewer, approver, etc. + * Hence, this method does not replace the old user but actually deletes the old user and + * adds a new one. Adding the new reviewer, approver, etc. will also be done for old versions + * of a document. The same operation could be archieved by first calling + * SeedDMS_Core_DocumentVersion::delIndReviewer() followed by SeedDMS_Core_DocumentVersion::addIndReviewer() + * but this would require to do for each version of a document and the operation would not + * be in a single transaction. + * + * A new user is only added if the process (review, approval, etc.) is still in its initial + * state (have not been reviewed/approved or rejected). Unlike the removal of the user (see above). + * + * If a new user is given but has no read access on the document the transfer for that + * particular document will be skipped. Not even the removal of the user will take place. + * * @param object $user the user doing the removal (needed for entry in * review and approve log). * @param array $states remove user only from reviews/approvals in one of the states - * If passing array(0), the method will operate on reviews/approval which - * has not been touched. + * e.g. if passing array('review'=>array(0)), the method will operate on + * reviews which has not been touched yet. + * @param object user who takes over the processes * @return boolean true on success or false in case of an error */ - private function __removeFromProcesses($user, $states = array()) { /* {{{ */ + private function __removeFromProcesses($user, $states = array(), $newuser=null) { /* {{{ */ $db = $this->_dms->getDB(); + /* Get a list of all reviews, even those of older document versions */ $reviewStatus = $this->getReviewStatus(); + $db->startTransaction(); foreach ($reviewStatus["indstatus"] as $ri) { + if(!($doc = $this->_dms->getDocument($ri['documentID']))) + continue; + if($newuser && $doc->getAccessMode($newuser) < M_READ) + continue; if($ri['status'] != -2 && (!isset($states['review']) || in_array($ri['status'], $states['review']))) { $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $ri["reviewID"] ."', '-2', 'Reviewer removed from process', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; + "VALUES ('". $ri["reviewID"] ."', '-2', '".(($newuser && $ri['status'] == 0) ? 'Reviewer replaced by '.$newuser->getLogin() : 'Reviewer removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; $res=$db->getResult($queryStr); if(!$res) { + $db->rollbackTransaction(); return false; } + /* Only reviews not done already can be transferred to a new user */ + if($newuser && $ri['status'] == 0) { + if($doc = $this->_dms->getDocument($ri['documentID'])) { + if($version = $doc->getContentByVersion($ri['version'])) { + $ret = $version->addIndReviewer($newuser, $user); + /* returns -3 if the user is already a reviewer */ + if($ret === false || ($ret < 0 && $ret != -3)) { + $db->rollbackTransaction(); + return false; + } + } + } + } } } + $db->commitTransaction(); + /* Get a list of all approvals, even those of older document versions */ $approvalStatus = $this->getApprovalStatus(); + $db->startTransaction(); foreach ($approvalStatus["indstatus"] as $ai) { + if(!($doc = $this->_dms->getDocument($ai['documentID']))) + continue; + if($newuser && $doc->getAccessMode($newuser) < M_READ) + continue; if($ai['status'] != -2 && (!isset($states['approval']) || in_array($ai['status'], $states['approval']))) { $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". - "VALUES ('". $ai["approveID"] ."', '-2', 'Approver removed from process', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; + "VALUES ('". $ai["approveID"] ."', '-2', '".(($newuser && $ai['status'] == 0)? 'Approver replaced by '.$newuser->getLogin() : 'Approver removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')"; $res=$db->getResult($queryStr); if(!$res) { + $db->rollbackTransaction(); return false; } + /* Only approvals not done already can be transferred to a new user */ + if($newuser && $ai['status'] == 0) { + if($doc = $this->_dms->getDocument($ai['documentID'])) { + if($version = $doc->getContentByVersion($ai['version'])) { + $ret = $version->addIndReviewer($newuser, $user); + /* returns -3 if the user is already a reviewer */ + if($ret === false || ($ret < 0 && $ret != -3)) { + $db->rollbackTransaction(); + return false; + } + } + } + } } } + $db->commitTransaction(); + return true; } /* }}} */ @@ -711,13 +775,14 @@ class SeedDMS_Core_User { /* {{{ */ * @param object $user the user doing the removal (needed for entry in * review and approve log). * @param array $states remove user only from reviews/approvals in one of the states + * @param object user who takes over the processes * @return boolean true on success or false in case of an error */ - public function removeFromProcesses($user, $states=array()) { /* {{{ */ + public function removeFromProcesses($user, $states=array(), $newuser=null) { /* {{{ */ $db = $this->_dms->getDB(); $db->startTransaction(); - if(!$this->__removeFromProcesses($user, $states)) { + if(!$this->__removeFromProcesses($user, $states, $newuser)) { $db->rollbackTransaction(); return false; }