mirror of
https://git.code.sf.net/p/seeddms/code
synced 2025-02-06 23:24:57 +00:00
5598 lines
176 KiB
PHP
5598 lines
176 KiB
PHP
<?php
|
||
/**
|
||
* Implementation of a document in the document management system
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @license GPL2
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||
* 2010 Matteo Lucarelli, 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
|
||
/**
|
||
* The different states a document can be in
|
||
*/
|
||
/*
|
||
* Document is in review state. A document is in review state when
|
||
* it needs to be reviewed by a user or group.
|
||
*/
|
||
define("S_DRAFT_REV", 0);
|
||
|
||
/*
|
||
* Document is in approval state. A document is in approval state when
|
||
* it needs to be approved by a user or group.
|
||
*/
|
||
define("S_DRAFT_APP", 1);
|
||
|
||
/*
|
||
* Document is released. A document is in release state either when
|
||
* it needs no review or approval after uploaded or has been reviewed
|
||
* and/or approved.
|
||
*/
|
||
define("S_RELEASED", 2);
|
||
|
||
/*
|
||
* Document is in workflow. A document is in workflow if a workflow
|
||
* has been started and has not reached a final state.
|
||
*/
|
||
define("S_IN_WORKFLOW", 3);
|
||
|
||
/*
|
||
* Document was rejected. A document is in rejected state when
|
||
* the review failed or approval was not given.
|
||
*/
|
||
define("S_REJECTED", -1);
|
||
|
||
/*
|
||
* Document is obsolete. A document can be obsoleted once it was
|
||
* released.
|
||
*/
|
||
define("S_OBSOLETE", -2);
|
||
|
||
/*
|
||
* Document is expired. A document expires when the expiration date
|
||
* is reached
|
||
*/
|
||
define("S_EXPIRED", -3);
|
||
|
||
/**
|
||
* The different states a workflow log can be in. This is used in
|
||
* all tables tblDocumentXXXLog
|
||
*/
|
||
/*
|
||
* workflow is in a neutral status waiting for action of user
|
||
*/
|
||
define("S_LOG_WAITING", 0);
|
||
|
||
/*
|
||
* workflow has been successful ended. The document content has been
|
||
* approved, reviewed, aknowledged or revised
|
||
*/
|
||
define("S_LOG_ACCEPTED", 1);
|
||
|
||
/*
|
||
* workflow has been unsuccessful ended. The document content has been
|
||
* rejected
|
||
*/
|
||
define("S_LOG_REJECTED", -1);
|
||
|
||
/*
|
||
* user has been removed from workflow. This can be for different reasons
|
||
* 1. the user has been actively removed from the workflow, 2. the user has
|
||
* been deleted.
|
||
*/
|
||
define("S_LOG_USER_REMOVED", -2);
|
||
|
||
/*
|
||
* workflow is sleeping until reactivation. The workflow has been set up
|
||
* but not started. This is only valid for the revision workflow, which
|
||
* may run over and over again.
|
||
*/
|
||
define("S_LOG_SLEEPING", -3);
|
||
|
||
/**
|
||
* Class to represent a document in the document management system
|
||
*
|
||
* A document in SeedDMS is similar to files in a regular file system.
|
||
* Documents may have any number of content elements
|
||
* ({@link SeedDMS_Core_DocumentContent}). These content elements are often
|
||
* called versions ordered in a timely manner. The most recent content element
|
||
* is the current version.
|
||
*
|
||
* Documents can be linked to other documents and can have attached files.
|
||
* The document content can be anything that can be stored in a regular
|
||
* file.
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
|
||
* 2010 Matteo Lucarelli, 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_Document extends SeedDMS_Core_Object { /* {{{ */
|
||
/**
|
||
* @var string name of document
|
||
*/
|
||
protected $_name;
|
||
|
||
/**
|
||
* @var string comment of document
|
||
*/
|
||
protected $_comment;
|
||
|
||
/**
|
||
* @var integer unix timestamp of creation date
|
||
*/
|
||
protected $_date;
|
||
|
||
/**
|
||
* @var integer id of user who is the owner
|
||
*/
|
||
protected $_ownerID;
|
||
|
||
/**
|
||
* @var integer id of folder this document belongs to
|
||
*/
|
||
protected $_folderID;
|
||
|
||
/**
|
||
* @var integer timestamp of expiration date
|
||
*/
|
||
protected $_expires;
|
||
|
||
/**
|
||
* @var boolean true if access is inherited, otherwise false
|
||
*/
|
||
protected $_inheritAccess;
|
||
|
||
/**
|
||
* @var integer default access if access rights are not inherited
|
||
*/
|
||
protected $_defaultAccess;
|
||
|
||
/**
|
||
* @var array list of notifications for users and groups
|
||
*/
|
||
protected $_readAccessList;
|
||
|
||
/**
|
||
* @var array list of notifications for users and groups
|
||
*/
|
||
public $_notifyList;
|
||
|
||
/**
|
||
* @var boolean true if document is locked, otherwise false
|
||
*/
|
||
protected $_locked;
|
||
|
||
/**
|
||
* @var string list of keywords
|
||
*/
|
||
protected $_keywords;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_DocumentCategory[] list of categories
|
||
*/
|
||
protected $_categories;
|
||
|
||
/**
|
||
* @var integer position of document within the parent folder
|
||
*/
|
||
protected $_sequence;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_DocumentContent temp. storage for latestcontent
|
||
*/
|
||
protected $_latestContent;
|
||
|
||
/**
|
||
* @var array temp. storage for content
|
||
*/
|
||
protected $_content;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_Folder
|
||
*/
|
||
protected $_folder;
|
||
|
||
/** @var array of SeedDMS_Core_UserAccess and SeedDMS_Core_GroupAccess */
|
||
protected $_accessList;
|
||
|
||
function __construct($id, $name, $comment, $date, $expires, $ownerID, $folderID, $inheritAccess, $defaultAccess, $locked, $keywords, $sequence) { /* {{{ */
|
||
parent::__construct($id);
|
||
$this->_name = $name;
|
||
$this->_comment = $comment;
|
||
$this->_date = $date;
|
||
$this->_expires = $expires;
|
||
$this->_ownerID = $ownerID;
|
||
$this->_folderID = $folderID;
|
||
$this->_inheritAccess = $inheritAccess;
|
||
$this->_defaultAccess = $defaultAccess;
|
||
$this->_locked = ($locked == null || $locked == '' ? -1 : $locked);
|
||
$this->_keywords = $keywords;
|
||
$this->_sequence = $sequence;
|
||
$this->_categories = array();
|
||
$this->_notifyList = array();
|
||
$this->_latestContent = null;
|
||
$this->_content = null;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if this object is of type 'document'.
|
||
*
|
||
* @param string $type type of object
|
||
*/
|
||
public function isType($type) { /* {{{ */
|
||
return $type == 'document';
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return an array of database fields which used for searching
|
||
* a term entered in the database search form
|
||
*
|
||
* @param SeedDMS_Core_DMS $dms
|
||
* @param array $searchin integer list of search scopes (2=name, 3=comment,
|
||
* 4=attributes)
|
||
* @return array list of database fields
|
||
*/
|
||
public static function getSearchFields($dms, $searchin) { /* {{{ */
|
||
$db = $dms->getDB();
|
||
|
||
$searchFields = array();
|
||
if (in_array(1, $searchin)) {
|
||
$searchFields[] = "`tblDocuments`.`keywords`";
|
||
}
|
||
if (in_array(2, $searchin)) {
|
||
$searchFields[] = "`tblDocuments`.`name`";
|
||
}
|
||
if (in_array(3, $searchin)) {
|
||
$searchFields[] = "`tblDocuments`.`comment`";
|
||
$searchFields[] = "`tblDocumentContent`.`comment`";
|
||
}
|
||
if (in_array(4, $searchin)) {
|
||
$searchFields[] = "`tblDocumentAttributes`.`value`";
|
||
$searchFields[] = "`tblDocumentContentAttributes`.`value`";
|
||
}
|
||
if (in_array(5, $searchin)) {
|
||
$searchFields[] = $db->castToText("`tblDocuments`.`id`");
|
||
}
|
||
|
||
return $searchFields;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a folder by its database record
|
||
*
|
||
* @param array $resArr array of folder data as returned by database
|
||
* @param SeedDMS_Core_DMS $dms
|
||
* @return SeedDMS_Core_Folder|bool instance of SeedDMS_Core_Folder if document exists
|
||
*/
|
||
public static function getInstanceByData($resArr, $dms) { /* {{{ */
|
||
$classname = $dms->getClassname('document');
|
||
/** @var SeedDMS_Core_Document $document */
|
||
$document = new $classname($resArr["id"], $resArr["name"], $resArr["comment"], $resArr["date"], $resArr["expires"], $resArr["owner"], $resArr["folder"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr['lock'], $resArr["keywords"], $resArr["sequence"]);
|
||
$document->setDMS($dms);
|
||
$document = $document->applyDecorators();
|
||
return $document;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return an document by its id
|
||
*
|
||
* @param integer $id id of document
|
||
* @param SeedDMS_Core_DMS $dms
|
||
* @return bool|SeedDMS_Core_Document instance of SeedDMS_Core_Document if document exists, null
|
||
* if document does not exist, false in case of error
|
||
*/
|
||
public static function getInstance($id, $dms) { /* {{{ */
|
||
$db = $dms->getDB();
|
||
|
||
// $queryStr = "SELECT * FROM `tblDocuments` WHERE `id` = " . (int) $id;
|
||
$queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lock` FROM `tblDocuments` LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` WHERE `id` = " . (int) $id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
if (count($resArr) != 1)
|
||
return null;
|
||
$resArr = $resArr[0];
|
||
|
||
// New Locking mechanism uses a separate table to track the lock.
|
||
/*
|
||
$queryStr = "SELECT * FROM `tblDocumentLocks` WHERE `document` = " . (int) $id;
|
||
$lockArr = $db->getResultArray($queryStr);
|
||
if ((is_bool($lockArr) && $lockArr==false) || (count($lockArr)==0)) {
|
||
// Could not find a lock on the selected document.
|
||
$resArr['lock'] = -1;
|
||
}
|
||
else {
|
||
// A lock has been identified for this document.
|
||
$resArr['lock'] = $lockArr[0]["userID"];
|
||
}
|
||
*/
|
||
$resArr['lock'] = !$resArr['lock'] ? -1 : $resArr['lock'];
|
||
// print_r($resArr);exit;
|
||
|
||
return self::getInstanceByData($resArr, $dms);
|
||
|
||
$classname = $dms->getClassname('document');
|
||
/** @var SeedDMS_Core_Document $document */
|
||
$document = new $classname($resArr["id"], $resArr["name"], $resArr["comment"], $resArr["date"], $resArr["expires"], $resArr["owner"], $resArr["folder"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr['lock'], $resArr["keywords"], $resArr["sequence"]);
|
||
$document->setDMS($dms);
|
||
$document = $document->applyDecorators();
|
||
return $document;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Apply decorators
|
||
*
|
||
* @return object final object after all decorators has been applied
|
||
*/
|
||
function applyDecorators() { /* {{{ */
|
||
if($decorators = $this->_dms->getDecorators('document')) {
|
||
$s = $this;
|
||
foreach($decorators as $decorator) {
|
||
$s = new $decorator($s);
|
||
}
|
||
return $s;
|
||
} else {
|
||
return $this;
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return the directory of the document in the file system relativ
|
||
* to the contentDir
|
||
*
|
||
* @return string directory of document
|
||
*/
|
||
function getDir() { /* {{{ */
|
||
if($this->_dms->maxDirID) {
|
||
$dirid = (int) (($this->_id-1) / $this->_dms->maxDirID) + 1;
|
||
return $dirid."/".$this->_id."/";
|
||
} else {
|
||
return $this->_id."/";
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return the name of the document
|
||
*
|
||
* @return string name of document
|
||
*/
|
||
function getName() { return $this->_name; }
|
||
|
||
/**
|
||
* Set the name of the document
|
||
*
|
||
* @param $newName string new name of document
|
||
* @return bool
|
||
*/
|
||
function setName($newName) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `name` = ".$db->qstr($newName)." WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_name = $newName;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return the comment of the document
|
||
*
|
||
* @return string comment of document
|
||
*/
|
||
function getComment() { return $this->_comment; }
|
||
|
||
/**
|
||
* Set the comment of the document
|
||
*
|
||
* @param $newComment string new comment of document
|
||
* @return bool
|
||
*/
|
||
function setComment($newComment) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `comment` = ".$db->qstr($newComment)." WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_comment = $newComment;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getKeywords() { return $this->_keywords; }
|
||
|
||
/**
|
||
* @param string $newKeywords
|
||
* @return bool
|
||
*/
|
||
function setKeywords($newKeywords) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `keywords` = ".$db->qstr($newKeywords)." WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_keywords = $newKeywords;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Retrieve a list of all categories this document belongs to
|
||
*
|
||
* @return bool|SeedDMS_Core_DocumentCategory[]
|
||
*/
|
||
function getCategories() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if(!$this->_categories) {
|
||
$queryStr = "SELECT * FROM `tblCategory` where `id` in (select `categoryID` from `tblDocumentCategory` where `documentID` = ".$this->_id.")";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
foreach ($resArr as $row) {
|
||
$cat = new SeedDMS_Core_DocumentCategory($row['id'], $row['name']);
|
||
$cat->setDMS($this->_dms);
|
||
$this->_categories[] = $cat;
|
||
}
|
||
}
|
||
return $this->_categories;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set a list of categories for the document
|
||
* This function will delete currently assigned categories and sets new
|
||
* categories.
|
||
*
|
||
* @param SeedDMS_Core_DocumentCategory[] $newCategories list of category objects
|
||
* @return bool
|
||
*/
|
||
function setCategories($newCategories) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "DELETE from `tblDocumentCategory` WHERE `documentID` = ". $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
foreach($newCategories as $cat) {
|
||
$queryStr = "INSERT INTO `tblDocumentCategory` (`categoryID`, `documentID`) VALUES (". $cat->getId() .", ". $this->_id .")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
$this->_categories = $newCategories;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a list of categories to the document
|
||
* This function will add a list of new categories to the document.
|
||
*
|
||
* @param array $newCategories list of category objects
|
||
*/
|
||
function addCategories($newCategories) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if(!$this->_categories)
|
||
$this->getCategories();
|
||
|
||
$catids = array();
|
||
foreach($this->_categories as $cat)
|
||
$catids[] = $cat->getID();
|
||
|
||
$db->startTransaction();
|
||
$ncat = array(); // Array containing actually added new categories
|
||
foreach($newCategories as $cat) {
|
||
if(!in_array($cat->getID(), $catids)) {
|
||
$queryStr = "INSERT INTO `tblDocumentCategory` (`categoryID`, `documentID`) VALUES (". $cat->getId() .", ". $this->_id .")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$ncat[] = $cat;
|
||
}
|
||
}
|
||
$db->commitTransaction();
|
||
$this->_categories = array_merge($this->_categories, $ncat);
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove a list of categories from the document
|
||
* This function will remove a list of assigned categories to the document.
|
||
*
|
||
* @param array $newCategories list of category objects
|
||
*/
|
||
function removeCategories($categories) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$catids = array();
|
||
foreach($categories as $cat)
|
||
$catids[] = $cat->getID();
|
||
|
||
$queryStr = "DELETE from `tblDocumentCategory` WHERE `documentID` = ". $this->_id ." AND `categoryID` IN (".implode(',', $catids).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
return false;
|
||
}
|
||
|
||
$this->_categories = null;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return creation date of the document
|
||
*
|
||
* @return integer unix timestamp of creation date
|
||
*/
|
||
function getDate() { /* {{{ */
|
||
return $this->_date;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set creation date of the document
|
||
*
|
||
* @param integer $date timestamp of creation date. If false then set it
|
||
* to the current timestamp
|
||
* @return boolean true on success
|
||
*/
|
||
function setDate($date) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if(!$date)
|
||
$date = time();
|
||
else {
|
||
if(!is_numeric($date))
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `date` = " . (int) $date . " WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
$this->_date = $date;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check, if this document is below of a given folder
|
||
*
|
||
* @param object $folder parent folder
|
||
* @return boolean true if folder is a subfolder
|
||
*/
|
||
function isDescendant($folder) { /* {{{ */
|
||
/* First check if the parent folder is folder looking for */
|
||
if ($this->getFolder()->getID() == $folder->getID())
|
||
return true;
|
||
/* Second, check for the parent folder of this document to be
|
||
* below the given folder
|
||
*/
|
||
if($this->getFolder()->isDescendant($folder))
|
||
return true;
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return the parent folder of the document
|
||
*
|
||
* @return SeedDMS_Core_Folder parent folder
|
||
*/
|
||
function getParent() { /* {{{ */
|
||
return $this->getFolder();
|
||
} /* }}} */
|
||
|
||
function getFolder() { /* {{{ */
|
||
if (!isset($this->_folder))
|
||
$this->_folder = $this->_dms->getFolder($this->_folderID);
|
||
return $this->_folder;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set folder of a document
|
||
*
|
||
* This function basically moves a document from a folder to another
|
||
* folder.
|
||
*
|
||
* @param SeedDMS_Core_Folder $newFolder
|
||
* @return boolean false in case of an error, otherwise true
|
||
*/
|
||
function setParent($newFolder) { /* {{{ */
|
||
return $this->setFolder($newFolder);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set folder of a document
|
||
*
|
||
* This function basically moves a document from a folder to another
|
||
* folder.
|
||
*
|
||
* @param SeedDMS_Core_Folder $newFolder
|
||
* @return boolean false in case of an error, otherwise true
|
||
*/
|
||
function setFolder($newFolder) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `folder` = " . $newFolder->getID() . " WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
$this->_folderID = $newFolder->getID();
|
||
/** @noinspection PhpUndefinedFieldInspection */
|
||
$this->_folder = $newFolder;
|
||
|
||
// Make sure that the folder search path is also updated.
|
||
$path = $newFolder->getPath();
|
||
$flist = "";
|
||
/** @var SeedDMS_Core_Folder[] $path */
|
||
foreach ($path as $f) {
|
||
$flist .= ":".$f->getID();
|
||
}
|
||
if (strlen($flist)>1) {
|
||
$flist .= ":";
|
||
}
|
||
$queryStr = "UPDATE `tblDocuments` SET `folderList` = '" . $flist . "' WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return owner of document
|
||
*
|
||
* @return SeedDMS_Core_User owner of document as an instance of {@link SeedDMS_Core_User}
|
||
*/
|
||
function getOwner() { /* {{{ */
|
||
if (!isset($this->_owner))
|
||
$this->_owner = $this->_dms->getUser($this->_ownerID);
|
||
return $this->_owner;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set owner of a document
|
||
*
|
||
* @param SeedDMS_Core_User $newOwner new owner
|
||
* @return boolean true if successful otherwise false
|
||
*/
|
||
function setOwner($newOwner) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` set `owner` = " . $newOwner->getID() . " WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_ownerID = $newOwner->getID();
|
||
/** @noinspection PhpUndefinedFieldInspection */
|
||
$this->_owner = $newOwner;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return bool|int
|
||
*/
|
||
function getDefaultAccess() { /* {{{ */
|
||
if ($this->inheritsAccess()) {
|
||
$res = $this->getFolder();
|
||
if (!$res) return false;
|
||
return $this->_folder->getDefaultAccess();
|
||
}
|
||
return $this->_defaultAccess;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set default access mode
|
||
*
|
||
* This method sets the default access mode and also removes all notifiers which
|
||
* will not have read access anymore.
|
||
*
|
||
* @param integer $mode access mode
|
||
* @param bool|string $noclean set to true if notifier list shall not be clean up
|
||
* @return bool
|
||
*/
|
||
function setDefaultAccess($mode, $noclean="false") { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` set `defaultAccess` = " . (int) $mode . " WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_defaultAccess = $mode;
|
||
|
||
if(!$noclean)
|
||
$this->cleanNotifyList();
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return bool
|
||
*/
|
||
function inheritsAccess() { return $this->_inheritAccess; }
|
||
|
||
/**
|
||
* Set inherited access mode
|
||
* Setting inherited access mode will set or unset the internal flag which
|
||
* controls if the access mode is inherited from the parent folder or not.
|
||
* It will not modify the
|
||
* access control list for the current object. It will remove all
|
||
* notifications of users which do not even have read access anymore
|
||
* after setting or unsetting inherited access.
|
||
*
|
||
* @param boolean $inheritAccess set to true for setting and false for
|
||
* unsetting inherited access mode
|
||
* @param boolean $noclean set to true if notifier list shall not be clean up
|
||
* @return boolean true if operation was successful otherwise false
|
||
*/
|
||
function setInheritAccess($inheritAccess, $noclean=false) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `inheritAccess` = " . ($inheritAccess ? "1" : "0") . " WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_inheritAccess = ($inheritAccess ? "1" : "0");
|
||
|
||
if(!$noclean)
|
||
$this->cleanNotifyList();
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if document expires
|
||
*
|
||
* @return boolean true if document has expiration date set, otherwise false
|
||
*/
|
||
function expires() { /* {{{ */
|
||
if (intval($this->_expires) == 0)
|
||
return false;
|
||
else
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get expiration time of document
|
||
*
|
||
* @return integer/boolean expiration date as unix timestamp or false
|
||
*/
|
||
function getExpires() { /* {{{ */
|
||
if (intval($this->_expires) == 0)
|
||
return false;
|
||
else
|
||
return $this->_expires;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set expiration date as unix timestamp
|
||
*
|
||
* @param integer $expires unix timestamp of expiration date
|
||
* @return bool
|
||
*/
|
||
function setExpires($expires) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$expires = (!$expires) ? 0 : $expires;
|
||
|
||
if ($expires == $this->_expires) {
|
||
// No change is necessary.
|
||
return true;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `expires` = " . (int) $expires . " WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_expires = $expires;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if the document has expired
|
||
*
|
||
* The method expects to database field 'expired' to hold the timestamp
|
||
* of the start of day at which end the document expires. The document will
|
||
* expire if that day is over. Hence, a document will *not*
|
||
* be expired during the day of expiration but at the end of that day
|
||
*
|
||
* @return boolean true if document has expired otherwise false
|
||
*/
|
||
function hasExpired() { /* {{{ */
|
||
if (intval($this->_expires) == 0) return false;
|
||
if (time()>=$this->_expires+24*60*60) return true;
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if the document has expired and set the status accordingly
|
||
* It will also recalculate the status if the current status is
|
||
* set to S_EXPIRED but the document isn't actually expired.
|
||
* The method will update the document status log database table
|
||
* if needed.
|
||
* FIXME: some left over reviewers/approvers are in the way if
|
||
* no workflow is set and traditional workflow mode is on. In that
|
||
* case the status is set to S_DRAFT_REV or S_DRAFT_APP
|
||
*
|
||
* @return boolean true if status has changed
|
||
*/
|
||
function verifyLastestContentExpriry(){ /* {{{ */
|
||
$lc=$this->getLatestContent();
|
||
if($lc) {
|
||
$st=$lc->getStatus();
|
||
|
||
if (($st["status"]==S_DRAFT_REV || $st["status"]==S_DRAFT_APP || $st["status"]==S_IN_WORKFLOW || $st["status"]==S_RELEASED) && $this->hasExpired()){
|
||
return $lc->setStatus(S_EXPIRED,"", $this->getOwner());
|
||
}
|
||
elseif ($st["status"]==S_EXPIRED && !$this->hasExpired() ){
|
||
$lc->verifyStatus(true, $this->getOwner());
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if document is locked
|
||
*
|
||
* @return boolean true if locked otherwise false
|
||
*/
|
||
function isLocked() { return $this->_locked != -1; }
|
||
|
||
/**
|
||
* Lock or unlock document
|
||
*
|
||
* @param SeedDMS_Core_User|bool $falseOrUser user object for locking or false for unlocking
|
||
* @return boolean true if operation was successful otherwise false
|
||
*/
|
||
function setLocked($falseOrUser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$lockUserID = -1;
|
||
if (is_bool($falseOrUser) && !$falseOrUser) {
|
||
$queryStr = "DELETE FROM `tblDocumentLocks` WHERE `document` = ".$this->_id;
|
||
}
|
||
else if (is_object($falseOrUser)) {
|
||
$queryStr = "INSERT INTO `tblDocumentLocks` (`document`, `userID`) VALUES (".$this->_id.", ".$falseOrUser->getID().")";
|
||
$lockUserID = $falseOrUser->getID();
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
if (!$db->getResult($queryStr)) {
|
||
return false;
|
||
}
|
||
unset($this->_lockingUser);
|
||
$this->_locked = $lockUserID;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the user currently locking the document
|
||
*
|
||
* @return SeedDMS_Core_User|bool user have a lock
|
||
*/
|
||
function getLockingUser() { /* {{{ */
|
||
if (!$this->isLocked())
|
||
return false;
|
||
|
||
if (!isset($this->_lockingUser))
|
||
$this->_lockingUser = $this->_dms->getUser($this->_locked);
|
||
return $this->_lockingUser;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return float
|
||
*/
|
||
function getSequence() { return $this->_sequence; }
|
||
|
||
/**
|
||
* @param float $seq
|
||
* @return bool
|
||
*/
|
||
function setSequence($seq) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocuments` SET `sequence` = " . $seq . " WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_sequence = $seq;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Delete all entries for this document from the access control list
|
||
*
|
||
* @param boolean $noclean set to true if notifier list shall not be clean up
|
||
* @return boolean true if operation was successful otherwise false
|
||
*/
|
||
function clearAccessList($noclean=false) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = " . T_DOCUMENT . " AND `target` = " . $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset($this->_accessList);
|
||
|
||
if(!$noclean)
|
||
$this->cleanNotifyList();
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of access privileges
|
||
*
|
||
* If the document inherits the access privileges from the parent folder
|
||
* those will be returned.
|
||
* $mode and $op can be set to restrict the list of returned access
|
||
* privileges. If $mode is set to M_ANY no restriction will apply
|
||
* regardless of the value of $op. The returned array contains a list
|
||
* of {@link SeedDMS_Core_UserAccess} and
|
||
* {@link SeedDMS_Core_GroupAccess} objects. Even if the document
|
||
* has no access list the returned array contains the two elements
|
||
* 'users' and 'groups' which are than empty. The methode returns false
|
||
* if the function fails.
|
||
*
|
||
* @param int $mode access mode (defaults to M_ANY)
|
||
* @param int|string $op operation (defaults to O_EQ)
|
||
* @return bool|array
|
||
*/
|
||
function getAccessList($mode = M_ANY, $op = O_EQ) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if ($this->inheritsAccess()) {
|
||
$res = $this->getFolder();
|
||
if (!$res) return false;
|
||
return $this->_folder->getAccessList($mode, $op);
|
||
}
|
||
|
||
if (!isset($this->_accessList[$mode])) {
|
||
if ($op!=O_GTEQ && $op!=O_LTEQ && $op!=O_EQ) {
|
||
return false;
|
||
}
|
||
$modeStr = "";
|
||
if ($mode!=M_ANY) {
|
||
$modeStr = " AND mode".$op.(int)$mode;
|
||
}
|
||
$queryStr = "SELECT * FROM `tblACLs` WHERE `targetType` = ".T_DOCUMENT.
|
||
" AND target = " . $this->_id . $modeStr . " ORDER BY `targetType`";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$this->_accessList[$mode] = array("groups" => array(), "users" => array());
|
||
foreach ($resArr as $row) {
|
||
if ($row["userID"] != -1)
|
||
array_push($this->_accessList[$mode]["users"], new SeedDMS_Core_UserAccess($this->_dms->getUser($row["userID"]), $row["mode"]));
|
||
else //if ($row["groupID"] != -1)
|
||
array_push($this->_accessList[$mode]["groups"], new SeedDMS_Core_GroupAccess($this->_dms->getGroup($row["groupID"]), $row["mode"]));
|
||
}
|
||
}
|
||
|
||
return $this->_accessList[$mode];
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add access right to folder
|
||
* This function may change in the future. Instead of passing the a flag
|
||
* and a user/group id a user or group object will be expected.
|
||
*
|
||
* @param integer $mode access mode
|
||
* @param integer $userOrGroupID id of user or group
|
||
* @param integer $isUser set to 1 if $userOrGroupID is the id of a
|
||
* user
|
||
* @return bool
|
||
*/
|
||
function addAccess($mode, $userOrGroupID, $isUser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$userOrGroup = ($isUser) ? "`userID`" : "`groupID`";
|
||
|
||
$queryStr = "INSERT INTO `tblACLs` (`target`, `targetType`, ".$userOrGroup.", `mode`) VALUES
|
||
(".$this->_id.", ".T_DOCUMENT.", " . (int) $userOrGroupID . ", " .(int) $mode. ")";
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset($this->_accessList);
|
||
|
||
// Update the notify list, if necessary.
|
||
if ($mode == M_NONE) {
|
||
$this->removeNotify($userOrGroupID, $isUser);
|
||
}
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Change access right of document
|
||
* This function may change in the future. Instead of passing the a flag
|
||
* and a user/group id a user or group object will be expected.
|
||
*
|
||
* @param integer $newMode access mode
|
||
* @param integer $userOrGroupID id of user or group
|
||
* @param integer $isUser set to 1 if $userOrGroupID is the id of a
|
||
* user
|
||
* @return bool
|
||
*/
|
||
function changeAccess($newMode, $userOrGroupID, $isUser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$userOrGroup = ($isUser) ? "`userID`" : "`groupID`";
|
||
|
||
$queryStr = "UPDATE `tblACLs` SET `mode` = " . (int) $newMode . " WHERE `targetType` = ".T_DOCUMENT." AND `target` = " . $this->_id . " AND " . $userOrGroup . " = " . (int) $userOrGroupID;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset($this->_accessList);
|
||
|
||
// Update the notify list, if necessary.
|
||
if ($newMode == M_NONE) {
|
||
$this->removeNotify($userOrGroupID, $isUser);
|
||
}
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove access rights for a user or group
|
||
*
|
||
* @param integer $userOrGroupID ID of user or group
|
||
* @param boolean $isUser true if $userOrGroupID is a user id, false if it
|
||
* is a group id.
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function removeAccess($userOrGroupID, $isUser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$userOrGroup = ($isUser) ? "`userID`" : "`groupID`";
|
||
|
||
$queryStr = "DELETE FROM `tblACLs` WHERE `targetType` = ".T_DOCUMENT." AND `target` = ".$this->_id." AND ".$userOrGroup." = " . (int) $userOrGroupID;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset($this->_accessList);
|
||
|
||
// Update the notify list, if the user looses access rights.
|
||
$mode = ($isUser ? $this->getAccessMode($this->_dms->getUser($userOrGroupID)) : $this->getGroupAccessMode($this->_dms->getGroup($userOrGroupID)));
|
||
if ($mode == M_NONE) {
|
||
$this->removeNotify($userOrGroupID, $isUser);
|
||
}
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns the greatest access privilege for a given user
|
||
*
|
||
* This function returns the access mode for a given user. An administrator
|
||
* and the owner of the folder has unrestricted access. A guest user has
|
||
* read only access or no access if access rights are further limited
|
||
* by access control lists. All other users have access rights according
|
||
* to the access control lists or the default access. This function will
|
||
* recursive check for access rights of parent folders if access rights
|
||
* are inherited.
|
||
*
|
||
* The function searches the access control list for entries of
|
||
* user $user. If it finds more than one entry it will return the
|
||
* one allowing the greatest privileges, but user rights will always
|
||
* precede group rights. If there is no entry in the
|
||
* access control list, it will return the default access mode.
|
||
* The function takes inherited access rights into account.
|
||
* For a list of possible access rights see @file inc.AccessUtils.php
|
||
*
|
||
* Having access on a document does not necessarily mean the document
|
||
* content is accessible too. Accessing the content is checked by
|
||
* {@link SeedDMS_Core_DocumentContent::getAccessMode()} which calls
|
||
* a callback function defined by the application. If the callback
|
||
* function is not set, access on the content is always granted.
|
||
*
|
||
* Before checking the access in the method itself a callback 'onCheckAccessDocument'
|
||
* is called. If it returns a value > 0, then this will be returned by this
|
||
* method without any further checks. The optional paramater $context
|
||
* will be passed as a third parameter to the callback. It contains
|
||
* the operation for which the access mode is retrieved. It is for example
|
||
* set to 'removeDocument' if the access mode is used to check for sufficient
|
||
* permission on deleting a document.
|
||
*
|
||
* @param $user object instance of class SeedDMS_Core_User
|
||
* @param string $context context in which the access mode is requested
|
||
* @return integer access mode
|
||
*/
|
||
function getAccessMode($user, $context='') { /* {{{ */
|
||
if(!$user)
|
||
return M_NONE;
|
||
|
||
/* Check if 'onCheckAccessDocument' callback is set */
|
||
if(isset($this->_dms->callbacks['onCheckAccessDocument'])) {
|
||
foreach($this->_dms->callbacks['onCheckAccessDocument'] as $callback) {
|
||
if(($ret = call_user_func($callback[0], $callback[1], $this, $user, $context)) > 0) {
|
||
return $ret;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Administrators have unrestricted access */
|
||
if ($user->isAdmin()) return M_ALL;
|
||
|
||
/* The owner of the document has unrestricted access */
|
||
if ($user->getID() == $this->_ownerID) return M_ALL;
|
||
|
||
/* Check ACLs */
|
||
$accessList = $this->getAccessList();
|
||
if (!$accessList) return false;
|
||
|
||
/** @var SeedDMS_Core_UserAccess $userAccess */
|
||
foreach ($accessList["users"] as $userAccess) {
|
||
if ($userAccess->getUserID() == $user->getID()) {
|
||
$mode = $userAccess->getMode();
|
||
if ($user->isGuest()) {
|
||
if ($mode >= M_READ) $mode = M_READ;
|
||
}
|
||
return $mode;
|
||
}
|
||
}
|
||
|
||
/* Get the highest right defined by a group */
|
||
if($accessList['groups']) {
|
||
$mode = 0;
|
||
/** @var SeedDMS_Core_GroupAccess $groupAccess */
|
||
foreach ($accessList["groups"] as $groupAccess) {
|
||
if ($user->isMemberOfGroup($groupAccess->getGroup())) {
|
||
if ($groupAccess->getMode() > $mode)
|
||
$mode = $groupAccess->getMode();
|
||
}
|
||
}
|
||
if($mode) {
|
||
if ($user->isGuest()) {
|
||
if ($mode >= M_READ) $mode = M_READ;
|
||
}
|
||
return $mode;
|
||
}
|
||
}
|
||
|
||
$mode = $this->getDefaultAccess();
|
||
if ($user->isGuest()) {
|
||
if ($mode >= M_READ) $mode = M_READ;
|
||
}
|
||
return $mode;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns the greatest access privilege for a given group
|
||
*
|
||
* This function searches the access control list for entries of
|
||
* group $group. If it finds more than one entry it will return the
|
||
* one allowing the greatest privileges. If there is no entry in the
|
||
* access control list, it will return the default access mode.
|
||
* The function takes inherited access rights into account.
|
||
* For a list of possible access rights see @file inc.AccessUtils.php
|
||
*
|
||
* @param SeedDMS_Core_Group $group object instance of class SeedDMS_Core_Group
|
||
* @return integer access mode
|
||
*/
|
||
function getGroupAccessMode($group) { /* {{{ */
|
||
$highestPrivileged = M_NONE;
|
||
|
||
//ACLs durchforsten
|
||
$foundInACL = false;
|
||
$accessList = $this->getAccessList();
|
||
if (!$accessList)
|
||
return false;
|
||
|
||
/** @var SeedDMS_Core_GroupAccess $groupAccess */
|
||
foreach ($accessList["groups"] as $groupAccess) {
|
||
if ($groupAccess->getGroupID() == $group->getID()) {
|
||
$foundInACL = true;
|
||
if ($groupAccess->getMode() > $highestPrivileged)
|
||
$highestPrivileged = $groupAccess->getMode();
|
||
if ($highestPrivileged == M_ALL) // max access right -> skip the rest
|
||
return $highestPrivileged;
|
||
}
|
||
}
|
||
|
||
if ($foundInACL)
|
||
return $highestPrivileged;
|
||
|
||
//Standard-Berechtigung verwenden
|
||
return $this->getDefaultAccess();
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of all notifications
|
||
*
|
||
* The returned list has two elements called 'users' and 'groups'. Each one
|
||
* is an array itself countaining objects of class SeedDMS_Core_User and
|
||
* SeedDMS_Core_Group.
|
||
*
|
||
* @param integer $type type of notification (not yet used)
|
||
* @param bool $incdisabled set to true if disabled user shall be included
|
||
* @return array|bool
|
||
*/
|
||
function getNotifyList($type=0, $incdisabled=false) { /* {{{ */
|
||
if (empty($this->_notifyList)) {
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr ="SELECT * FROM `tblNotify` WHERE `targetType` = " . T_DOCUMENT . " AND `target` = " . $this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
$this->_notifyList = array("groups" => array(), "users" => array());
|
||
foreach ($resArr as $row)
|
||
{
|
||
if ($row["userID"] != -1) {
|
||
$u = $this->_dms->getUser($row["userID"]);
|
||
if($u && (!$u->isDisabled() || $incdisabled))
|
||
array_push($this->_notifyList["users"], $u);
|
||
} else { //if ($row["groupID"] != -1)
|
||
$g = $this->_dms->getGroup($row["groupID"]);
|
||
if($g)
|
||
array_push($this->_notifyList["groups"], $g);
|
||
}
|
||
}
|
||
}
|
||
return $this->_notifyList;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Make sure only users/groups with read access are in the notify list
|
||
*
|
||
*/
|
||
function cleanNotifyList() { /* {{{ */
|
||
// If any of the notification subscribers no longer have read access,
|
||
// remove their subscription.
|
||
if (empty($this->_notifyList))
|
||
$this->getNotifyList();
|
||
|
||
/* Make a copy of both notifier lists because removeNotify will empty
|
||
* $this->_notifyList and the second foreach will not work anymore.
|
||
*/
|
||
/** @var SeedDMS_Core_User[] $nusers */
|
||
$nusers = $this->_notifyList["users"];
|
||
/** @var SeedDMS_Core_Group[] $ngroups */
|
||
$ngroups = $this->_notifyList["groups"];
|
||
foreach ($nusers as $u) {
|
||
if ($this->getAccessMode($u) < M_READ) {
|
||
$this->removeNotify($u->getID(), true);
|
||
}
|
||
}
|
||
foreach ($ngroups as $g) {
|
||
if ($this->getGroupAccessMode($g) < M_READ) {
|
||
$this->removeNotify($g->getID(), false);
|
||
}
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a user/group to the notification list
|
||
* This function does not check if the currently logged in user
|
||
* is allowed to add a notification. This must be checked by the calling
|
||
* application.
|
||
*
|
||
* @param $userOrGroupID integer id of user or group to add
|
||
* @param $isUser integer 1 if $userOrGroupID is a user,
|
||
* 0 if $userOrGroupID is a group
|
||
* @return integer 0: Update successful.
|
||
* -1: Invalid User/Group ID.
|
||
* -2: Target User / Group does not have read access.
|
||
* -3: User is already subscribed.
|
||
* -4: Database / internal error.
|
||
*/
|
||
function addNotify($userOrGroupID, $isUser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$userOrGroup = ($isUser ? "`userID`" : "`groupID`");
|
||
|
||
/* Verify that user / group exists. */
|
||
$obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID));
|
||
if (!is_object($obj)) {
|
||
return -1;
|
||
}
|
||
|
||
/* Verify that the requesting user has permission to add the target to
|
||
* the notification system.
|
||
*/
|
||
/*
|
||
* The calling application should enforce the policy on who is allowed
|
||
* to add someone to the notification system. If is shall remain here
|
||
* the currently logged in user should be passed to this function
|
||
*
|
||
GLOBAL $user;
|
||
if ($user->isGuest()) {
|
||
return -2;
|
||
}
|
||
if (!$user->isAdmin()) {
|
||
if ($isUser) {
|
||
if ($user->getID() != $obj->getID()) {
|
||
return -2;
|
||
}
|
||
}
|
||
else {
|
||
if (!$obj->isMember($user)) {
|
||
return -2;
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
|
||
/* Verify that target user / group has read access to the document. */
|
||
if ($isUser) {
|
||
// Users are straightforward to check.
|
||
if ($this->getAccessMode($obj) < M_READ) {
|
||
return -2;
|
||
}
|
||
}
|
||
else {
|
||
// Groups are a little more complex.
|
||
if ($this->getDefaultAccess() >= M_READ) {
|
||
// If the default access is at least READ-ONLY, then just make sure
|
||
// that the current group has not been explicitly excluded.
|
||
$acl = $this->getAccessList(M_NONE, O_EQ);
|
||
$found = false;
|
||
/** @var SeedDMS_Core_GroupAccess $group */
|
||
foreach ($acl["groups"] as $group) {
|
||
if ($group->getGroupID() == $userOrGroupID) {
|
||
$found = true;
|
||
break;
|
||
}
|
||
}
|
||
if ($found) {
|
||
return -2;
|
||
}
|
||
}
|
||
else {
|
||
// The default access is restricted. Make sure that the group has
|
||
// been explicitly allocated access to the document.
|
||
$acl = $this->getAccessList(M_READ, O_GTEQ);
|
||
if (is_bool($acl)) {
|
||
return -4;
|
||
}
|
||
$found = false;
|
||
/** @var SeedDMS_Core_GroupAccess $group */
|
||
foreach ($acl["groups"] as $group) {
|
||
if ($group->getGroupID() == $userOrGroupID) {
|
||
$found = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!$found) {
|
||
return -2;
|
||
}
|
||
}
|
||
}
|
||
/* Check to see if user/group is already on the list. */
|
||
$queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ".
|
||
"AND `tblNotify`.`targetType` = '".T_DOCUMENT."' ".
|
||
"AND `tblNotify`.".$userOrGroup." = '".(int) $userOrGroupID."'";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr)) {
|
||
return -4;
|
||
}
|
||
if (count($resArr)>0) {
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblNotify` (`target`, `targetType`, " . $userOrGroup . ") VALUES (" . $this->_id . ", " . T_DOCUMENT . ", " . (int) $userOrGroupID . ")";
|
||
if (!$db->getResult($queryStr))
|
||
return -4;
|
||
|
||
unset($this->_notifyList);
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove a user or group from the notification list
|
||
* This function does not check if the currently logged in user
|
||
* is allowed to remove a notification. This must be checked by the calling
|
||
* application.
|
||
*
|
||
* @param integer $userOrGroupID id of user or group
|
||
* @param boolean $isUser boolean true if a user is passed in $userOrGroupID, false
|
||
* if a group is passed in $userOrGroupID
|
||
* @param integer $type type of notification (0 will delete all) Not used yet!
|
||
* @return integer 0 if operation was succesful
|
||
* -1 if the userid/groupid is invalid
|
||
* -3 if the user/group is already subscribed
|
||
* -4 in case of an internal database error
|
||
*/
|
||
function removeNotify($userOrGroupID, $isUser, $type=0) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
/* Verify that user / group exists. */
|
||
/** @var SeedDMS_Core_Group|SeedDMS_Core_User $obj */
|
||
$obj = ($isUser ? $this->_dms->getUser($userOrGroupID) : $this->_dms->getGroup($userOrGroupID));
|
||
if (!is_object($obj)) {
|
||
return -1;
|
||
}
|
||
|
||
$userOrGroup = ($isUser) ? "`userID`" : "`groupID`";
|
||
|
||
/* Verify that the requesting user has permission to add the target to
|
||
* the notification system.
|
||
*/
|
||
/*
|
||
* The calling application should enforce the policy on who is allowed
|
||
* to add someone to the notification system. If is shall remain here
|
||
* the currently logged in user should be passed to this function
|
||
*
|
||
GLOBAL $user;
|
||
if ($user->isGuest()) {
|
||
return -2;
|
||
}
|
||
if (!$user->isAdmin()) {
|
||
if ($isUser) {
|
||
if ($user->getID() != $obj->getID()) {
|
||
return -2;
|
||
}
|
||
}
|
||
else {
|
||
if (!$obj->isMember($user)) {
|
||
return -2;
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
|
||
/* Check to see if the target is in the database. */
|
||
$queryStr = "SELECT * FROM `tblNotify` WHERE `tblNotify`.`target` = '".$this->_id."' ".
|
||
"AND `tblNotify`.`targetType` = '".T_DOCUMENT."' ".
|
||
"AND `tblNotify`.".$userOrGroup." = '".(int) $userOrGroupID."'";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr)) {
|
||
return -4;
|
||
}
|
||
if (count($resArr)==0) {
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblNotify` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT . " AND " . $userOrGroup . " = " . (int) $userOrGroupID;
|
||
/* If type is given then delete only those notifications */
|
||
if($type)
|
||
$queryStr .= " AND `type` = ".(int) $type;
|
||
if (!$db->getResult($queryStr))
|
||
return -4;
|
||
|
||
unset($this->_notifyList);
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add content to a document
|
||
*
|
||
* Each document may have any number of content elements attached to it.
|
||
* Each content element has a version number. Newer versions (greater
|
||
* version number) replace older versions.
|
||
*
|
||
* @param string $comment comment
|
||
* @param object $user user who shall be the owner of this content
|
||
* @param string $tmpFile file containing the actuall content
|
||
* @param string $orgFileName original file name
|
||
* @param string $fileType
|
||
* @param string $mimeType MimeType of the content
|
||
* @param array $reviewers list of reviewers
|
||
* @param array $approvers list of approvers
|
||
* @param integer $version version number of content or 0 if next higher version shall be used.
|
||
* @param array $attributes list of version attributes. The element key
|
||
* must be the id of the attribute definition.
|
||
* @param object $workflow
|
||
* @return bool|SeedDMS_Core_AddContentResultSet
|
||
*/
|
||
function addContent($comment, $user, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers=array(), $approvers=array(), $version=0, $attributes=array(), $workflow=null) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
// the doc path is id/version.filetype
|
||
$dir = $this->getDir();
|
||
|
||
/* The version field in table tblDocumentContent used to be auto
|
||
* increment but that requires the field to be primary as well if
|
||
* innodb is used. That's why the version is now determined here.
|
||
*/
|
||
if ((int)$version<1) {
|
||
$queryStr = "SELECT MAX(`version`) as m from `tblDocumentContent` where `document` = ".$this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$version = $resArr[0]['m']+1;
|
||
}
|
||
|
||
if($fileType == '.')
|
||
$fileType = '';
|
||
$filesize = SeedDMS_Core_File::fileSize($tmpFile);
|
||
$checksum = SeedDMS_Core_File::checksum($tmpFile);
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "INSERT INTO `tblDocumentContent` (`document`, `version`, `comment`, `date`, `createdBy`, `dir`, `orgFileName`, `fileType`, `mimeType`, `fileSize`, `checksum`) VALUES ".
|
||
"(".$this->_id.", ".(int)$version.",".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".$user->getID().", ".$db->qstr($dir).", ".$db->qstr($orgFileName).", ".$db->qstr($fileType).", ".$db->qstr($mimeType).", ".$filesize.", ".$db->qstr($checksum).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$contentID = $db->getInsertID('tblDocumentContent');
|
||
|
||
// copy file
|
||
if (!SeedDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
if($this->_dms->forceRename)
|
||
$err = SeedDMS_Core_File::renameFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType);
|
||
else
|
||
$err = SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType);
|
||
if (!$err) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$this->_content = null;
|
||
$this->_latestContent = null;
|
||
$content = $this->getLatestContent($contentID); /** @todo: Parameter not defined in Funktion */
|
||
$docResultSet = new SeedDMS_Core_AddContentResultSet($content);
|
||
$docResultSet->setDMS($this->_dms);
|
||
|
||
if($attributes) {
|
||
foreach($attributes as $attrdefid=>$attribute) {
|
||
/* $attribute can be a string or an array */
|
||
if($attribute)
|
||
if(!$content->setAttributeValue($this->_dms->getAttributeDefinition($attrdefid), $attribute)) {
|
||
$this->_removeContent($content);
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentStatus` (`documentID`, `version`) ".
|
||
"VALUES (". $this->_id .", ". (int) $version .")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$this->_removeContent($content);
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$statusID = $db->getInsertID('tblDocumentStatus', 'statusID');
|
||
|
||
if($workflow)
|
||
$content->setWorkflow($workflow, $user);
|
||
|
||
// Add reviewers into the database. Reviewers must review the document
|
||
// and submit comments, if appropriate. Reviewers can also recommend that
|
||
// a document be rejected.
|
||
$pendingReview=false;
|
||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||
foreach (array("i", "g") as $i){
|
||
if (isset($reviewers[$i])) {
|
||
foreach ($reviewers[$i] as $reviewerID) {
|
||
$reviewer=($i=="i" ?$this->_dms->getUser($reviewerID) : $this->_dms->getGroup($reviewerID));
|
||
$res = ($i=="i" ? $docResultSet->getContent()->addIndReviewer($reviewer, $user, true) : $docResultSet->getContent()->addGrpReviewer($reviewer, $user, true));
|
||
$docResultSet->addReviewer($reviewer, $i, $res);
|
||
// If no error is returned, or if the error is just due to email
|
||
// failure, mark the state as "pending review".
|
||
if ($res==0 || $res=-3 || $res=-4) {
|
||
$pendingReview=true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Add approvers to the database. Approvers must also review the document
|
||
// and make a recommendation on its release as an approved version.
|
||
$pendingApproval=false;
|
||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||
foreach (array("i", "g") as $i){
|
||
if (isset($approvers[$i])) {
|
||
foreach ($approvers[$i] as $approverID) {
|
||
$approver=($i=="i" ? $this->_dms->getUser($approverID) : $this->_dms->getGroup($approverID));
|
||
$res=($i=="i" ? $docResultSet->getContent()->addIndApprover($approver, $user, true) : $docResultSet->getContent()->addGrpApprover($approver, $user, !$pendingReview));
|
||
$docResultSet->addApprover($approver, $i, $res);
|
||
if ($res==0 || $res=-3 || $res=-4) {
|
||
$pendingApproval=true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// If there are no reviewers or approvers, the document is automatically
|
||
// promoted to the released state.
|
||
if ($pendingReview) {
|
||
$status = S_DRAFT_REV;
|
||
$comment = "";
|
||
}
|
||
elseif ($pendingApproval) {
|
||
$status = S_DRAFT_APP;
|
||
$comment = "";
|
||
}
|
||
elseif($workflow) {
|
||
$status = S_IN_WORKFLOW;
|
||
$comment = ", workflow: ".$workflow->getName();
|
||
} else {
|
||
$status = S_RELEASED;
|
||
$comment = "";
|
||
}
|
||
$queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $statusID ."', '". $status."', 'New document content submitted". $comment ."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||
$docResultSet->setStatus($status);
|
||
|
||
$db->commitTransaction();
|
||
return $docResultSet;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Replace a version of a document
|
||
*
|
||
* Each document may have any number of content elements attached to it.
|
||
* This function replaces the file content of a given version.
|
||
* Using this function is highly discourage, because it undermines the
|
||
* idea of keeping all versions of a document as originally saved.
|
||
* Content will only be replaced if the mimetype, filetype, user and
|
||
* original filename are identical to the version being updated.
|
||
*
|
||
* This function was introduced for the webdav server because any saving
|
||
* of a document created a new version.
|
||
*
|
||
* @param object $user user who shall be the owner of this content
|
||
* @param string $tmpFile file containing the actuall content
|
||
* @param string $orgFileName original file name
|
||
* @param string $fileType
|
||
* @param string $mimeType MimeType of the content
|
||
* @param integer $version version number of content or 0 if next higher version shall be used.
|
||
* @return bool/array false in case of an error or a result set
|
||
*/
|
||
function replaceContent($version, $user, $tmpFile, $orgFileName, $fileType, $mimeType) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
// the doc path is id/version.filetype
|
||
$dir = $this->getDir();
|
||
|
||
/* If $version < 1 than replace the content of the latest version.
|
||
*/
|
||
if ((int) $version<1) {
|
||
$queryStr = "SELECT MAX(`version`) as m from `tblDocumentContent` where `document` = ".$this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$version = $resArr[0]['m'];
|
||
}
|
||
|
||
$content = $this->getContentByVersion($version);
|
||
if(!$content)
|
||
return false;
|
||
|
||
if($fileType == '.')
|
||
$fileType = '';
|
||
|
||
/* Check if $user, $orgFileName, $fileType and $mimeType are the same */
|
||
if($user->getID() != $content->getUser()->getID()) {
|
||
return false;
|
||
}
|
||
if($orgFileName != $content->getOriginalFileName()) {
|
||
return false;
|
||
}
|
||
if($fileType != $content->getFileType()) {
|
||
return false;
|
||
}
|
||
if($mimeType != $content->getMimeType()) {
|
||
return false;
|
||
}
|
||
|
||
$filesize = SeedDMS_Core_File::fileSize($tmpFile);
|
||
$checksum = SeedDMS_Core_File::checksum($tmpFile);
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "UPDATE `tblDocumentContent` set `date`=".$db->getCurrentTimestamp().", `fileSize`=".$filesize.", `checksum`=".$db->qstr($checksum)." WHERE `id`=".$content->getID();
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
// copy file
|
||
if (!SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$this->_content = null;
|
||
$this->_latestContent = null;
|
||
$db->commitTransaction();
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return all content elements of a document
|
||
*
|
||
* This functions returns an array of content elements ordered by version.
|
||
* Version which are not accessible because of its status, will be filtered
|
||
* out. Access rights based on the document status are calculated for the
|
||
* currently logged in user.
|
||
*
|
||
* @return bool|SeedDMS_Core_DocumentContent[]
|
||
*/
|
||
function getContent() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!isset($this->_content)) {
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version`";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$this->_content = array();
|
||
$classname = $this->_dms->getClassname('documentcontent');
|
||
$user = $this->_dms->getLoggedInUser();
|
||
foreach ($resArr as $row) {
|
||
/** @var SeedDMS_Core_DocumentContent $content */
|
||
$content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']);
|
||
/* TODO: Better use content id as key in $this->_content. This
|
||
* would allow to remove a single content object in removeContent().
|
||
* Currently removeContent() must clear $this->_content completely
|
||
*/
|
||
if($user) {
|
||
if($content->getAccessMode($user) >= M_READ)
|
||
array_push($this->_content, $content);
|
||
} else {
|
||
array_push($this->_content, $content);
|
||
}
|
||
}
|
||
}
|
||
|
||
return $this->_content;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return the content element of a document with a given version number
|
||
*
|
||
* This function will check if the version is accessible and return false
|
||
* if not. Access rights based on the document status are calculated for the
|
||
* currently logged in user.
|
||
*
|
||
* @param integer $version version number of content element
|
||
* @return SeedDMS_Core_DocumentContent|boolean object of class {@link SeedDMS_Core_DocumentContent}
|
||
* or false
|
||
*/
|
||
function getContentByVersion($version) { /* {{{ */
|
||
if (!is_numeric($version)) return false;
|
||
|
||
if (isset($this->_content)) {
|
||
foreach ($this->_content as $revision) {
|
||
if ($revision->getVersion() == $version)
|
||
return $revision;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
$db = $this->_dms->getDB();
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." AND `version` = " . (int) $version;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
if (count($resArr) != 1)
|
||
return false;
|
||
|
||
$resArr = $resArr[0];
|
||
$classname = $this->_dms->getClassname('documentcontent');
|
||
/** @var SeedDMS_Core_DocumentContent $content */
|
||
if($content = new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum'])) {
|
||
$user = $this->_dms->getLoggedInUser();
|
||
/* A user with write access on the document may always see the version */
|
||
if($user && $content->getAccessMode($user) == M_NONE)
|
||
return false;
|
||
else
|
||
return $content;
|
||
} else {
|
||
return false;
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if a given version is the latest version of the document
|
||
*
|
||
* @param integer $version version number of content element
|
||
* @return SeedDMS_Core_DocumentContent|boolean object of class {@link SeedDMS_Core_DocumentContent}
|
||
* or false
|
||
*/
|
||
function isLatestContent($version) { /* {{{ */
|
||
return $this->getLatestContent()->getVersion() == $version;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return bool|null|SeedDMS_Core_DocumentContent
|
||
*/
|
||
function __getLatestContent() { /* {{{ */
|
||
if (!$this->_latestContent) {
|
||
$db = $this->_dms->getDB();
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC LIMIT 1";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
if (count($resArr) != 1)
|
||
return false;
|
||
|
||
$resArr = $resArr[0];
|
||
$classname = $this->_dms->getClassname('documentcontent');
|
||
$this->_latestContent = new $classname($resArr["id"], $this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"], $resArr['fileSize'], $resArr['checksum']);
|
||
}
|
||
return $this->_latestContent;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the latest version of document
|
||
*
|
||
* This function returns the latest accessible version of a document.
|
||
* If content access has been restricted by setting
|
||
* {@link SeedDMS_Core_DMS::noReadForStatus} the function will go
|
||
* backwards in history until an accessible version is found. If none
|
||
* is found null will be returned.
|
||
* Access rights based on the document status are calculated for the
|
||
* currently logged in user.
|
||
*
|
||
* @return bool|SeedDMS_Core_DocumentContent object of class {@link SeedDMS_Core_DocumentContent}
|
||
*/
|
||
function getLatestContent() { /* {{{ */
|
||
if (!$this->_latestContent) {
|
||
$db = $this->_dms->getDB();
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = ".$this->_id." ORDER BY `version` DESC";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$classname = $this->_dms->getClassname('documentcontent');
|
||
$user = $this->_dms->getLoggedInUser();
|
||
foreach ($resArr as $row) {
|
||
if (!$this->_latestContent) {
|
||
/** @var SeedDMS_Core_DocumentContent $content */
|
||
$content = new $classname($row["id"], $this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']);
|
||
if($user) {
|
||
/* If the user may even write the document, then also allow to see all content.
|
||
* This is needed because the user could upload a new version
|
||
*/
|
||
if($content->getAccessMode($user) >= M_READ) {
|
||
$this->_latestContent = $content;
|
||
}
|
||
} else {
|
||
$this->_latestContent = $content;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return $this->_latestContent;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove version of document
|
||
*
|
||
* @param SeedDMS_Core_DocumentContent $version version number of content
|
||
* @return boolean true if successful, otherwise false
|
||
*/
|
||
private function _removeContent($version) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (file_exists( $this->_dms->contentDir.$version->getPath() ))
|
||
if (!SeedDMS_Core_File::removeFile( $this->_dms->contentDir.$version->getPath() ))
|
||
return false;
|
||
|
||
$db->startTransaction();
|
||
|
||
$status = $version->getStatus();
|
||
$stID = $status["statusID"];
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentContent` WHERE `document` = " . $this->getID() . " AND `version` = " . $version->getVersion();
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentContentAttributes` WHERE `content` = " . $version->getId();
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentStatusLog` WHERE `statusID` = '".$stID."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentStatus` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$status = $version->getReviewStatus();
|
||
$stList = "";
|
||
foreach ($status as $st) {
|
||
$stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["reviewID"]."'";
|
||
$queryStr = "SELECT * FROM `tblDocumentReviewLog` WHERE `reviewID` = " . $st['reviewID'];
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if ((is_bool($resArr) && !$resArr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
foreach($resArr as $res) {
|
||
$file = $this->_dms->contentDir . $this->getDir().'r'.$res['reviewLogID'];
|
||
if(file_exists($file))
|
||
SeedDMS_Core_File::removeFile($file);
|
||
}
|
||
}
|
||
|
||
if (strlen($stList)>0) {
|
||
$queryStr = "DELETE FROM `tblDocumentReviewLog` WHERE `tblDocumentReviewLog`.`reviewID` IN (".$stList.")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentReviewers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$status = $version->getApprovalStatus();
|
||
$stList = "";
|
||
foreach ($status as $st) {
|
||
$stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["approveID"]."'";
|
||
$queryStr = "SELECT * FROM `tblDocumentApproveLog` WHERE `approveID` = " . $st['approveID'];
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if ((is_bool($resArr) && !$resArr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
foreach($resArr as $res) {
|
||
$file = $this->_dms->contentDir . $this->getDir().'a'.$res['approveLogID'];
|
||
if(file_exists($file))
|
||
SeedDMS_Core_File::removeFile($file);
|
||
}
|
||
}
|
||
|
||
if (strlen($stList)>0) {
|
||
$queryStr = "DELETE FROM `tblDocumentApproveLog` WHERE `tblDocumentApproveLog`.`approveID` IN (".$stList.")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentApprovers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblWorkflowDocumentContent` WHERE `document` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblWorkflowLog` WHERE `document` = '". $this->getID() ."' AND `version` = '" . $version->getVersion()."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
// remove only those document files attached to version
|
||
$res = $this->getDocumentFiles($version->getVersion(), false);
|
||
if (is_bool($res) && !$res) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
foreach ($res as $documentfile)
|
||
if(!$this->removeDocumentFile($documentfile->getId())) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Call callback onPreRemoveDocument before deleting content
|
||
*
|
||
* @param SeedDMS_Core_DocumentContent $version version number of content
|
||
* @return bool|mixed
|
||
*/
|
||
function removeContent($version) { /* {{{ */
|
||
$this->_dms->lasterror = '';
|
||
|
||
/* Check if 'onPreRemoveDocument' callback is set */
|
||
if(isset($this->_dms->callbacks['onPreRemoveContent'])) {
|
||
foreach($this->_dms->callbacks['onPreRemoveContent'] as $callback) {
|
||
$ret = call_user_func($callback[0], $callback[1], $this, $version);
|
||
if(is_bool($ret))
|
||
return $ret;
|
||
}
|
||
}
|
||
|
||
if(false === ($ret = self::_removeContent($version))) {
|
||
return false;
|
||
}
|
||
|
||
/* Invalidate the content list and the latest content of this document,
|
||
* otherwise getContent() and getLatestContent()
|
||
* will still return the content just deleted.
|
||
*/
|
||
$this->_latestContent = null;
|
||
$this->_content = null;
|
||
|
||
/* Check if 'onPostRemoveDocument' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostRemoveContent'])) {
|
||
foreach($this->_dms->callbacks['onPostRemoveContent'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $version)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return $ret;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a certain document link
|
||
*
|
||
* @param integer $linkID id of link
|
||
* @return SeedDMS_Core_DocumentLink|bool of SeedDMS_Core_DocumentLink or false in case of
|
||
* an error.
|
||
*/
|
||
function getDocumentLink($linkID) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!is_numeric($linkID)) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $linkID;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if ((is_bool($resArr) && !$resArr) || count($resArr)==0)
|
||
return false;
|
||
|
||
$resArr = $resArr[0];
|
||
$document = $this->_dms->getDocument($resArr["document"]);
|
||
$target = $this->_dms->getDocument($resArr["target"]);
|
||
$link = new SeedDMS_Core_DocumentLink($resArr["id"], $document, $target, $resArr["userID"], $resArr["public"]);
|
||
$user = $this->_dms->getLoggedInUser();
|
||
if($link->getAccessMode($user, $document, $target) >= M_READ)
|
||
return $link;
|
||
return null;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return all document links
|
||
*
|
||
* The list may contain all links to other documents, even those which
|
||
* may not be visible by certain users, unless you pass appropriate
|
||
* parameters to filter out public links and those created by
|
||
* the given user. The application may call
|
||
* SeedDMS_Core_DMS::filterDocumentLinks() afterwards.
|
||
*
|
||
* @param boolean $publiconly return on publically visible links
|
||
* @param object $user return also private links of this user
|
||
* @return array list of objects of class SeedDMS_Core_DocumentLink
|
||
*/
|
||
function getDocumentLinks($publiconly=false, $user=null) { /* {{{ */
|
||
if (!isset($this->_documentLinks)) {
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `document` = " . $this->_id;
|
||
$tmp = array();
|
||
if($publiconly)
|
||
$tmp[] = "`public`=1";
|
||
if($user)
|
||
$tmp[] = "`userID`=".$user->getID();
|
||
if($tmp) {
|
||
$queryStr .= " AND (".implode(" OR ", $tmp).")";
|
||
}
|
||
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
$this->_documentLinks = array();
|
||
|
||
$user = $this->_dms->getLoggedInUser();
|
||
foreach ($resArr as $row) {
|
||
$target = $this->_dms->getDocument($row["target"]);
|
||
$link = new SeedDMS_Core_DocumentLink($row["id"], $this, $target, $row["userID"], $row["public"]);
|
||
if($link->getAccessMode($user, $this, $target) >= M_READ)
|
||
array_push($this->_documentLinks, $link);
|
||
}
|
||
}
|
||
return $this->_documentLinks;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return all document having a link on this document
|
||
*
|
||
* The list contains all documents which have a link to the current
|
||
* document. The list contains even those documents which
|
||
* may not be accessible by the user, unless you pass appropriate
|
||
* parameters to filter out public links and those created by
|
||
* the given user.
|
||
* This functions is basically the reverse of
|
||
* SeedDMS_Core_Document::getDocumentLinks()
|
||
*
|
||
* The application may call
|
||
* SeedDMS_Core_DMS::filterDocumentLinks() afterwards.
|
||
*
|
||
* @param boolean $publiconly return on publically visible links
|
||
* @param object $user return also private links of this user
|
||
* @return array list of objects of class SeedDMS_Core_DocumentLink
|
||
*/
|
||
function getReverseDocumentLinks($publiconly=false, $user=null) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentLinks` WHERE `target` = " . $this->_id;
|
||
$tmp = array();
|
||
if($publiconly)
|
||
$tmp[] = "`public`=1";
|
||
if($user)
|
||
$tmp[] = "`userID`=".$user->getID();
|
||
if($tmp) {
|
||
$queryStr .= " AND (".implode(" OR ", $tmp).")";
|
||
}
|
||
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$links = array();
|
||
foreach ($resArr as $row) {
|
||
$document = $this->_dms->getDocument($row["document"]);
|
||
$link = new SeedDMS_Core_DocumentLink($row["id"], $document, $this, $row["userID"], $row["public"]);
|
||
if($link->getAccessMode($user, $document, $this) >= M_READ)
|
||
array_push($links, $link);
|
||
}
|
||
|
||
return $links;
|
||
} /* }}} */
|
||
|
||
function addDocumentLink($targetID, $userID, $public) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$public = ($public) ? "1" : "0";
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentLinks` (`document`, `target`, `userID`, `public`) VALUES (".$this->_id.", ".(int)$targetID.", ".(int)$userID.", ".(int)$public.")";
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset($this->_documentLinks);
|
||
return true;
|
||
} /* }}} */
|
||
|
||
function removeDocumentLink($linkID) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!is_numeric($linkID)) return false;
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentLinks` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $linkID;
|
||
if (!$db->getResult($queryStr)) return false;
|
||
unset ($this->_documentLinks);
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get attached file by its id
|
||
*
|
||
* @return object instance of SeedDMS_Core_DocumentFile, null if file is not
|
||
* accessible, false in case of an sql error
|
||
*/
|
||
function getDocumentFile($ID) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!is_numeric($ID)) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id ." AND `id` = " . (int) $ID;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if ((is_bool($resArr) && !$resArr) || count($resArr)==0) return false;
|
||
|
||
$resArr = $resArr[0];
|
||
$file = new SeedDMS_Core_DocumentFile($resArr["id"], $this, $resArr["userID"], $resArr["comment"], $resArr["date"], $resArr["dir"], $resArr["fileType"], $resArr["mimeType"], $resArr["orgFileName"], $resArr["name"],$resArr["version"],$resArr["public"]);
|
||
$user = $this->_dms->getLoggedInUser();
|
||
if($file->getAccessMode($user) >= M_READ)
|
||
return $file;
|
||
return null;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get list of files attached to document
|
||
*
|
||
* @param integer $version get only attachments for this version
|
||
*@param boolean $incnoversion include attachments without a version
|
||
* @return array list of files, false in case of an sql error
|
||
*/
|
||
function getDocumentFiles($version=0, $incnoversion=true) { /* {{{ */
|
||
if (!isset($this->_documentFiles)) {
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id;
|
||
if($version) {
|
||
if($incnoversion)
|
||
$queryStr .= " AND (`version`=0 OR `version`=".(int) $version.")";
|
||
else
|
||
$queryStr .= " AND (`version`=".(int) $version.")";
|
||
}
|
||
$queryStr .= " ORDER BY ";
|
||
if($version) {
|
||
$queryStr .= "`version` DESC,";
|
||
}
|
||
$queryStr .= "`date` DESC";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr) return false;
|
||
|
||
$this->_documentFiles = array();
|
||
|
||
$user = $this->_dms->getLoggedInUser();
|
||
foreach ($resArr as $row) {
|
||
$file = new SeedDMS_Core_DocumentFile($row["id"], $this, $row["userID"], $row["comment"], $row["date"], $row["dir"], $row["fileType"], $row["mimeType"], $row["orgFileName"], $row["name"], $row["version"], $row["public"]);
|
||
if($file->getAccessMode($user) >= M_READ)
|
||
array_push($this->_documentFiles, $file);
|
||
}
|
||
}
|
||
return $this->_documentFiles;
|
||
} /* }}} */
|
||
|
||
function addDocumentFile($name, $comment, $user, $tmpFile, $orgFileName,$fileType, $mimeType,$version=0,$public=1) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$dir = $this->getDir();
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "INSERT INTO `tblDocumentFiles` (`comment`, `date`, `dir`, `document`, `fileType`, `mimeType`, `orgFileName`, `userID`, `name`, `version`, `public`) VALUES ".
|
||
"(".$db->qstr($comment).", ".$db->getCurrentTimestamp().", ".$db->qstr($dir).", ".$this->_id.", ".$db->qstr($fileType).", ".$db->qstr($mimeType).", ".$db->qstr($orgFileName).",".$user->getID().",".$db->qstr($name).", ".((int) $version).", ".($public ? 1 : 0).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$id = $db->getInsertID('tblDocumentFiles');
|
||
|
||
$file = $this->getDocumentFile($id);
|
||
if (is_bool($file) && !$file) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
// copy file
|
||
if (!SeedDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) return false;
|
||
if($this->_dms->forceRename)
|
||
$err = SeedDMS_Core_File::renameFile($tmpFile, $this->_dms->contentDir . $file->getPath());
|
||
else
|
||
$err = SeedDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $file->getPath());
|
||
if (!$err) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return $file;
|
||
} /* }}} */
|
||
|
||
function removeDocumentFile($ID) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!is_numeric($ID)) return false;
|
||
|
||
$file = $this->getDocumentFile($ID);
|
||
if (is_bool($file) && !$file) return false;
|
||
|
||
if (file_exists( $this->_dms->contentDir . $file->getPath() )){
|
||
if (!SeedDMS_Core_File::removeFile( $this->_dms->contentDir . $file->getPath() ))
|
||
return false;
|
||
}
|
||
|
||
$name=$file->getName();
|
||
$comment=$file->getcomment();
|
||
|
||
$queryStr = "DELETE FROM `tblDocumentFiles` WHERE `document` = " . $this->getID() . " AND `id` = " . (int) $ID;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
unset ($this->_documentFiles);
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove a document completly
|
||
*
|
||
* This methods calls the callback 'onPreRemoveDocument' before removing
|
||
* the document. The current document will be passed as the second
|
||
* parameter to the callback function. After successful deletion the
|
||
* 'onPostRemoveDocument' callback will be used. The current document id
|
||
* will be passed as the second parameter. If onPreRemoveDocument fails
|
||
* the whole function will fail and the document will not be deleted.
|
||
* The return value of 'onPostRemoveDocument' will be disregarded.
|
||
*
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function remove() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
$this->_dms->lasterror = '';
|
||
|
||
/* Check if 'onPreRemoveDocument' callback is set */
|
||
if(isset($this->_dms->callbacks['onPreRemoveDocument'])) {
|
||
foreach($this->_dms->callbacks['onPreRemoveDocument'] as $callback) {
|
||
$ret = call_user_func($callback[0], $callback[1], $this);
|
||
if(is_bool($ret))
|
||
return $ret;
|
||
}
|
||
}
|
||
|
||
$res = $this->getContent();
|
||
if (is_bool($res) && !$res) return false;
|
||
|
||
$db->startTransaction();
|
||
|
||
// remove content of document
|
||
foreach ($this->_content as $version) {
|
||
if (!$this->_removeContent($version)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// remove all document files
|
||
$res = $this->getDocumentFiles();
|
||
if (is_bool($res) && !$res) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
foreach ($res as $documentfile)
|
||
if(!$this->removeDocumentFile($documentfile->getId())) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
// TODO: versioning file?
|
||
|
||
if (file_exists( $this->_dms->contentDir . $this->getDir() ))
|
||
if (!SeedDMS_Core_File::removeDir( $this->_dms->contentDir . $this->getDir() )) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblDocuments` WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentAttributes` WHERE `document` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblACLs` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentLinks` WHERE `document` = " . $this->_id . " OR `target` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentLocks` WHERE `document` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentFiles` WHERE `document` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "DELETE FROM `tblDocumentCategory` WHERE `documentID` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
// Delete the notification list.
|
||
$queryStr = "DELETE FROM `tblNotify` WHERE `target` = " . $this->_id . " AND `targetType` = " . T_DOCUMENT;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
|
||
/* Check if 'onPostRemoveDocument' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostRemoveDocument'])) {
|
||
foreach($this->_dms->callbacks['onPostRemoveDocument'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $this->_id)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get List of users and groups which have read access on the document
|
||
* The list will not include any guest users,
|
||
* administrators and the owner of the folder unless $listadmin resp.
|
||
* $listowner is set to true.
|
||
*
|
||
* This function is deprecated. Use
|
||
* {@see SeedDMS_Core_Document::getReadAccessList()} instead.
|
||
*/
|
||
function getApproversList() { /* {{{ */
|
||
return $this->getReadAccessList(0, 0, 0);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of groups and users with read access on the document
|
||
*
|
||
* @param boolean $listadmin if set to true any admin will be listed too
|
||
* @param boolean $listowner if set to true the owner will be listed too
|
||
* @param boolean $listguest if set to true any guest will be listed too
|
||
*
|
||
* @return array list of users and groups
|
||
*/
|
||
function getReadAccessList($listadmin=0, $listowner=0, $listguest=0) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if (!isset($this->_readAccessList)) {
|
||
$this->_readAccessList = array("groups" => array(), "users" => array());
|
||
$userIDs = "";
|
||
$groupIDs = "";
|
||
$defAccess = $this->getDefaultAccess();
|
||
|
||
/* Check if the default access is < read access or >= read access.
|
||
* If default access is less than read access, then create a list
|
||
* of users and groups with read access.
|
||
* If default access is equal or greater then read access, then
|
||
* create a list of users and groups without read access.
|
||
*/
|
||
if ($defAccess<M_READ) {
|
||
// Get the list of all users and groups that are listed in the ACL as
|
||
// having read access to the document.
|
||
$tmpList = $this->getAccessList(M_READ, O_GTEQ);
|
||
}
|
||
else {
|
||
// Get the list of all users and groups that DO NOT have read access
|
||
// to the document.
|
||
$tmpList = $this->getAccessList(M_NONE, O_LTEQ);
|
||
}
|
||
/** @var SeedDMS_Core_GroupAccess $groupAccess */
|
||
foreach ($tmpList["groups"] as $groupAccess) {
|
||
$groupIDs .= (strlen($groupIDs)==0 ? "" : ", ") . $groupAccess->getGroupID();
|
||
}
|
||
|
||
/** @var SeedDMS_Core_UserAccess $userAccess */
|
||
foreach ($tmpList["users"] as $userAccess) {
|
||
$user = $userAccess->getUser();
|
||
if (!$listadmin && $user->isAdmin()) continue;
|
||
if (!$listowner && $user->getID() == $this->_ownerID) continue;
|
||
if (!$listguest && $user->isGuest()) continue;
|
||
$userIDs .= (strlen($userIDs)==0 ? "" : ", ") . $userAccess->getUserID();
|
||
}
|
||
|
||
// Construct a query against the users table to identify those users
|
||
// that have read access to this document, either directly through an
|
||
// ACL entry, by virtue of ownership or by having administrative rights
|
||
// on the database.
|
||
$queryStr="";
|
||
/* If default access is less then read, $userIDs and $groupIDs contains
|
||
* a list of user with read access
|
||
*/
|
||
if ($defAccess < M_READ) {
|
||
if (strlen($groupIDs)>0) {
|
||
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
|
||
"WHERE `tblGroupMembers`.`groupID` IN (". $groupIDs .") ".
|
||
"AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." UNION ";
|
||
}
|
||
$queryStr .=
|
||
"SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
"WHERE (`tblUsers`.`role` != ".SeedDMS_Core_User::role_guest.") ".
|
||
"AND ((`tblUsers`.`id` = ". $this->_ownerID . ") ".
|
||
"OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.")".
|
||
(strlen($userIDs) == 0 ? "" : " OR (`tblUsers`.`id` IN (". $userIDs ."))").
|
||
") ORDER BY `login`";
|
||
}
|
||
/* If default access is equal or greater than M_READ, $userIDs and
|
||
* $groupIDs contains a list of user without read access
|
||
*/
|
||
else {
|
||
if (strlen($groupIDs)>0) {
|
||
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
|
||
"WHERE `tblGroupMembers`.`groupID` NOT IN (". $groupIDs .")".
|
||
"AND `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ".
|
||
(strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))")." UNION ";
|
||
} else {
|
||
$queryStr .=
|
||
"SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
"WHERE `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ".
|
||
(strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))")." UNION ";
|
||
}
|
||
$queryStr .=
|
||
"SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
"WHERE (`tblUsers`.`id` = ". $this->_ownerID . ") ".
|
||
"OR (`tblUsers`.`role` = ".SeedDMS_Core_User::role_admin.") ".
|
||
// "UNION ".
|
||
// "SELECT `tblUsers`.* FROM `tblUsers` ".
|
||
// "WHERE `tblUsers`.`role` != ".SeedDMS_Core_User::role_guest." ".
|
||
// (strlen($userIDs) == 0 ? "" : " AND (`tblUsers`.`id` NOT IN (". $userIDs ."))").
|
||
" ORDER BY `login`";
|
||
}
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (!is_bool($resArr)) {
|
||
foreach ($resArr as $row) {
|
||
$user = $this->_dms->getUser($row['id']);
|
||
if (!$listadmin && $user->isAdmin()) continue;
|
||
if (!$listowner && $user->getID() == $this->_ownerID) continue;
|
||
$this->_readAccessList["users"][] = $user;
|
||
}
|
||
}
|
||
|
||
// Assemble the list of groups that have read access to the document.
|
||
$queryStr="";
|
||
if ($defAccess < M_READ) {
|
||
if (strlen($groupIDs)>0) {
|
||
$queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ".
|
||
"WHERE `tblGroups`.`id` IN (". $groupIDs .") ORDER BY `name`";
|
||
}
|
||
}
|
||
else {
|
||
if (strlen($groupIDs)>0) {
|
||
$queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ".
|
||
"WHERE `tblGroups`.`id` NOT IN (". $groupIDs .") ORDER BY `name`";
|
||
}
|
||
else {
|
||
$queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ORDER BY `name`";
|
||
}
|
||
}
|
||
if (strlen($queryStr)>0) {
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (!is_bool($resArr)) {
|
||
foreach ($resArr as $row) {
|
||
$group = $this->_dms->getGroup($row["id"]);
|
||
$this->_readAccessList["groups"][] = $group;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $this->_readAccessList;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the internally used folderList which stores the ids of folders from
|
||
* the root folder to the parent folder.
|
||
*
|
||
* @return string column separated list of folder ids
|
||
*/
|
||
function getFolderList() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "SELECT `folderList` FROM `tblDocuments` where id = ".$this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
return $resArr[0]['folderList'];
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Checks the internal data of the document and repairs it.
|
||
* Currently, this function only repairs an incorrect folderList
|
||
*
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function repair() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$curfolderlist = $this->getFolderList();
|
||
|
||
// calculate the folderList of the folder
|
||
$parent = $this->getFolder();
|
||
$pathPrefix="";
|
||
$path = $parent->getPath();
|
||
foreach ($path as $f) {
|
||
$pathPrefix .= ":".$f->getID();
|
||
}
|
||
if (strlen($pathPrefix)>1) {
|
||
$pathPrefix .= ":";
|
||
}
|
||
if($curfolderlist != $pathPrefix) {
|
||
$queryStr = "UPDATE `tblDocuments` SET `folderList`='".$pathPrefix."' WHERE `id` = ". $this->_id;
|
||
$res = $db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Calculate the disk space including all versions of the document
|
||
*
|
||
* This is done by using the internal database field storing the
|
||
* filesize of a document version.
|
||
*
|
||
* @return integer total disk space in Bytes
|
||
*/
|
||
function getUsedDiskSpace() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$queryStr = "SELECT SUM(`fileSize`) sum FROM `tblDocumentContent` WHERE `document` = " . $this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
return $resArr[0]['sum'];
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of events happend during the life of the document
|
||
*
|
||
* This includes the creation of new versions, approval and reviews, etc.
|
||
*
|
||
* @return array list of events
|
||
*/
|
||
function getTimeline() { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
$timeline = array();
|
||
|
||
/* No need to add entries for new version because the status log
|
||
* will generate an entry as well.
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` = " . $this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
foreach ($resArr as $row) {
|
||
$date = date('Y-m-d H:i:s', $row['date']);
|
||
$timeline[] = array('date'=>$date, 'msg'=>'Added version '.$row['version'], 'type'=>'add_version', 'version'=>$row['version'], 'document'=>$this, 'params'=>array($row['version']));
|
||
}
|
||
*/
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentFiles` WHERE `document` = " . $this->_id;
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
foreach ($resArr as $row) {
|
||
$date = date('Y-m-d H:i:s', $row['date']);
|
||
$timeline[] = array('date'=>$date, 'msg'=>'Added attachment "'.$row['name'].'"', 'document'=>$this, 'type'=>'add_file', 'fileid'=>$row['id']);
|
||
}
|
||
|
||
$queryStr=
|
||
"SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`statusLogID`,`tblDocumentStatusLog`.`status`, ".
|
||
"`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ".
|
||
"`tblDocumentStatusLog`.`userID` ".
|
||
"FROM `tblDocumentStatus` ".
|
||
"LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ".
|
||
"WHERE `tblDocumentStatus`.`documentID` = '". $this->_id ."' ".
|
||
"ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
/* The above query will also contain entries where a document status exists
|
||
* but no status log entry. Those records will have no date and must be
|
||
* skipped.
|
||
*/
|
||
foreach ($resArr as $row) {
|
||
if($row['date']) {
|
||
$date = $row['date'];
|
||
$timeline[] = array('date'=>$date, 'msg'=>'Version '.$row['version'].': Status change to '.$row['status'], 'type'=>'status_change', 'version'=>$row['version'], 'document'=>$this, 'status'=>$row['status'], 'statusid'=>$row['statusID'], 'statuslogid'=>$row['statusLogID']);
|
||
}
|
||
}
|
||
return $timeline;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Transfers the document to a new user
|
||
*
|
||
* This method not just sets a new owner of the document but also
|
||
* transfers the document links, attachments and locks to the new user.
|
||
*
|
||
* @return boolean true if successful, otherwise false
|
||
*/
|
||
function transferToUser($newuser) { /* {{{ */
|
||
$db = $this->_dms->getDB();
|
||
|
||
if($newuser->getId() == $this->_ownerID)
|
||
return true;
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "UPDATE `tblDocuments` SET `owner` = ".$newuser->getId()." WHERE `id` = " . $this->_id;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocumentLocks` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocumentLinks` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `userID` = ".$newuser->getId()." WHERE `document` = " . $this->_id . " AND `userID` = ".$this->_ownerID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$this->_ownerID = $newuser->getID();
|
||
$this->_owner = $newuser;
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
} /* }}} */
|
||
|
||
|
||
/**
|
||
* Class to represent content of a document
|
||
*
|
||
* Each document has content attached to it, often called a 'version' of the
|
||
* document. The document content represents a file on the disk with some
|
||
* meta data stored in the database. A document content has a version number
|
||
* which is incremented with each replacement of the old content. Old versions
|
||
* are kept unless they are explicitly deleted by
|
||
* {@link SeedDMS_Core_Document::removeContent()}.
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||
* 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_DocumentContent extends SeedDMS_Core_Object { /* {{{ */
|
||
/**
|
||
* @var object document
|
||
*/
|
||
protected $_document;
|
||
|
||
/**
|
||
* @var integer version
|
||
*/
|
||
protected $_version;
|
||
|
||
/**
|
||
* @var string comment
|
||
*/
|
||
protected $_comment;
|
||
|
||
/**
|
||
* @var string date
|
||
*/
|
||
protected $_date;
|
||
|
||
/**
|
||
* @var integer userID
|
||
*/
|
||
protected $_userID;
|
||
|
||
/**
|
||
* @var string dir on disk (deprecated)
|
||
*/
|
||
protected $_dir;
|
||
|
||
/**
|
||
* @var string original file name
|
||
*/
|
||
protected $_orgFileName;
|
||
|
||
/**
|
||
* @var string file type (actually the extension without the leading dot)
|
||
*/
|
||
protected $_fileType;
|
||
|
||
/**
|
||
* @var string mime type
|
||
*/
|
||
protected $_mimeType;
|
||
|
||
/**
|
||
* @var string checksum of content
|
||
*/
|
||
protected $_checksum;
|
||
|
||
/**
|
||
* @var object workflow
|
||
*/
|
||
protected $_workflow;
|
||
|
||
/**
|
||
* @var object workflow state
|
||
*/
|
||
protected $_workflowState;
|
||
|
||
/**
|
||
* @var object dms
|
||
*/
|
||
public $_dms;
|
||
|
||
/**
|
||
* Recalculate the status of a document
|
||
*
|
||
* The methods checks the review and approval status and sets the
|
||
* status of the document accordingly.
|
||
*
|
||
* If status is S_RELEASED and the version has a workflow, then set
|
||
* the status to S_IN_WORKFLOW
|
||
* If status is S_RELEASED and there are reviewers => set status S_DRAFT_REV
|
||
* If status is S_RELEASED or S_DRAFT_REV and there are approvers => set
|
||
* status S_DRAFT_APP
|
||
* If status is draft and there are no approver and no reviewers => set
|
||
* status to S_RELEASED
|
||
* The status of a document with the current status S_OBSOLETE, S_REJECTED,
|
||
* or S_EXPIRED will not be changed unless the parameter
|
||
* $ignorecurrentstatus is set to true.
|
||
*
|
||
* This method may not be called after a negative approval or review to
|
||
* recalculated the status, because
|
||
* it doesn't take a defeating approval or review into account. It will
|
||
* just check for a pending workflow, approval or review and set the status
|
||
* accordingly, e.g. after the list of reviewers or appovers has been
|
||
* modified. If there is not pending workflow, approval or review the
|
||
* status will be set to S_RELEASED.
|
||
*
|
||
* This method will call {@see SeedDMS_Core_DocumentContent::setStatus()}
|
||
* which checks if the status has actually changed. This is, why this
|
||
* function can be called at any time without harm to the status log.
|
||
*
|
||
* @param boolean $ignorecurrentstatus ignore the current status and
|
||
* recalculate a new status in any case
|
||
* @param object $user the user initiating this method
|
||
* @param string $msg message stored in status log when status is set
|
||
*/
|
||
function verifyStatus($ignorecurrentstatus=false, $user=null, $msg='') { /* {{{ */
|
||
|
||
unset($this->_status);
|
||
$st=$this->getStatus();
|
||
|
||
if (!$ignorecurrentstatus && ($st["status"]==S_OBSOLETE || $st["status"]==S_REJECTED || $st["status"]==S_EXPIRED )) return;
|
||
|
||
unset($this->_workflow); // force to be reloaded from DB
|
||
$hasworkflow = $this->getWorkflow() ? true : false;
|
||
|
||
/* $pendingReview will be set when there are still open reviews */
|
||
$pendingReview=false;
|
||
unset($this->_reviewStatus); // force to be reloaded from DB
|
||
$reviewStatus=$this->getReviewStatus();
|
||
if (is_array($reviewStatus) && count($reviewStatus)>0) {
|
||
foreach ($reviewStatus as $r){
|
||
if ($r["status"]==0){
|
||
$pendingReview=true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* $pendingApproval will be set when there are still open approvals */
|
||
$pendingApproval=false;
|
||
unset($this->_approvalStatus); // force to be reloaded from DB
|
||
$approvalStatus=$this->getApprovalStatus();
|
||
if (is_array($approvalStatus) && count($approvalStatus)>0) {
|
||
foreach ($approvalStatus as $a){
|
||
if ($a["status"]==0){
|
||
$pendingApproval=true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* First check for a running workflow or open reviews or approvals. */
|
||
if ($hasworkflow) $this->setStatus(S_IN_WORKFLOW,$msg,$user);
|
||
elseif ($pendingReview) $this->setStatus(S_DRAFT_REV,$msg,$user);
|
||
elseif ($pendingApproval) $this->setStatus(S_DRAFT_APP,$msg,$user);
|
||
else $this->setStatus(S_RELEASED,$msg,$user);
|
||
} /* }}} */
|
||
|
||
function __construct($id, $document, $version, $comment, $date, $userID, $dir, $orgFileName, $fileType, $mimeType, $fileSize=0, $checksum='') { /* {{{ */
|
||
parent::__construct($id);
|
||
$this->_document = $document;
|
||
$this->_version = (int) $version;
|
||
$this->_comment = $comment;
|
||
$this->_date = $date;
|
||
$this->_userID = (int) $userID;
|
||
$this->_dir = $dir;
|
||
$this->_orgFileName = $orgFileName;
|
||
$this->_fileType = $fileType;
|
||
$this->_mimeType = $mimeType;
|
||
$this->_dms = $document->getDMS();
|
||
if(!$fileSize) {
|
||
$this->_fileSize = SeedDMS_Core_File::fileSize($this->_dms->contentDir . $this->getPath());
|
||
} else {
|
||
$this->_fileSize = $fileSize;
|
||
}
|
||
$this->_checksum = $checksum;
|
||
$this->_workflow = null;
|
||
$this->_workflowState = null;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if this object is of type 'documentcontent'.
|
||
*
|
||
* @param string $type type of object
|
||
*/
|
||
public function isType($type) { /* {{{ */
|
||
return $type == 'documentcontent';
|
||
} /* }}} */
|
||
|
||
function getVersion() { return $this->_version; }
|
||
function getComment() { return $this->_comment; }
|
||
function getDate() { return $this->_date; }
|
||
function getOriginalFileName() { return $this->_orgFileName; }
|
||
function getFileType() { return $this->_fileType; }
|
||
function getFileName(){ return $this->_version . $this->_fileType; }
|
||
/**
|
||
* getDir and the corresponding database table field are deprecated
|
||
*/
|
||
function __getDir() { return $this->_dir; }
|
||
function getMimeType() { return $this->_mimeType; }
|
||
function getDocument() { return $this->_document; }
|
||
|
||
function getUser() { /* {{{ */
|
||
if (!isset($this->_user))
|
||
$this->_user = $this->_document->getDMS()->getUser($this->_userID);
|
||
return $this->_user;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return path of file on disk relative to the content directory
|
||
*
|
||
* Since version 5.1.13 a single '.' in the fileType will be skipped.
|
||
* On Windows a file named 'name.' will be saved as 'name' but the fileType
|
||
* will contain the a single '.'.
|
||
*
|
||
* @return string path of file on disc
|
||
*/
|
||
function getPath() { return $this->_document->getDir() . $this->_version . $this->_fileType; }
|
||
|
||
function setDate($date = false) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$date)
|
||
$date = time();
|
||
else {
|
||
if(!is_numeric($date))
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocumentContent` SET `date` = ".(int) $date." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_date = $date;
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
function getFileSize() { /* {{{ */
|
||
return $this->_fileSize;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set file size by reading the file
|
||
*/
|
||
function setFileSize() { /* {{{ */
|
||
$filesize = SeedDMS_Core_File::fileSize($this->_dms->contentDir . $this->_document->getDir() . $this->getFileName());
|
||
if($filesize === false)
|
||
return false;
|
||
|
||
$db = $this->_document->getDMS()->getDB();
|
||
$queryStr = "UPDATE `tblDocumentContent` SET `fileSize` = ".$filesize." where `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
$this->_fileSize = $filesize;
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
function getChecksum() { /* {{{ */
|
||
return $this->_checksum;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set checksum by reading the file
|
||
*/
|
||
function setChecksum() { /* {{{ */
|
||
$checksum = SeedDMS_Core_File::checksum($this->_dms->contentDir . $this->_document->getDir() . $this->getFileName());
|
||
if($checksum === false)
|
||
return false;
|
||
|
||
$db = $this->_document->getDMS()->getDB();
|
||
$queryStr = "UPDATE `tblDocumentContent` SET `checksum` = ".$db->qstr($checksum)." where `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
$this->_checksum = $checksum;
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
function setComment($newComment) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocumentContent` SET `comment` = ".$db->qstr($newComment)." WHERE `document` = " . $this->_document->getID() . " AND `version` = " . $this->_version;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_comment = $newComment;
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the latest status of the content
|
||
*
|
||
* The status of the content reflects its current review, approval or workflow
|
||
* state. A status can be a negative or positive number or 0. A negative
|
||
* numbers indicate a missing approval, review or an obsolete content.
|
||
* Positive numbers indicate some kind of approval or workflow being
|
||
* active, but not necessarily a release.
|
||
* S_DRAFT_REV, 0
|
||
* S_DRAFT_APP, 1
|
||
* S_RELEASED, 2
|
||
* S_IN_WORKFLOW, 3
|
||
* S_REJECTED, -1
|
||
* S_OBSOLETE, -2
|
||
* S_EXPIRED, -3
|
||
* When a content is inserted and does not need approval nor review,
|
||
* then its status is set to S_RELEASED immediately. Any change of
|
||
* the status is monitored in the table tblDocumentStatusLog. This
|
||
* function will always return the latest entry for the content.
|
||
*
|
||
* @return array latest record from tblDocumentStatusLog
|
||
*/
|
||
function getStatus($limit=1) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!is_numeric($limit)) return false;
|
||
|
||
// Retrieve the current overall status of the content represented by
|
||
// this object.
|
||
if (!isset($this->_status)) {
|
||
$queryStr=
|
||
"SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ".
|
||
"`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ".
|
||
"`tblDocumentStatusLog`.`userID` ".
|
||
"FROM `tblDocumentStatus` ".
|
||
"LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ".
|
||
"WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' ".
|
||
"AND `tblDocumentStatus`.`version` = '". $this->_version ."' ".
|
||
"ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC LIMIT ".(int) $limit;
|
||
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return false;
|
||
if (count($res)!=1)
|
||
return false;
|
||
$this->_status = $res[0];
|
||
}
|
||
return $this->_status;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get current and former states of the document content
|
||
*
|
||
* @param integer $limit if not set all log entries will be returned
|
||
* @return array list of status changes
|
||
*/
|
||
function getStatusLog($limit=0) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!is_numeric($limit)) return false;
|
||
|
||
$queryStr=
|
||
"SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ".
|
||
"`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ".
|
||
"`tblDocumentStatusLog`.`userID` ".
|
||
"FROM `tblDocumentStatus` ".
|
||
"LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ".
|
||
"WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' ".
|
||
"AND `tblDocumentStatus`.`version` = '". $this->_version ."' ".
|
||
"ORDER BY `tblDocumentStatusLog`.`statusLogID` DESC ";
|
||
if($limit)
|
||
$queryStr .= "LIMIT ".(int) $limit;
|
||
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return false;
|
||
|
||
return $res;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set the status of the content
|
||
* Setting the status means to add another entry into the table
|
||
* tblDocumentStatusLog. The method returns also false if the status
|
||
* is already set on the value passed to the method.
|
||
*
|
||
* @param integer $status new status of content
|
||
* @param string $comment comment for this status change
|
||
* @param object $updateUser user initiating the status change
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function setStatus($status, $comment, $updateUser, $date='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!is_numeric($status)) return false;
|
||
|
||
/* return an error if $updateuser is not set */
|
||
if(!$updateUser)
|
||
return false;
|
||
|
||
// If the supplied value lies outside of the accepted range, return an
|
||
// error.
|
||
if ($status < -3 || $status > 3) {
|
||
return false;
|
||
}
|
||
|
||
// Retrieve the current overall status of the content represented by
|
||
// this object, if it hasn't been done already.
|
||
if (!isset($this->_status)) {
|
||
$this->getStatus();
|
||
}
|
||
if ($this->_status["status"]==$status) {
|
||
return true;
|
||
}
|
||
if($date)
|
||
$ddate = $db->qstr($date);
|
||
else
|
||
$ddate = $db->getCurrentDatetime();
|
||
$db->startTransaction();
|
||
$queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $this->_status["statusID"] ."', '". (int) $status ."', ".$db->qstr($comment).", ".$ddate.", '". $updateUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
/* Check if 'onSetStatus' callback is set */
|
||
if(isset($this->_dms->callbacks['onSetStatus'])) {
|
||
foreach($this->_dms->callbacks['onSetStatus'] as $callback) {
|
||
$ret = call_user_func($callback[0], $callback[1], $this, $updateUser, $this->_status["status"], $status);
|
||
if(is_bool($ret)) {
|
||
unset($this->_status);
|
||
if($ret)
|
||
$db->commitTransaction();
|
||
else
|
||
$db->rollbackTransaction();
|
||
return $ret;
|
||
}
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
unset($this->_status);
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Rewrites the complete status log
|
||
*
|
||
* Attention: this function is highly dangerous.
|
||
* It removes an existing status log and rewrites it.
|
||
* This method was added for importing an xml dump.
|
||
*
|
||
* @param array $statuslog new status log with the newest log entry first.
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function rewriteStatusLog($statuslog) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr= "SELECT `tblDocumentStatus`.* FROM `tblDocumentStatus` WHERE `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentStatus`.`version` = '". $this->_version ."' ";
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return false;
|
||
|
||
$statusID = $res[0]['statusID'];
|
||
|
||
$db->startTransaction();
|
||
|
||
/* First, remove the old entries */
|
||
$queryStr = "DELETE from `tblDocumentStatusLog` where `statusID`=".$statusID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
/* Second, insert the new entries */
|
||
$statuslog = array_reverse($statuslog);
|
||
foreach($statuslog as $log) {
|
||
if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('".$statusID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".$log['user']->getID().")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
|
||
/**
|
||
* Returns the access mode similar to a document
|
||
*
|
||
* There is no real access mode for document content, so this is more
|
||
* like a virtual access mode, derived from the status of the document
|
||
* content. The function checks if {@link SeedDMS_Core_DMS::noReadForStatus}
|
||
* contains the status of the version and returns M_NONE if it exists and
|
||
* the user is not involved in a workflow or review/approval/revision.
|
||
* This method is called by all functions that returns the content e.g.
|
||
* {@link SeedDMS_Core_Document::getLatestContent()}
|
||
* It is also used by {@link SeedDMS_Core_Document::getAccessMode()} to
|
||
* prevent access on the whole document if there is no accessible version.
|
||
*
|
||
* FIXME: This function only works propperly if $u is the currently logged in
|
||
* user, because noReadForStatus will be set for this user.
|
||
* FIXED: instead of using $dms->noReadForStatus it is take from the user's role
|
||
*
|
||
* @param object $u user
|
||
* @return integer either M_NONE or M_READ
|
||
*/
|
||
function getAccessMode($u) { /* {{{ */
|
||
$dms = $this->_document->getDMS();
|
||
|
||
/* Check if 'onCheckAccessDocumentContent' callback is set */
|
||
if(isset($this->_dms->callbacks['onCheckAccessDocumentContent'])) {
|
||
foreach($this->_dms->callbacks['onCheckAccessDocumentContent'] as $callback) {
|
||
if(($ret = call_user_func($callback[0], $callback[1], $this, $u)) > 0) {
|
||
return $ret;
|
||
}
|
||
}
|
||
}
|
||
|
||
return M_READ;
|
||
|
||
if(!$u)
|
||
return M_NONE;
|
||
|
||
/* If read access isn't further restricted by status, than grant read access */
|
||
if(!$dms->noReadForStatus)
|
||
return M_READ;
|
||
$noReadForStatus = $dms->noReadForStatus;
|
||
|
||
/* If the current status is not in list of status without read access, then grant read access */
|
||
if(!in_array($this->getStatus()['status'], $noReadForStatus))
|
||
return M_READ;
|
||
|
||
/* Administrators have unrestricted access */
|
||
if ($u->isAdmin()) return M_READ;
|
||
|
||
/* The owner of the document has unrestricted access */
|
||
$owner = $this->_document->getOwner();
|
||
if ($u->getID() == $owner->getID()) return M_READ;
|
||
|
||
/* Read/Write access on the document will also grant access on the version */
|
||
if($this->_document->getAccessMode($u) >= M_READWRITE) return M_READ;
|
||
|
||
/* At this point the current status is in the list of status without read access.
|
||
* The only way to still gain read access is, if the user is involved in the
|
||
* process, e.g. is a reviewer, approver or an active person in the workflow.
|
||
*/
|
||
$s = $this->getStatus();
|
||
switch($s['status']) {
|
||
case S_DRAFT_REV:
|
||
$status = $this->getReviewStatus();
|
||
foreach ($status as $r) {
|
||
if($r['status'] != -2) // Check if reviewer was removed
|
||
switch ($r["type"]) {
|
||
case 0: // Reviewer is an individual.
|
||
if($u->getId() == $r["required"])
|
||
return M_READ;
|
||
break;
|
||
case 1: // Reviewer is a group.
|
||
$required = $dms->getGroup($r["required"]);
|
||
if (is_object($required) && $required->isMember($u))
|
||
return M_READ;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case S_DRAFT_APP:
|
||
$status = $this->getApprovalStatus();
|
||
foreach ($status as $r) {
|
||
if($r['status'] != -2) // Check if approver was removed
|
||
switch ($r["type"]) {
|
||
case 0: // Reviewer is an individual.
|
||
if($u->getId() == $r["required"])
|
||
return M_READ;
|
||
break;
|
||
case 1: // Reviewer is a group.
|
||
$required = $dms->getGroup($r["required"]);
|
||
if (is_object($required) && $required->isMember($u))
|
||
return M_READ;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case S_RELEASED:
|
||
break;
|
||
case S_IN_WORKFLOW:
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if($this->_workflow) {
|
||
if (!$this->_workflowState)
|
||
$this->getWorkflowState();
|
||
$transitions = $this->_workflow->getNextTransitions($this->_workflowState);
|
||
foreach($transitions as $transition) {
|
||
if($this->triggerWorkflowTransitionIsAllowed($u, $transition))
|
||
return M_READ;
|
||
}
|
||
}
|
||
break;
|
||
case S_REJECTED:
|
||
break;
|
||
case S_OBSOLETE:
|
||
break;
|
||
case S_EXPIRED:
|
||
break;
|
||
}
|
||
|
||
return M_NONE;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the current review status of the document content
|
||
* The review status is a list of reviews and its current status
|
||
*
|
||
* @param integer $limit the number of recent status changes per reviewer
|
||
* @return array list of review status
|
||
*/
|
||
function getReviewStatus($limit=1) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!is_numeric($limit)) return false;
|
||
|
||
// Retrieve the current status of each assigned reviewer for the content
|
||
// represented by this object.
|
||
// FIXME: caching was turned off to make list of review log in ViewDocument
|
||
// possible
|
||
if (1 || !isset($this->_reviewStatus)) {
|
||
/* First get a list of all reviews for this document content */
|
||
$queryStr=
|
||
"SELECT `reviewID` FROM `tblDocumentReviewers` WHERE `version`='".$this->_version
|
||
."' AND `documentID` = '". $this->_document->getID() ."' ";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs)
|
||
return false;
|
||
$this->_reviewStatus = array();
|
||
if($recs) {
|
||
foreach($recs as $rec) {
|
||
$queryStr=
|
||
"SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`reviewLogID`, `tblDocumentReviewLog`.`status`, ".
|
||
"`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
|
||
"`tblDocumentReviewLog`.`userID`, `tblUsers`.`fullName`, `tblGroups`.`name` AS `groupName` ".
|
||
"FROM `tblDocumentReviewers` ".
|
||
"LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
|
||
"LEFT JOIN `tblUsers` on `tblUsers`.`id` = `tblDocumentReviewers`.`required`".
|
||
"LEFT JOIN `tblGroups` on `tblGroups`.`id` = `tblDocumentReviewers`.`required`".
|
||
"WHERE `tblDocumentReviewers`.`reviewID` = '". $rec['reviewID'] ."' ".
|
||
"ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC LIMIT ".(int) $limit;
|
||
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
unset($this->_reviewStatus);
|
||
return false;
|
||
}
|
||
foreach($res as &$t) {
|
||
$filename = $this->_dms->contentDir . $this->_document->getDir().'r'.$t['reviewLogID'];
|
||
if(file_exists($filename))
|
||
$t['file'] = $filename;
|
||
else
|
||
$t['file'] = '';
|
||
}
|
||
$this->_reviewStatus = array_merge($this->_reviewStatus, $res);
|
||
}
|
||
}
|
||
}
|
||
return $this->_reviewStatus;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Rewrites the complete review log
|
||
*
|
||
* Attention: this function is highly dangerous.
|
||
* It removes an existing review log and rewrites it.
|
||
* This method was added for importing an xml dump.
|
||
*
|
||
* @param array $reviewlog new status log with the newest log entry first.
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function rewriteReviewLog($reviewers) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr= "SELECT `tblDocumentReviewers`.* FROM `tblDocumentReviewers` WHERE `tblDocumentReviewers`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentReviewers`.`version` = '". $this->_version ."' ";
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return false;
|
||
|
||
$db->startTransaction();
|
||
|
||
if($res) {
|
||
foreach($res as $review) {
|
||
$reviewID = $review['reviewID'];
|
||
|
||
/* First, remove the old entries */
|
||
$queryStr = "DELETE from `tblDocumentReviewLog` where `reviewID`=".$reviewID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE from `tblDocumentReviewers` where `reviewID`=".$reviewID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Second, insert the new entries */
|
||
foreach($reviewers as $review) {
|
||
$queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('".$this->_document->getID()."', '".$this->_version."', ".$review['type'] .", ".(is_object($review['required']) ? $review['required']->getID() : (int) $review['required']).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID');
|
||
$reviewlog = array_reverse($review['logs']);
|
||
foreach($reviewlog as $log) {
|
||
if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('".$reviewID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".(is_object($log['user']) ? $log['user']->getID() : (int) $log['user']).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID');
|
||
if(!empty($log['file'])) {
|
||
SeedDMS_Core_File::copyFile($log['file'], $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID);
|
||
}
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the current approval status of the document content
|
||
* The approval status is a list of approvals and its current status
|
||
*
|
||
* @param integer $limit the number of recent status changes per approver
|
||
* @return array list of approval status
|
||
*/
|
||
function getApprovalStatus($limit=1) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!is_numeric($limit)) return false;
|
||
|
||
// Retrieve the current status of each assigned approver for the content
|
||
// represented by this object.
|
||
// FIXME: caching was turned off to make list of approval log in ViewDocument
|
||
// possible
|
||
if (1 || !isset($this->_approvalStatus)) {
|
||
/* First get a list of all approvals for this document content */
|
||
$queryStr=
|
||
"SELECT `approveID` FROM `tblDocumentApprovers` WHERE `version`='".$this->_version
|
||
."' AND `documentID` = '". $this->_document->getID() ."' ";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs)
|
||
return false;
|
||
$this->_approvalStatus = array();
|
||
if($recs) {
|
||
foreach($recs as $rec) {
|
||
$queryStr=
|
||
"SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`approveLogID`, `tblDocumentApproveLog`.`status`, ".
|
||
"`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
|
||
"`tblDocumentApproveLog`.`userID`, `tblUsers`.`fullName`, `tblGroups`.`name` AS `groupName` ".
|
||
"FROM `tblDocumentApprovers` ".
|
||
"LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
|
||
"LEFT JOIN `tblUsers` on `tblUsers`.`id` = `tblDocumentApprovers`.`required` ".
|
||
"LEFT JOIN `tblGroups` on `tblGroups`.`id` = `tblDocumentApprovers`.`required`".
|
||
"WHERE `tblDocumentApprovers`.`approveID` = '". $rec['approveID'] ."' ".
|
||
"ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC LIMIT ".(int) $limit;
|
||
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
unset($this->_approvalStatus);
|
||
return false;
|
||
}
|
||
foreach($res as &$t) {
|
||
$filename = $this->_dms->contentDir . $this->_document->getDir().'a'.$t['approveLogID'];
|
||
if(file_exists($filename))
|
||
$t['file'] = $filename;
|
||
else
|
||
$t['file'] = '';
|
||
}
|
||
$this->_approvalStatus = array_merge($this->_approvalStatus, $res);
|
||
}
|
||
}
|
||
}
|
||
return $this->_approvalStatus;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Rewrites the complete approval log
|
||
*
|
||
* Attention: this function is highly dangerous.
|
||
* It removes an existing review log and rewrites it.
|
||
* This method was added for importing an xml dump.
|
||
*
|
||
* @param array $reviewlog new status log with the newest log entry first.
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function rewriteApprovalLog($reviewers) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr= "SELECT `tblDocumentApprovers`.* FROM `tblDocumentApprovers` WHERE `tblDocumentApprovers`.`documentID` = '". $this->_document->getID() ."' AND `tblDocumentApprovers`.`version` = '". $this->_version ."' ";
|
||
$res = $db->getResultArray($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return false;
|
||
|
||
$db->startTransaction();
|
||
|
||
if($res) {
|
||
foreach($res as $review) {
|
||
$reviewID = $review['reviewID'];
|
||
|
||
/* First, remove the old entries */
|
||
$queryStr = "DELETE from `tblDocumentApproveLog` where `approveID`=".$reviewID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE from `tblDocumentApprovers` where `approveID`=".$reviewID;
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Second, insert the new entries */
|
||
foreach($reviewers as $review) {
|
||
$queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('".$this->_document->getID()."', '".$this->_version."', ".$review['type'] .", ".(is_object($review['required']) ? $review['required']->getID() : (int) $review['required']).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$reviewID = $db->getInsertID('tblDocumentApprovers', 'approveID');
|
||
$reviewlog = array_reverse($review['logs']);
|
||
foreach($reviewlog as $log) {
|
||
if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('".$reviewID ."', '".(int) $log['status']."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".(is_object($log['user']) ? $log['user']->getID() : (int) $log['user']).")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID');
|
||
if(!empty($log['file'])) {
|
||
SeedDMS_Core_File::copyFile($log['file'], $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID);
|
||
}
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
function addIndReviewer($user, $requestUser) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$userID = $user->getID();
|
||
|
||
// Get the list of users and groups with read access to this document.
|
||
if($this->_document->getAccessMode($user) < M_READ) {
|
||
return -2;
|
||
}
|
||
|
||
// Check to see if the user has already been added to the review list.
|
||
$reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
$indstatus = false;
|
||
if (count($reviewStatus["indstatus"]) > 0) {
|
||
$indstatus = array_pop($reviewStatus["indstatus"]);
|
||
if($indstatus["status"]!=-2) {
|
||
// User is already on the list of reviewers; return an error.
|
||
return -3;
|
||
}
|
||
}
|
||
|
||
// Add the user into the review database.
|
||
if (!$indstatus || ($indstatus && $indstatus["status"]!=-2)) {
|
||
$queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '0', '". $userID ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
$reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID');
|
||
}
|
||
else {
|
||
$reviewID = isset($indstatus["reviewID"]) ? $indstatus["reviewID"] : NULL;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $reviewID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
// Add reviewer to event notification table.
|
||
//$this->_document->addNotify($userID, true);
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
function addGrpReviewer($group, $requestUser) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$groupID = $group->getID();
|
||
|
||
// Get the list of users and groups with read access to this document.
|
||
if (!isset($this->_readAccessList)) {
|
||
// TODO: error checking.
|
||
$this->_readAccessList = $this->_document->getReadAccessList();
|
||
}
|
||
$approved = false;
|
||
foreach ($this->_readAccessList["groups"] as $appGroup) {
|
||
if ($groupID == $appGroup->getID()) {
|
||
$approved = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!$approved) {
|
||
return -2;
|
||
}
|
||
|
||
// Check to see if the group has already been added to the review list.
|
||
$reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
if (count($reviewStatus) > 0 && $reviewStatus[0]["status"]!=-2) {
|
||
// Group is already on the list of reviewers; return an error.
|
||
return -3;
|
||
}
|
||
|
||
// Add the group into the review database.
|
||
if (!isset($reviewStatus[0]["status"]) || (isset($reviewStatus[0]["status"]) && $reviewStatus[0]["status"]!=-2)) {
|
||
$queryStr = "INSERT INTO `tblDocumentReviewers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '1', '". $groupID ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
$reviewID = $db->getInsertID('tblDocumentReviewers', 'reviewID');
|
||
}
|
||
else {
|
||
$reviewID = isset($reviewStatus[0]["reviewID"])?$reviewStatus[0]["reviewID"]:NULL;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $reviewID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
// Add reviewer to event notification table.
|
||
//$this->_document->addNotify($groupID, false);
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a review to the document content
|
||
*
|
||
* This method will add an entry to the table tblDocumentReviewLog.
|
||
* It will first check if the user is ment to review the document version.
|
||
* It not the return value is -3.
|
||
* Next it will check if the users has been removed from the list of
|
||
* reviewers. In that case -4 will be returned.
|
||
* If the given review status has been set by the user before, it cannot
|
||
* be set again and 0 will be returned. Іf the review could be succesfully
|
||
* added, the review log id will be returned.
|
||
*
|
||
* @see SeedDMS_Core_DocumentContent::setApprovalByInd()
|
||
* @param object $user user doing the review
|
||
* @param object $requestUser user asking for the review, this is mostly
|
||
* the user currently logged in.
|
||
* @param integer $status status of review
|
||
* @param string $comment comment for review
|
||
* @return integer new review log id
|
||
*/
|
||
function setReviewByInd($user, $requestUser, $status, $comment, $file='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
// Check to see if the user can be removed from the review list.
|
||
$reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
if (count($reviewStatus["indstatus"])==0) {
|
||
// User is not assigned to review this document. No action required.
|
||
// Return an error.
|
||
return -3;
|
||
}
|
||
$indstatus = array_pop($reviewStatus["indstatus"]);
|
||
if ($indstatus["status"]==-2) {
|
||
// User has been deleted from reviewers
|
||
return -4;
|
||
}
|
||
// Check if the status is really different from the current status
|
||
if ($indstatus["status"] == $status)
|
||
return 0;
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`,
|
||
`comment`, `date`, `userID`) ".
|
||
"VALUES ('". $indstatus["reviewID"] ."', '".
|
||
(int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '".
|
||
$requestUser->getID() ."')";
|
||
$res=$db->getResult($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return -1;
|
||
|
||
$reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID');
|
||
if($file) {
|
||
SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID);
|
||
}
|
||
return $reviewLogID;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a review to the document content
|
||
*
|
||
* This method is similar to
|
||
* {@see SeedDMS_Core_DocumentContent::setReviewByInd()} but adds a review
|
||
* for a group instead of a user.
|
||
*
|
||
* @param object $group group doing the review
|
||
* @param object $requestUser user asking for the review, this is mostly
|
||
* the user currently logged in.
|
||
* @param integer $status status of review
|
||
* @param string $comment comment for review
|
||
* @return integer new review log id
|
||
*/
|
||
function setReviewByGrp($group, $requestUser, $status, $comment, $file='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
// Check to see if the user can be removed from the review list.
|
||
$reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
if (count($reviewStatus)==0) {
|
||
// User is not assigned to review this document. No action required.
|
||
// Return an error.
|
||
return -3;
|
||
}
|
||
if ($reviewStatus[0]["status"]==-2) {
|
||
// Group has been deleted from reviewers
|
||
return -4;
|
||
}
|
||
|
||
// Check if the status is really different from the current status
|
||
if ($reviewStatus[0]["status"] == $status)
|
||
return 0;
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`,
|
||
`comment`, `date`, `userID`) ".
|
||
"VALUES ('". $reviewStatus[0]["reviewID"] ."', '".
|
||
(int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '".
|
||
$requestUser->getID() ."')";
|
||
$res=$db->getResult($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return -1;
|
||
else {
|
||
$reviewLogID = $db->getInsertID('tblDocumentReviewLog', 'reviewLogID');
|
||
if($file) {
|
||
SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'r' . $reviewLogID);
|
||
}
|
||
return $reviewLogID;
|
||
}
|
||
} /* }}} */
|
||
|
||
function addIndApprover($user, $requestUser) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$userID = $user->getID();
|
||
|
||
// Get the list of users and groups with read access to this document.
|
||
if($this->_document->getAccessMode($user) < M_READ) {
|
||
return -2;
|
||
}
|
||
|
||
// Check to see if the user has already been added to the approvers list.
|
||
$approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
$indstatus = false;
|
||
if (count($approvalStatus["indstatus"]) > 0) {
|
||
$indstatus = array_pop($approvalStatus["indstatus"]);
|
||
if($indstatus["status"]!=-2) {
|
||
// User is already on the list of approverss; return an error.
|
||
return -3;
|
||
}
|
||
}
|
||
|
||
if ( !$indstatus || (isset($indstatus["status"]) && $indstatus["status"]!=-2)) {
|
||
// Add the user into the approvers database.
|
||
$queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '0', '". $userID ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
$approveID = $db->getInsertID('tblDocumentApprovers', 'approveID');
|
||
}
|
||
else {
|
||
$approveID = isset($indstatus["approveID"]) ? $indstatus["approveID"] : NULL;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $approveID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
$approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID');
|
||
return $approveLogID;
|
||
} /* }}} */
|
||
|
||
function addGrpApprover($group, $requestUser) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$groupID = $group->getID();
|
||
|
||
// Get the list of users and groups with read access to this document.
|
||
if (!isset($this->_readAccessList)) {
|
||
// TODO: error checking.
|
||
$this->_readAccessList = $this->_document->getReadAccessList();
|
||
}
|
||
$approved = false;
|
||
foreach ($this->_readAccessList["groups"] as $appGroup) {
|
||
if ($groupID == $appGroup->getID()) {
|
||
$approved = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!$approved) {
|
||
return -2;
|
||
}
|
||
|
||
// Check to see if the group has already been added to the approver list.
|
||
$approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
if (count($approvalStatus) > 0 && $approvalStatus[0]["status"]!=-2) {
|
||
// Group is already on the list of approvers; return an error.
|
||
return -3;
|
||
}
|
||
|
||
// Add the group into the approver database.
|
||
if (!isset($approvalStatus[0]["status"]) || (isset($approvalStatus[0]["status"]) && $approvalStatus[0]["status"]!=-2)) {
|
||
$queryStr = "INSERT INTO `tblDocumentApprovers` (`documentID`, `version`, `type`, `required`) ".
|
||
"VALUES ('". $this->_document->getID() ."', '". $this->_version ."', '1', '". $groupID ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
$approveID = $db->getInsertID('tblDocumentApprovers', 'approveID');
|
||
}
|
||
else {
|
||
$approveID = isset($approvalStatus[0]["approveID"])?$approvalStatus[0]["approveID"]:NULL;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $approveID ."', '0', '', ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
// Add approver to event notification table.
|
||
//$this->_document->addNotify($groupID, false);
|
||
|
||
$approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID');
|
||
return $approveLogID;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Sets approval status of a document content for a user
|
||
*
|
||
* This function can be used to approve or reject a document content, or
|
||
* to reset its approval state. In most cases this function will be
|
||
* called by an user, but an admin may set the approval for
|
||
* somebody else.
|
||
* It is first checked if the user is in the list of approvers at all.
|
||
* Then it is check if the approval status is already -2. In both cases
|
||
* the function returns with an error.
|
||
*
|
||
* @see SeedDMS_Core_DocumentContent::setReviewByInd()
|
||
* @param object $user user in charge for doing the approval
|
||
* @param object $requestUser user actually calling this function
|
||
* @param integer $status the status of the approval, possible values are
|
||
* 0=unprocessed (maybe used to reset a status)
|
||
* 1=approved,
|
||
* -1=rejected,
|
||
* -2=user is deleted (use {link
|
||
* SeedDMS_Core_DocumentContent::delIndApprover} instead)
|
||
* @param string $comment approval comment
|
||
* @return integer 0 on success, < 0 in case of an error
|
||
*/
|
||
function setApprovalByInd($user, $requestUser, $status, $comment, $file='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
// Check to see if the user can be removed from the approval list.
|
||
$approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
if (count($approvalStatus["indstatus"])==0) {
|
||
// User is not assigned to approve this document. No action required.
|
||
// Return an error.
|
||
return -3;
|
||
}
|
||
$indstatus = array_pop($approvalStatus["indstatus"]);
|
||
if ($indstatus["status"]==-2) {
|
||
// User has been deleted from approvers
|
||
return -4;
|
||
}
|
||
// Check if the status is really different from the current status
|
||
if ($indstatus["status"] == $status)
|
||
return 0;
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`,
|
||
`comment`, `date`, `userID`) ".
|
||
"VALUES ('". $indstatus["approveID"] ."', '".
|
||
(int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '".
|
||
$requestUser->getID() ."')";
|
||
$res=$db->getResult($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return -1;
|
||
|
||
$approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID');
|
||
if($file) {
|
||
SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID);
|
||
}
|
||
return $approveLogID;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Sets approval status of a document content for a group
|
||
* The functions behaves like
|
||
* {link SeedDMS_Core_DocumentContent::setApprovalByInd} but does it for
|
||
* group instead of a user
|
||
*/
|
||
function setApprovalByGrp($group, $requestUser, $status, $comment, $file='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
// Check to see if the user can be removed from the approval list.
|
||
$approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
if (count($approvalStatus)==0) {
|
||
// User is not assigned to approve this document. No action required.
|
||
// Return an error.
|
||
return -3;
|
||
}
|
||
if ($approvalStatus[0]["status"]==-2) {
|
||
// Group has been deleted from approvers
|
||
return -4;
|
||
}
|
||
|
||
// Check if the status is really different from the current status
|
||
if ($approvalStatus[0]["status"] == $status)
|
||
return 0;
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`,
|
||
`comment`, `date`, `userID`) ".
|
||
"VALUES ('". $approvalStatus[0]["approveID"] ."', '".
|
||
(int) $status ."', ".$db->qstr($comment).", ".$db->getCurrentDatetime().", '".
|
||
$requestUser->getID() ."')";
|
||
$res=$db->getResult($queryStr);
|
||
if (is_bool($res) && !$res)
|
||
return -1;
|
||
|
||
$approveLogID = $db->getInsertID('tblDocumentApproveLog', 'approveLogID');
|
||
if($file) {
|
||
SeedDMS_Core_File::copyFile($file, $this->_dms->contentDir . $this->_document->getDir() . 'a' . $approveLogID);
|
||
}
|
||
return $approveLogID;
|
||
} /* }}} */
|
||
|
||
function delIndReviewer($user, $requestUser, $msg='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
// Check to see if the user can be removed from the review list.
|
||
$reviewStatus = $user->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
if (count($reviewStatus["indstatus"])==0) {
|
||
// User is not assigned to review this document. No action required.
|
||
// Return an error.
|
||
return -2;
|
||
}
|
||
$indstatus = array_pop($reviewStatus["indstatus"]);
|
||
if ($indstatus["status"]!=0) {
|
||
// User has already submitted a review or has already been deleted;
|
||
// return an error.
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $indstatus["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
function delGrpReviewer($group, $requestUser, $msg='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$groupID = $group->getID();
|
||
|
||
// Check to see if the user can be removed from the review list.
|
||
$reviewStatus = $group->getReviewStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($reviewStatus) && !$reviewStatus) {
|
||
return -1;
|
||
}
|
||
if (count($reviewStatus)==0) {
|
||
// User is not assigned to review this document. No action required.
|
||
// Return an error.
|
||
return -2;
|
||
}
|
||
if ($reviewStatus[0]["status"]!=0) {
|
||
// User has already submitted a review or has already been deleted;
|
||
// return an error.
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $reviewStatus[0]["reviewID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
function delIndApprover($user, $requestUser, $msg='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$userID = $user->getID();
|
||
|
||
// Check to see if the user can be removed from the approval list.
|
||
$approvalStatus = $user->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
if (count($approvalStatus["indstatus"])==0) {
|
||
// User is not assigned to approve this document. No action required.
|
||
// Return an error.
|
||
return -2;
|
||
}
|
||
$indstatus = array_pop($approvalStatus["indstatus"]);
|
||
if ($indstatus["status"]!=0) {
|
||
// User has already submitted an approval or has already been deleted;
|
||
// return an error.
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $indstatus["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
function delGrpApprover($group, $requestUser, $msg='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$groupID = $group->getID();
|
||
|
||
// Check to see if the user can be removed from the approver list.
|
||
$approvalStatus = $group->getApprovalStatus($this->_document->getID(), $this->_version);
|
||
if (is_bool($approvalStatus) && !$approvalStatus) {
|
||
return -1;
|
||
}
|
||
if (count($approvalStatus)==0) {
|
||
// User is not assigned to approve this document. No action required.
|
||
// Return an error.
|
||
return -2;
|
||
}
|
||
if ($approvalStatus[0]["status"]!=0) {
|
||
// User has already submitted an approval or has already been deleted;
|
||
// return an error.
|
||
return -3;
|
||
}
|
||
|
||
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
|
||
"VALUES ('". $approvalStatus[0]["approveID"] ."', '".S_LOG_USER_REMOVED."', ".$db->qstr($msg).", ".$db->getCurrentDatetime().", '". $requestUser->getID() ."')";
|
||
$res = $db->getResult($queryStr);
|
||
if (is_bool($res) && !$res) {
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set state of workflow assigned to the document content
|
||
*
|
||
* @param object $state
|
||
*/
|
||
function setWorkflowState($state) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if($this->_workflow) {
|
||
$queryStr = "UPDATE `tblWorkflowDocumentContent` set `state`=". $state->getID() ." WHERE `workflow`=". intval($this->_workflow->getID()). " AND `document`=". intval($this->_document->getID()) ." AND version=". intval($this->_version) ."";
|
||
if (!$db->getResult($queryStr)) {
|
||
return false;
|
||
}
|
||
$this->_workflowState = $state;
|
||
return true;
|
||
}
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get state of workflow assigned to the document content
|
||
*
|
||
* @return object/boolean an object of class SeedDMS_Core_Workflow_State
|
||
* or false in case of error, e.g. the version has not a workflow
|
||
*/
|
||
function getWorkflowState() { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
if (!$this->_workflowState) {
|
||
$queryStr=
|
||
"SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflowStates` b ON a.`state` = b.`id` WHERE `workflow`=". intval($this->_workflow->getID())
|
||
." AND a.`version`='".$this->_version
|
||
."' AND a.`document` = '". $this->_document->getID() ."' ";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs)
|
||
return false;
|
||
$this->_workflowState = new SeedDMS_Core_Workflow_State($recs[0]['id'], $recs[0]['name'], $recs[0]['maxtime'], $recs[0]['precondfunc'], $recs[0]['documentstatus']);
|
||
$this->_workflowState->setDMS($this->_document->getDMS());
|
||
}
|
||
return $this->_workflowState;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Assign a workflow to a document
|
||
*
|
||
* @param object $workflow
|
||
*/
|
||
function setWorkflow($workflow, $user) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$this->getWorkflow();
|
||
if($workflow && is_object($workflow)) {
|
||
$db->startTransaction();
|
||
$initstate = $workflow->getInitState();
|
||
$queryStr = "INSERT INTO `tblWorkflowDocumentContent` (`workflow`, `document`, `version`, `state`, `date`) VALUES (". $workflow->getID(). ", ". $this->_document->getID() .", ". $this->_version .", ".$initstate->getID().", ".$db->getCurrentDatetime().")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$this->_workflow = $workflow;
|
||
if(!$this->setStatus(S_IN_WORKFLOW, "Added workflow '".$workflow->getName()."'", $user)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$db->commitTransaction();
|
||
return true;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get workflow assigned to the document content
|
||
*
|
||
* The method returns the last workflow if one was assigned.
|
||
* If a the document version is in a sub workflow, it will have
|
||
* a never date and therefore will be found first.
|
||
*
|
||
* @return object/boolean an object of class SeedDMS_Core_Workflow
|
||
* or false in case of error, e.g. the version has not a workflow
|
||
*/
|
||
function getWorkflow() { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if (!isset($this->_workflow)) {
|
||
$queryStr=
|
||
"SELECT b.* FROM `tblWorkflowDocumentContent` a LEFT JOIN `tblWorkflows` b ON a.`workflow` = b.`id` WHERE a.`version`='".$this->_version
|
||
."' AND a.`document` = '". $this->_document->getID() ."' "
|
||
." ORDER BY `date` DESC LIMIT 1";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs)
|
||
return false;
|
||
if(!$recs)
|
||
return false;
|
||
$this->_workflow = new SeedDMS_Core_Workflow($recs[0]['id'], $recs[0]['name'], $this->_document->getDMS()->getWorkflowState($recs[0]['initstate']));
|
||
$this->_workflow->setDMS($this->_document->getDMS());
|
||
}
|
||
return $this->_workflow;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Rewrites the complete workflow log
|
||
*
|
||
* Attention: this function is highly dangerous.
|
||
* It removes an existing workflow log and rewrites it.
|
||
* This method was added for importing an xml dump.
|
||
*
|
||
* @param array $workflowlog new workflow log with the newest log entry first.
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function rewriteWorkflowLog($workflowlog) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$db->startTransaction();
|
||
|
||
/* First, remove the old entries */
|
||
$queryStr = "DELETE FROM `tblWorkflowLog` WHERE `tblWorkflowLog`.`document` = '". $this->_document->getID() ."' AND `tblWorkflowLog`.`version` = '". $this->_version ."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
/* Second, insert the new entries */
|
||
$workflowlog = array_reverse($workflowlog);
|
||
foreach($workflowlog as $log) {
|
||
if(!SeedDMS_Core_DMS::checkDate($log['date'], 'Y-m-d H:i:s')) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblWorkflowLog` (`document`, `version`, `workflow`, `transition`, `comment`, `date`, `userid`) ".
|
||
"VALUES ('".$this->_document->getID() ."', '".(int) $this->_version."', '".(int) $log['workflow']->getID()."', '".(int) $log['transition']->getID()."', ".$db->qstr($log['comment']) .", ".$db->qstr($log['date']).", ".$log['user']->getID().")";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Restart workflow from its initial state
|
||
*
|
||
* @return boolean true if workflow could be restarted
|
||
* or false in case of error
|
||
*/
|
||
function rewindWorkflow() { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$this->getWorkflow();
|
||
|
||
if (!isset($this->_workflow)) {
|
||
return true;
|
||
}
|
||
|
||
$db->startTransaction();
|
||
$queryStr = "DELETE from `tblWorkflowLog` WHERE `document` = ". $this->_document->getID() ." AND `version` = ".$this->_version." AND `workflow` = ".$this->_workflow->getID();
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$this->setWorkflowState($this->_workflow->getInitState());
|
||
$db->commitTransaction();
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Remove workflow
|
||
*
|
||
* Fully removing a workflow including entries in the workflow log is
|
||
* only allowed if the workflow is still its initial state.
|
||
* At a later point of time only unlinking the document from the
|
||
* workflow is allowed. It will keep any log entries.
|
||
* A workflow is unlinked from a document when enterNextState()
|
||
* succeeds.
|
||
*
|
||
* @param object $user user doing initiating the removal
|
||
* @param boolean $unlink if true, just unlink the workflow from the
|
||
* document but do not remove the workflow log. The $unlink
|
||
* flag has been added to detach the workflow from the document
|
||
* when it has reached a valid end state
|
||
(see SeedDMS_Core_DocumentContent::enterNextState())
|
||
* @return boolean true if workflow could be removed
|
||
* or false in case of error
|
||
*/
|
||
function removeWorkflow($user, $unlink=false) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$this->getWorkflow();
|
||
|
||
if (!isset($this->_workflow)) {
|
||
return true;
|
||
}
|
||
|
||
if(SeedDMS_Core_DMS::checkIfEqual($this->_workflow->getInitState(), $this->getWorkflowState()) || $unlink == true) {
|
||
$db->startTransaction();
|
||
$queryStr=
|
||
"DELETE FROM `tblWorkflowDocumentContent` WHERE "
|
||
."`version`='".$this->_version."' "
|
||
." AND `document` = '". $this->_document->getID() ."' "
|
||
." AND `workflow` = '". $this->_workflow->getID() ."' ";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
if(!$unlink) {
|
||
$queryStr=
|
||
"DELETE FROM `tblWorkflowLog` WHERE "
|
||
."`version`='".$this->_version."' "
|
||
." AND `document` = '". $this->_document->getID() ."' "
|
||
." AND `workflow` = '". $this->_workflow->getID() ."' ";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
$this->_workflow = null;
|
||
$this->_workflowState = null;
|
||
$this->verifyStatus(false, $user, 'Workflow removed');
|
||
$db->commitTransaction();
|
||
}
|
||
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Run a sub workflow
|
||
*
|
||
* @param object $subworkflow
|
||
*/
|
||
function getParentWorkflow() { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
/* document content must be in a workflow */
|
||
$this->getWorkflow();
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
$queryStr=
|
||
"SELECT * FROM `tblWorkflowDocumentContent` WHERE "
|
||
."`version`='".$this->_version."' "
|
||
." AND `document` = '". $this->_document->getID() ."' "
|
||
." AND `workflow` = '". $this->_workflow->getID() ."' ";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs)
|
||
return false;
|
||
if(!$recs)
|
||
return false;
|
||
|
||
if($recs[0]['parentworkflow'])
|
||
return $this->_document->getDMS()->getWorkflow($recs[0]['parentworkflow']);
|
||
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Run a sub workflow
|
||
*
|
||
* @param object $subworkflow
|
||
*/
|
||
function runSubWorkflow($subworkflow) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
/* document content must be in a workflow */
|
||
$this->getWorkflow();
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
/* The current workflow state must match the sub workflows initial state */
|
||
if($subworkflow->getInitState()->getID() != $this->_workflowState->getID())
|
||
return false;
|
||
|
||
if($subworkflow) {
|
||
$initstate = $subworkflow->getInitState();
|
||
$queryStr = "INSERT INTO `tblWorkflowDocumentContent` (`parentworkflow`, `workflow`, `document`, `version`, `state`, `date`) VALUES (". $this->_workflow->getID(). ", ". $subworkflow->getID(). ", ". $this->_document->getID() .", ". $this->_version .", ".$initstate->getID().", ".$db->getCurrentDatetime().")";
|
||
if (!$db->getResult($queryStr)) {
|
||
return false;
|
||
}
|
||
$this->_workflow = $subworkflow;
|
||
return true;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return from sub workflow to parent workflow.
|
||
* The method will trigger the given transition
|
||
*
|
||
* FIXME: Needs much better checking if this is allowed
|
||
*
|
||
* @param object $user intiating the return
|
||
* @param object $transtion to trigger
|
||
* @param string comment for the transition trigger
|
||
*/
|
||
function returnFromSubWorkflow($user, $transition=null, $comment='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
/* document content must be in a workflow */
|
||
$this->getWorkflow();
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
if (isset($this->_workflow)) {
|
||
$db->startTransaction();
|
||
|
||
$queryStr=
|
||
"SELECT * FROM `tblWorkflowDocumentContent` WHERE `workflow`=". intval($this->_workflow->getID())
|
||
. " AND `version`='".$this->_version
|
||
."' AND `document` = '". $this->_document->getID() ."' ";
|
||
$recs = $db->getResultArray($queryStr);
|
||
if (is_bool($recs) && !$recs) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
if(!$recs) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "DELETE FROM `tblWorkflowDocumentContent` WHERE `workflow` =". intval($this->_workflow->getID())." AND `document` = '". $this->_document->getID() ."' AND `version` = '" . $this->_version."'";
|
||
if (!$db->getResult($queryStr)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
|
||
$this->_workflow = $this->_document->getDMS()->getWorkflow($recs[0]['parentworkflow']);
|
||
$this->_workflow->setDMS($this->_document->getDMS());
|
||
|
||
if($transition) {
|
||
if(false === $this->triggerWorkflowTransition($user, $transition, $comment)) {
|
||
$db->rollbackTransaction();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
$db->commitTransaction();
|
||
}
|
||
return $this->_workflow;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if the user is allowed to trigger the transition
|
||
* A user is allowed if either the user itself or
|
||
* a group of which the user is a member of is registered for
|
||
* triggering a transition. This method does not change the workflow
|
||
* state of the document content.
|
||
*
|
||
* @param object $user
|
||
* @return boolean true if user may trigger transaction
|
||
*/
|
||
function triggerWorkflowTransitionIsAllowed($user, $transition) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
if(!$this->_workflowState)
|
||
$this->getWorkflowState();
|
||
|
||
/* Check if the user has already triggered the transition */
|
||
$queryStr=
|
||
"SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."' AND `workflow` = ". $this->_workflow->getID(). " AND userid = ".$user->getID();
|
||
$queryStr .= " AND `transition` = ".$transition->getID();
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
if(count($resArr))
|
||
return false;
|
||
|
||
/* Get all transition users allowed to trigger the transition */
|
||
$transusers = $transition->getUsers();
|
||
if($transusers) {
|
||
foreach($transusers as $transuser) {
|
||
if($user->getID() == $transuser->getUser()->getID())
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/* Get all transition groups whose members are allowed to trigger
|
||
* the transition */
|
||
$transgroups = $transition->getGroups();
|
||
if($transgroups) {
|
||
foreach($transgroups as $transgroup) {
|
||
$group = $transgroup->getGroup();
|
||
if($group->isMember($user))
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if all conditions are met to change the workflow state
|
||
* of a document content (run the transition).
|
||
* The conditions are met if all explicitly set users and a sufficient
|
||
* number of users of the groups have acknowledged the content.
|
||
*
|
||
* @return boolean true if transaction maybe executed
|
||
*/
|
||
function executeWorkflowTransitionIsAllowed($transition) { /* {{{ */
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
if(!$this->_workflowState)
|
||
$this->getWorkflowState();
|
||
|
||
/* Get the Log of transition triggers */
|
||
$entries = $this->getWorkflowLog($transition);
|
||
if(!$entries)
|
||
return false;
|
||
|
||
/* Get all transition users allowed to trigger the transition
|
||
* $allowedusers is a list of all users allowed to trigger the
|
||
* transition
|
||
*/
|
||
$transusers = $transition->getUsers();
|
||
$allowedusers = array();
|
||
foreach($transusers as $transuser) {
|
||
$a = $transuser->getUser();
|
||
$allowedusers[$a->getID()] = $a;
|
||
}
|
||
|
||
/* Get all transition groups whose members are allowed to trigger
|
||
* the transition */
|
||
$transgroups = $transition->getGroups();
|
||
foreach($entries as $entry) {
|
||
$loguser = $entry->getUser();
|
||
/* Unset each allowed user if it was found in the log */
|
||
if(isset($allowedusers[$loguser->getID()]))
|
||
unset($allowedusers[$loguser->getID()]);
|
||
/* Also check groups if required. Count the group membership of
|
||
* each user in the log in the array $gg
|
||
*/
|
||
if($transgroups) {
|
||
$loggroups = $loguser->getGroups();
|
||
foreach($loggroups as $loggroup) {
|
||
if(!isset($gg[$loggroup->getID()]))
|
||
$gg[$loggroup->getID()] = 1;
|
||
else
|
||
$gg[$loggroup->getID()]++;
|
||
}
|
||
}
|
||
}
|
||
/* If there are allowed users left, then there some users still
|
||
* need to trigger the transition.
|
||
*/
|
||
if($allowedusers)
|
||
return false;
|
||
|
||
if($transgroups) {
|
||
foreach($transgroups as $transgroup) {
|
||
$group = $transgroup->getGroup();
|
||
$minusers = $transgroup->getNumOfUsers();
|
||
if(!isset($gg[$group->getID()]))
|
||
return false;
|
||
if($gg[$group->getID()] < $minusers)
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Trigger transition
|
||
*
|
||
* This method will be deprecated
|
||
*
|
||
* The method will first check if the user is allowed to trigger the
|
||
* transition. If the user is allowed, an entry in the workflow log
|
||
* will be added, which is later used to check if the transition
|
||
* can actually be processed. The method will finally call
|
||
* executeWorkflowTransitionIsAllowed() which checks all log entries
|
||
* and does the transitions post function if all users and groups have
|
||
* triggered the transition. Finally enterNextState() is called which
|
||
* will try to enter the next state.
|
||
*
|
||
* @param object $user
|
||
* @param object $transition
|
||
* @param string $comment user comment
|
||
* @return boolean/object next state if transition could be triggered and
|
||
* then next state could be entered,
|
||
* true if the transition could just be triggered or
|
||
* false in case of an error
|
||
*/
|
||
function triggerWorkflowTransition($user, $transition, $comment='') { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
if(!$this->_workflowState)
|
||
$this->getWorkflowState();
|
||
|
||
if(!$this->_workflowState)
|
||
return false;
|
||
|
||
/* Check if the user is allowed to trigger the transition.
|
||
*/
|
||
if(!$this->triggerWorkflowTransitionIsAllowed($user, $transition))
|
||
return false;
|
||
|
||
$state = $this->_workflowState;
|
||
$queryStr = "INSERT INTO `tblWorkflowLog` (`document`, `version`, `workflow`, `userid`, `transition`, `date`, `comment`) VALUES (".$this->_document->getID().", ".$this->_version.", " . (int) $this->_workflow->getID() . ", " .(int) $user->getID(). ", ".(int) $transition->getID().", ".$db->getCurrentDatetime().", ".$db->qstr($comment).")";
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
/* Check if this transition is processed. Run the post function in
|
||
* that case. A transition is processed when all users and groups
|
||
* have triggered it.
|
||
*/
|
||
if($this->executeWorkflowTransitionIsAllowed($transition)) {
|
||
/* run post function of transition */
|
||
// echo "run post function of transition ".$transition->getID()."<br />";
|
||
}
|
||
|
||
/* Go into the next state. This will only succeed if the pre condition
|
||
* function of that states succeeds.
|
||
*/
|
||
$nextstate = $transition->getNextState();
|
||
if($this->enterNextState($user, $nextstate)) {
|
||
return $nextstate;
|
||
}
|
||
return true;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Enter next state of workflow if possible
|
||
*
|
||
* The method will check if one of the following states in the workflow
|
||
* can be reached.
|
||
* It does it by running
|
||
* the precondition function of that state. The precondition function
|
||
* gets a list of all transitions leading to the state. It will
|
||
* determine, whether the transitions has been triggered and if that
|
||
* is sufficient to enter the next state. If no pre condition function
|
||
* is set, then 1 of n transtions are enough to enter the next state.
|
||
*
|
||
* If moving in the next state is possible and this state has a
|
||
* corresponding document state, then the document state will be
|
||
* updated and the workflow will be detached from the document.
|
||
*
|
||
* @param object $user
|
||
* @param object $nextstate
|
||
* @return boolean true if the state could be reached
|
||
* false if not
|
||
*/
|
||
function enterNextState($user, $nextstate) { /* {{{ */
|
||
|
||
/* run the pre condition of the next state. If it is not set
|
||
* the next state will be reached if one of the transitions
|
||
* leading to the given state can be processed.
|
||
*/
|
||
if($nextstate->getPreCondFunc() == '') {
|
||
$transitions = $this->_workflow->getPreviousTransitions($nextstate);
|
||
foreach($transitions as $transition) {
|
||
// echo "transition ".$transition->getID()." led to state ".$nextstate->getName()."<br />";
|
||
if($this->executeWorkflowTransitionIsAllowed($transition)) {
|
||
// echo "stepping into next state<br />";
|
||
$this->setWorkflowState($nextstate);
|
||
|
||
/* Check if the new workflow state has a mapping into a
|
||
* document state. If yes, set the document state will
|
||
* be updated and the workflow will be removed from the
|
||
* document.
|
||
*/
|
||
$docstate = $nextstate->getDocumentStatus();
|
||
if($docstate == S_RELEASED || $docstate == S_REJECTED) {
|
||
$this->setStatus($docstate, "Workflow has ended", $user);
|
||
/* Detach the workflow from the document, but keep the
|
||
* workflow log
|
||
*/
|
||
$this->removeWorkflow($user, true);
|
||
return true ;
|
||
}
|
||
|
||
/* make sure the users and groups allowed to trigger the next
|
||
* transitions are also allowed to read the document
|
||
*/
|
||
$transitions = $this->_workflow->getNextTransitions($nextstate);
|
||
foreach($transitions as $tran) {
|
||
// echo "checking access for users/groups allowed to trigger transition ".$tran->getID()."<br />";
|
||
$transusers = $tran->getUsers();
|
||
foreach($transusers as $transuser) {
|
||
$u = $transuser->getUser();
|
||
// echo $u->getFullName()."<br />";
|
||
if($this->_document->getAccessMode($u) < M_READ) {
|
||
$this->_document->addAccess(M_READ, $u->getID(), 1);
|
||
// echo "granted read access<br />";
|
||
} else {
|
||
// echo "has already access<br />";
|
||
}
|
||
}
|
||
$transgroups = $tran->getGroups();
|
||
foreach($transgroups as $transgroup) {
|
||
$g = $transgroup->getGroup();
|
||
// echo $g->getName()."<br />";
|
||
if ($this->_document->getGroupAccessMode($g) < M_READ) {
|
||
$this->_document->addAccess(M_READ, $g->getID(), 0);
|
||
// echo "granted read access<br />";
|
||
} else {
|
||
// echo "has already access<br />";
|
||
}
|
||
}
|
||
}
|
||
return(true);
|
||
} else {
|
||
// echo "transition not ready for process now<br />";
|
||
}
|
||
}
|
||
return false;
|
||
} else {
|
||
}
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the so far logged operations on the document content within the
|
||
* workflow
|
||
*
|
||
* @return array list of operations
|
||
*/
|
||
function getWorkflowLog($transition = null) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
/*
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
*/
|
||
$queryStr=
|
||
"SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."'"; // AND `workflow` = ". $this->_workflow->getID();
|
||
if($transition)
|
||
$queryStr .= " AND `transition` = ".$transition->getID();
|
||
$queryStr .= " ORDER BY `date`";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$workflowlogs = array();
|
||
for ($i = 0; $i < count($resArr); $i++) {
|
||
$workflow = $this->_document->getDMS()->getWorkflow($resArr[$i]["workflow"]);
|
||
$workflowlog = new SeedDMS_Core_Workflow_Log($resArr[$i]["id"], $this->_document->getDMS()->getDocument($resArr[$i]["document"]), $resArr[$i]["version"], $workflow, $this->_document->getDMS()->getUser($resArr[$i]["userid"]), $workflow->getTransition($resArr[$i]["transition"]), $resArr[$i]["date"], $resArr[$i]["comment"]);
|
||
$workflowlog->setDMS($this);
|
||
$workflowlogs[$i] = $workflowlog;
|
||
}
|
||
|
||
return $workflowlogs;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get the latest logged transition for the document content within the
|
||
* workflow
|
||
*
|
||
* @return array list of operations
|
||
*/
|
||
function getLastWorkflowTransition() { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$this->_workflow)
|
||
$this->getWorkflow();
|
||
|
||
if(!$this->_workflow)
|
||
return false;
|
||
|
||
$queryStr=
|
||
"SELECT * FROM `tblWorkflowLog` WHERE `version`='".$this->_version ."' AND `document` = '". $this->_document->getID() ."' AND `workflow` = ". $this->_workflow->getID();
|
||
$queryStr .= " ORDER BY `id` DESC LIMIT 1";
|
||
$resArr = $db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$workflowlogs = array();
|
||
$i = 0;
|
||
$workflowlog = new SeedDMS_Core_Workflow_Log($resArr[$i]["id"], $this->_document->getDMS()->getDocument($resArr[$i]["document"]), $resArr[$i]["version"], $this->_workflow, $this->_document->getDMS()->getUser($resArr[$i]["userid"]), $this->_workflow->getTransition($resArr[$i]["transition"]), $resArr[$i]["date"], $resArr[$i]["comment"]);
|
||
$workflowlog->setDMS($this);
|
||
|
||
return $workflowlog;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Check if the document content needs an action by a user
|
||
*
|
||
* This method will return true if document content is in a transition
|
||
* which can be triggered by the given user.
|
||
*
|
||
* @param SeedDMS_Core_User $user
|
||
* @return boolean true is action is needed
|
||
*/
|
||
function needsWorkflowAction($user) { /* {{{ */
|
||
$needwkflaction = false;
|
||
if($this->_workflow) {
|
||
if (!$this->_workflowState)
|
||
$this->getWorkflowState();
|
||
$workflowstate = $this->_workflowState;
|
||
if($transitions = $this->_workflow->getNextTransitions($workflowstate)) {
|
||
foreach($transitions as $transition) {
|
||
if($this->triggerWorkflowTransitionIsAllowed($user, $transition)) {
|
||
$needwkflaction = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $needwkflaction;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Checks the internal data of the document version and repairs it.
|
||
* Currently, this function only repairs a missing filetype
|
||
*
|
||
* @return boolean true on success, otherwise false
|
||
*/
|
||
function repair() { /* {{{ */
|
||
$dms = $this->_document->getDMS();
|
||
$db = $this->_dms->getDB();
|
||
|
||
if(file_exists($this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType)) {
|
||
if(strlen($this->_fileType) < 2) {
|
||
switch($this->_mimeType) {
|
||
case "application/pdf":
|
||
case "image/png":
|
||
case "image/gif":
|
||
case "image/jpg":
|
||
$expect = substr($this->_mimeType, -3, 3);
|
||
if($this->_fileType != '.'.$expect) {
|
||
$db->startTransaction();
|
||
$queryStr = "UPDATE `tblDocumentContent` SET `fileType`='.".$expect."' WHERE `id` = ". $this->_id;
|
||
$res = $db->getResult($queryStr);
|
||
if ($res) {
|
||
if(!SeedDMS_Core_File::renameFile($this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType, $this->_dms->contentDir.$this->_document->getDir() . $this->_version . '.' . $expect)) {
|
||
$db->rollbackTransaction();
|
||
} else {
|
||
$db->commitTransaction();
|
||
}
|
||
} else {
|
||
$db->rollbackTransaction();
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
} elseif(file_exists($this->_document->getDir() . $this->_version . '.')) {
|
||
echo "no file";
|
||
} else {
|
||
echo $this->_dms->contentDir.$this->_document->getDir() . $this->_version . $this->_fileType;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
} /* }}} */
|
||
|
||
|
||
/**
|
||
* Class to represent a link between two document
|
||
*
|
||
* Document links are to establish a reference from one document to
|
||
* another document. The owner of the document link may not be the same
|
||
* as the owner of one of the documents.
|
||
* Use {@link SeedDMS_Core_Document::addDocumentLink()} to add a reference
|
||
* to another document.
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||
* 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_DocumentLink { /* {{{ */
|
||
/**
|
||
* @var integer internal id of document link
|
||
*/
|
||
protected $_id;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_Document reference to document this link belongs to
|
||
*/
|
||
protected $_document;
|
||
|
||
/**
|
||
* @var object reference to target document this link points to
|
||
*/
|
||
protected $_target;
|
||
|
||
/**
|
||
* @var integer id of user who is the owner of this link
|
||
*/
|
||
protected $_userID;
|
||
|
||
/**
|
||
* @var integer 1 if this link is public, or 0 if is only visible to the owner
|
||
*/
|
||
protected $_public;
|
||
|
||
/**
|
||
* SeedDMS_Core_DocumentLink constructor.
|
||
* @param $id
|
||
* @param $document
|
||
* @param $target
|
||
* @param $userID
|
||
* @param $public
|
||
*/
|
||
function __construct($id, $document, $target, $userID, $public) {
|
||
$this->_id = $id;
|
||
$this->_document = $document;
|
||
$this->_target = $target;
|
||
$this->_userID = $userID;
|
||
$this->_public = $public;
|
||
}
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function getID() { return $this->_id; }
|
||
|
||
/**
|
||
* @return SeedDMS_Core_Document
|
||
*/
|
||
function getDocument() {
|
||
return $this->_document;
|
||
}
|
||
|
||
/**
|
||
* @return object
|
||
*/
|
||
function getTarget() {
|
||
return $this->_target;
|
||
}
|
||
|
||
/**
|
||
* @return bool|SeedDMS_Core_User
|
||
*/
|
||
function getUser() {
|
||
if (!isset($this->_user)) {
|
||
$this->_user = $this->_document->getDMS()->getUser($this->_userID);
|
||
}
|
||
return $this->_user;
|
||
}
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function isPublic() { return $this->_public; }
|
||
|
||
/**
|
||
* Returns the access mode similar to a document
|
||
*
|
||
* There is no real access mode for document links, so this is just
|
||
* another way to add more access restrictions than the default restrictions.
|
||
* It is only called for public document links, not accessed by the owner
|
||
* or the administrator.
|
||
*
|
||
* @param SeedDMS_Core_User $u user
|
||
* @param $source
|
||
* @param $target
|
||
* @return int either M_NONE or M_READ
|
||
*/
|
||
function getAccessMode($u, $source, $target) { /* {{{ */
|
||
$dms = $this->_document->getDMS();
|
||
|
||
/* Check if 'onCheckAccessDocumentLink' callback is set */
|
||
if(isset($dms->callbacks['onCheckAccessDocumentLink'])) {
|
||
foreach($dms->callbacks['onCheckAccessDocumentLink'] as $callback) {
|
||
if(($ret = call_user_func($callback[0], $callback[1], $this, $u, $source, $target)) > 0) {
|
||
return $ret;
|
||
}
|
||
}
|
||
}
|
||
|
||
return M_READ;
|
||
} /* }}} */
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Class to represent a file attached to a document
|
||
*
|
||
* Beside the regular document content arbitrary files can be attached
|
||
* to a document. This is a similar concept as attaching files to emails.
|
||
* The owner of the attached file and the document may not be the same.
|
||
* Use {@link SeedDMS_Core_Document::addDocumentFile()} to attach a file.
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||
* 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_DocumentFile { /* {{{ */
|
||
/**
|
||
* @var integer internal id of document file
|
||
*/
|
||
protected $_id;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_Document reference to document this file belongs to
|
||
*/
|
||
protected $_document;
|
||
|
||
/**
|
||
* @var integer id of user who is the owner of this link
|
||
*/
|
||
protected $_userID;
|
||
|
||
/**
|
||
* @var string comment for the attached file
|
||
*/
|
||
protected $_comment;
|
||
|
||
/**
|
||
* @var string date when the file was attached
|
||
*/
|
||
protected $_date;
|
||
|
||
/**
|
||
* @var integer version of document this file is attached to
|
||
*/
|
||
protected $_version;
|
||
|
||
/**
|
||
* @var integer 1 if this link is public, or 0 if is only visible to the owner
|
||
*/
|
||
protected $_public;
|
||
|
||
/**
|
||
* @var string directory where the file is stored. This is the
|
||
* document id with a proceding '/'.
|
||
* FIXME: looks like this isn't used anymore. The file path is
|
||
* constructed by getPath()
|
||
*/
|
||
protected $_dir;
|
||
|
||
/**
|
||
* @var string extension of the original file name with a leading '.'
|
||
*/
|
||
protected $_fileType;
|
||
|
||
/**
|
||
* @var string mime type of the file
|
||
*/
|
||
protected $_mimeType;
|
||
|
||
/**
|
||
* @var string name of the file that was originally uploaded
|
||
*/
|
||
protected $_orgFileName;
|
||
|
||
/**
|
||
* @var string name of the file as given by the user
|
||
*/
|
||
protected $_name;
|
||
|
||
/**
|
||
* SeedDMS_Core_DocumentFile constructor.
|
||
* @param $id
|
||
* @param $document
|
||
* @param $userID
|
||
* @param $comment
|
||
* @param $date
|
||
* @param $dir
|
||
* @param $fileType
|
||
* @param $mimeType
|
||
* @param $orgFileName
|
||
* @param $name
|
||
* @param $version
|
||
* @param $public
|
||
*/
|
||
function __construct($id, $document, $userID, $comment, $date, $dir, $fileType, $mimeType, $orgFileName,$name,$version,$public) {
|
||
$this->_id = $id;
|
||
$this->_document = $document;
|
||
$this->_userID = $userID;
|
||
$this->_comment = $comment;
|
||
$this->_date = $date;
|
||
$this->_dir = $dir;
|
||
$this->_fileType = $fileType;
|
||
$this->_mimeType = $mimeType;
|
||
$this->_orgFileName = $orgFileName;
|
||
$this->_name = $name;
|
||
$this->_version = $version;
|
||
$this->_public = $public;
|
||
}
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function getID() { return $this->_id; }
|
||
|
||
/**
|
||
* @return SeedDMS_Core_Document
|
||
*/
|
||
function getDocument() { return $this->_document; }
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function getUserID() { return $this->_userID; }
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getComment() { return $this->_comment; }
|
||
|
||
/*
|
||
* Set the comment of the document file
|
||
*
|
||
* @param string $newComment string new comment of document
|
||
*/
|
||
function setComment($newComment) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `comment` = ".$db->qstr($newComment)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_comment = $newComment;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getDate() { return $this->_date; }
|
||
|
||
/**
|
||
* Set creation date of the document file
|
||
*
|
||
* @param integer $date timestamp of creation date. If false then set it
|
||
* to the current timestamp
|
||
* @return boolean true on success
|
||
*/
|
||
function setDate($date) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!$date)
|
||
$date = time();
|
||
else {
|
||
if(!is_numeric($date))
|
||
return false;
|
||
}
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `date` = " . (int) $date . " WHERE `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
$this->_date = $date;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getDir() { return $this->_dir; }
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getFileType() { return $this->_fileType; }
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getMimeType() { return $this->_mimeType; }
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getOriginalFileName() { return $this->_orgFileName; }
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getName() { return $this->_name; }
|
||
|
||
/*
|
||
* Set the name of the document file
|
||
*
|
||
* @param $newComment string new name of document
|
||
*/
|
||
function setName($newName) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `name` = ".$db->qstr($newName)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_name = $newName;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return bool|SeedDMS_Core_User
|
||
*/
|
||
function getUser() {
|
||
if (!isset($this->_user))
|
||
$this->_user = $this->_document->getDMS()->getUser($this->_userID);
|
||
return $this->_user;
|
||
}
|
||
|
||
/**
|
||
* @return string
|
||
*/
|
||
function getPath() {
|
||
return $this->_document->getDir() . "f" .$this->_id . $this->_fileType;
|
||
}
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function getVersion() { return $this->_version; }
|
||
|
||
/*
|
||
* Set the version of the document file
|
||
*
|
||
* @param $newComment string new version of document
|
||
*/
|
||
function setVersion($newVersion) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
if(!is_numeric($newVersion) && $newVersion != '')
|
||
return false;
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `version` = ".(int) $newVersion." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_version = (int) $newVersion;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return int
|
||
*/
|
||
function isPublic() { return $this->_public; }
|
||
|
||
/*
|
||
* Set the public flag of the document file
|
||
*
|
||
* @param $newComment string new comment of document
|
||
*/
|
||
function setPublic($newPublic) { /* {{{ */
|
||
$db = $this->_document->getDMS()->getDB();
|
||
|
||
$queryStr = "UPDATE `tblDocumentFiles` SET `public` = ".($newPublic ? 1 : 0)." WHERE `document` = ".$this->_document->getId()." AND `id` = ". $this->_id;
|
||
if (!$db->getResult($queryStr))
|
||
return false;
|
||
|
||
$this->_public = $newPublic ? 1 : 0;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns the access mode similar to a document
|
||
*
|
||
* There is no real access mode for document files, so this is just
|
||
* another way to add more access restrictions than the default restrictions.
|
||
* It is only called for public document files, not accessed by the owner
|
||
* or the administrator.
|
||
*
|
||
* @param object $u user
|
||
* @return integer either M_NONE or M_READ
|
||
*/
|
||
function getAccessMode($u) { /* {{{ */
|
||
$dms = $this->_document->getDMS();
|
||
|
||
/* Check if 'onCheckAccessDocumentLink' callback is set */
|
||
if(isset($this->_dms->callbacks['onCheckAccessDocumentFile'])) {
|
||
foreach($this->_dms->callbacks['onCheckAccessDocumentFile'] as $callback) {
|
||
if(($ret = call_user_func($callback[0], $callback[1], $this, $u)) > 0) {
|
||
return $ret;
|
||
}
|
||
}
|
||
}
|
||
|
||
return M_READ;
|
||
} /* }}} */
|
||
|
||
} /* }}} */
|
||
|
||
//
|
||
// Perhaps not the cleanest object ever devised, it exists to encapsulate all
|
||
// of the data generated during the addition of new content to the database.
|
||
// The object stores a copy of the new DocumentContent object, the newly assigned
|
||
// reviewers and approvers and the status.
|
||
//
|
||
/**
|
||
* Class to represent a list of document contents
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
|
||
* Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2002-2005 Markus Westphal,
|
||
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
|
||
* 2010 Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_AddContentResultSet { /* {{{ */
|
||
|
||
/**
|
||
* @var null
|
||
*/
|
||
protected $_indReviewers;
|
||
|
||
/**
|
||
* @var null
|
||
*/
|
||
protected $_grpReviewers;
|
||
|
||
/**
|
||
* @var null
|
||
*/
|
||
protected $_indApprovers;
|
||
|
||
/**
|
||
* @var null
|
||
*/
|
||
protected $_grpApprovers;
|
||
|
||
/**
|
||
* @var
|
||
*/
|
||
protected $_content;
|
||
|
||
/**
|
||
* @var null
|
||
*/
|
||
protected $_status;
|
||
|
||
/**
|
||
* @var SeedDMS_Core_DMS back reference to document management system
|
||
*/
|
||
protected $_dms;
|
||
|
||
/**
|
||
* SeedDMS_Core_AddContentResultSet constructor.
|
||
* @param $content
|
||
*/
|
||
function __construct($content) { /* {{{ */
|
||
$this->_content = $content;
|
||
$this->_indReviewers = null;
|
||
$this->_grpReviewers = null;
|
||
$this->_indApprovers = null;
|
||
$this->_grpApprovers = null;
|
||
$this->_status = null;
|
||
$this->_dms = null;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set dms this object belongs to.
|
||
*
|
||
* Each object needs a reference to the dms it belongs to. It will be
|
||
* set when the object is created.
|
||
* The dms has a references to the currently logged in user
|
||
* and the database connection.
|
||
*
|
||
* @param SeedDMS_Core_DMS $dms reference to dms
|
||
*/
|
||
function setDMS($dms) { /* {{{ */
|
||
$this->_dms = $dms;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @param $reviewer
|
||
* @param $type
|
||
* @param $status
|
||
* @return bool
|
||
*/
|
||
function addReviewer($reviewer, $type, $status) { /* {{{ */
|
||
$dms = $this->_dms;
|
||
|
||
if (!is_object($reviewer) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){
|
||
return false;
|
||
}
|
||
if (!strcasecmp($type, "i")) {
|
||
if (strcasecmp(get_class($reviewer), $dms->getClassname("user"))) {
|
||
return false;
|
||
}
|
||
if ($this->_indReviewers == null) {
|
||
$this->_indReviewers = array();
|
||
}
|
||
$this->_indReviewers[$status][] = $reviewer;
|
||
}
|
||
if (!strcasecmp($type, "g")) {
|
||
if (strcasecmp(get_class($reviewer), $dms->getClassname("group"))) {
|
||
return false;
|
||
}
|
||
if ($this->_grpReviewers == null) {
|
||
$this->_grpReviewers = array();
|
||
}
|
||
$this->_grpReviewers[$status][] = $reviewer;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @param $approver
|
||
* @param $type
|
||
* @param $status
|
||
* @return bool
|
||
*/
|
||
function addApprover($approver, $type, $status) { /* {{{ */
|
||
$dms = $this->_dms;
|
||
|
||
if (!is_object($approver) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){
|
||
return false;
|
||
}
|
||
if (!strcasecmp($type, "i")) {
|
||
if (strcasecmp(get_class($approver), $dms->getClassname("user"))) {
|
||
return false;
|
||
}
|
||
if ($this->_indApprovers == null) {
|
||
$this->_indApprovers = array();
|
||
}
|
||
$this->_indApprovers[$status][] = $approver;
|
||
}
|
||
if (!strcasecmp($type, "g")) {
|
||
if (strcasecmp(get_class($approver), $dms->getClassname("group"))) {
|
||
return false;
|
||
}
|
||
if ($this->_grpApprovers == null) {
|
||
$this->_grpApprovers = array();
|
||
}
|
||
$this->_grpApprovers[$status][] = $approver;
|
||
}
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @param $status
|
||
* @return bool
|
||
*/
|
||
function setStatus($status) { /* {{{ */
|
||
if (!is_integer($status)) {
|
||
return false;
|
||
}
|
||
if ($status<-3 || $status>3) {
|
||
return false;
|
||
}
|
||
$this->_status = $status;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return null
|
||
*/
|
||
function getStatus() { /* {{{ */
|
||
return $this->_status;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @return mixed
|
||
*/
|
||
function getContent() { /* {{{ */
|
||
return $this->_content;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @param $type
|
||
* @return array|bool|null
|
||
*/
|
||
function getReviewers($type) { /* {{{ */
|
||
if (strcasecmp($type, "i") && strcasecmp($type, "g")) {
|
||
return false;
|
||
}
|
||
if (!strcasecmp($type, "i")) {
|
||
return ($this->_indReviewers == null ? array() : $this->_indReviewers);
|
||
}
|
||
else {
|
||
return ($this->_grpReviewers == null ? array() : $this->_grpReviewers);
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* @param $type
|
||
* @return array|bool|null
|
||
*/
|
||
function getApprovers($type) { /* {{{ */
|
||
if (strcasecmp($type, "i") && strcasecmp($type, "g")) {
|
||
return false;
|
||
}
|
||
if (!strcasecmp($type, "i")) {
|
||
return ($this->_indApprovers == null ? array() : $this->_indApprovers);
|
||
}
|
||
else {
|
||
return ($this->_grpApprovers == null ? array() : $this->_grpApprovers);
|
||
}
|
||
} /* }}} */
|
||
} /* }}} */
|