pax_global_header00006660000000000000000000000064120571654630014523gustar00rootroot0000000000000052 comment=a49d0e2b4d4e50ebc8afb65a5ef59b3b1f8bb08d php-letodms-core-3.3.11/000077500000000000000000000000001205716546300147725ustar00rootroot00000000000000php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/000077500000000000000000000000001205716546300177325ustar00rootroot00000000000000php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core.php000066400000000000000000000033471205716546300213420ustar00rootroot00000000000000 php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/000077500000000000000000000000001205716546300206225ustar00rootroot00000000000000php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.AccessUtils.php000066400000000000000000000016331205716546300243300ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Used to indicate that a search should return all * results in the ACL table. See {@link LetoDMS_Core_Folder::getAccessList()} */ define("M_ANY", -1); /** * No rights at all */ define("M_NONE", 1); /** * Read access only */ define("M_READ", 2); /** * Read and write access only */ define("M_READWRITE", 3); /** * Unrestricted access */ define("M_ALL", 4); define ("O_GTEQ", ">="); define ("O_LTEQ", "<="); define ("O_EQ", "="); define("T_FOLDER", 1); //TargetType = Folder define("T_DOCUMENT", 2); // " = Document ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassAccess.php000066400000000000000000000036251205716546300243000ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a user access right. * This class cannot be used to modify access rights. * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_UserAccess { /* {{{ */ var $_user; var $_mode; function LetoDMS_Core_UserAccess($user, $mode) { $this->_user = $user; $this->_mode = $mode; } function getUserID() { return $this->_user->getID(); } function getMode() { return $this->_mode; } function isAdmin() { return ($this->_mode == LetoDMS_Core_User::role_admin); } function getUser() { return $this->_user; } } /* }}} */ /** * Class to represent a group access right. * This class cannot be used to modify access rights. * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_GroupAccess { /* {{{ */ var $_group; var $_mode; function LetoDMS_Core_GroupAccess($group, $mode) { $this->_group = $group; $this->_mode = $mode; } function getGroupID() { return $this->_group->getID(); } function getMode() { return $this->_mode; } function getGroup() { return $this->_group; } } /* }}} */ ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassDMS.php000066400000000000000000001207761205716546300235310ustar00rootroot00000000000000 * @copyright Copyright (C) 2010, Uwe Steinmann * @version Release: 3.3.11 */ /** * Include some files */ require_once("inc.DBAccess.php"); require_once("inc.AccessUtils.php"); require_once("inc.FileUtils.php"); require_once("inc.ClassAccess.php"); require_once("inc.ClassFolder.php"); require_once("inc.ClassDocument.php"); require_once("inc.ClassGroup.php"); require_once("inc.ClassUser.php"); require_once("inc.ClassKeywords.php"); require_once("inc.ClassNotification.php"); /** * Class to represent the complete document management system. * This class is needed to do most of the dms operations. It needs * an instance of {@link LetoDMS_Core_DatabaseAccess} to access the * underlying database. Many methods are factory functions which create * objects representing the entities in the dms, like folders, documents, * users, or groups. * * Each dms has its own database for meta data and a data store for document * content. Both must be specified when creating a new instance of this class. * All folders and documents are organized in a hierachy like * a regular file system starting with a {@link $rootFolderID} * * This class does not enforce any access rights on documents and folders * by design. It is up to the calling application to use the methods * {@link LetoDMS_Core_Folder::getAccessMode} and * {@link LetoDMS_Core_Document::getAccessMode} and interpret them as desired. * Though, there are two convinient functions to filter a list of * documents/folders for which users have access rights for. See * {@link LetoDMS_Core_DMS::filterAccess} * and {@link LetoDMS_Core_DMS::filterUsersByAccess} * * Though, this class has two methods to set the currently logged in user * ({@link setUser} and {@link login}), none of them need to be called, because * there is currently no class within the LetoDMS core which needs the logged * in user. * * * connect() or die ("Could not connect to db-server"); * $dms = new LetoDMS_Core_DMS($db, $contentDir); * $dms->setRootFolderID(1); * ... * ?> * * * @category DMS * @package LetoDMS_Core * @version @version@ * @author Uwe Steinmann * @copyright Copyright (C) 2010, Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DMS { /** * @var object $db reference to database object. This must be an instance * of {@link LetoDMS_Core_DatabaseAccess}. * @access protected */ protected $db; /** * @var object $user reference to currently logged in user. This must be * an instance of {@link LetoDMS_Core_User}. This variable is currently not * used. It is set by {@link setUser}. * @access private */ private $user; /** * @var string $contentDir location in the file system where all the * document data is located. This should be an absolute path. * @access public */ public $contentDir; /** * @var integer $rootFolderID ID of root folder * @access public */ public $rootFolderID; /** * @var boolean $enableConverting set to true if conversion of content * is desired * @access public */ public $enableConverting; /** * @var array $convertFileTypes list of files types that shall be converted * @access public */ public $convertFileTypes; /** * @var array $viewOnlineFileTypes list of files types that can be viewed * online * @access public */ public $viewOnlineFileTypes; /** * @var string $version version of pear package * @access public */ public $version; /** * Filter objects out which are not accessible in a given mode by a user. * * @param array $objArr list of objects (either documents or folders) * @param object $user user for which access is checked * @param integer $minMode minimum access mode required * @return array filtered list of objects */ static function filterAccess($objArr, $user, $minMode) { /* {{{ */ if (!is_array($objArr)) { return array(); } $newArr = array(); foreach ($objArr as $obj) { if ($obj->getAccessMode($user) >= $minMode) array_push($newArr, $obj); } return $newArr; } /* }}} */ /** * Filter users out which cannot access an object in a given mode. * * @param object $obj object that shall be accessed * @param array $users list of users which are to check for sufficient * access rights * @param integer $minMode minimum access right on the object for each user * @return array filtered list of users */ static function filterUsersByAccess($obj, $users, $minMode) { /* {{{ */ $newArr = array(); foreach ($users as $currUser) { if ($obj->getAccessMode($currUser) >= $minMode) array_push($newArr, $currUser); } return $newArr; } /* }}} */ /** * Create a new instance of the dms * * @param object $db object to access the underlying database * @param string $contentDir path in filesystem containing the data store * all document contents is stored * @return object instance of LetoDMS_Core_DMS */ function __construct($db, $contentDir) { /* {{{ */ $this->db = $db; if(substr($contentDir, -1) == '/') $this->contentDir = $contentDir; else $this->contentDir = $contentDir.'/'; $this->rootFolderID = 1; $this->maxDirID = 0; //31998; $this->enableAdminRevApp = false; $this->enableConverting = false; $this->convertFileTypes = array(); $this->version = '3.3.11'; if($this->version[0] == '@') $this->version = '3.3.11'; } /* }}} */ function getDB() { /* {{{ */ return $this->db; } /* }}} */ /** * Return the database version * * @return array array with elements major, minor, subminor, date */ function getDBVersion() { /* {{{ */ $tbllist = $this->db->TableList(); $tbllist = explode(',',strtolower(join(',',$tbllist))); if(!array_search('tblversion', $tbllist)) return false; $queryStr = "SELECT * FROM tblVersion order by major,minor,subminor limit 1"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; return $resArr; } /* }}} */ /** * Check if the version in the database is the same as of this package * Only the major and minor version number will be checked. * * @return boolean returns false if versions do not match, but returns * true if version matches or table tblVersion does not exists. */ function checkVersion() { /* {{{ */ $tbllist = $this->db->TableList(); $tbllist = explode(',',strtolower(join(',',$tbllist))); if(!array_search('tblversion', $tbllist)) return true; $queryStr = "SELECT * FROM tblVersion order by major,minor,subminor limit 1"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; $ver = explode('.', $this->version); if(($resArr['major'] != $ver[0]) || ($resArr['minor'] != $ver[1])) return false; return true; } /* }}} */ /** * Set id of root folder * This function must be called right after creating an instance of * LetoDMS_Core_DMS * * @param interger $id id of root folder */ function setRootFolderID($id) { /* {{{ */ $this->rootFolderID = $id; } /* }}} */ /** * Set maximum number of subdirectories per directory * * The value of maxDirID is quite crucial because, all documents are * associated with a directory in the filesystem. Consequently, there is * maximum number of documents, because depending on the file system * the maximum number of subdirectories is limited. Since version 3.3.0 of * letodms an additional directory level has been introduced. All documents * from 1 to maxDirID-1 will be saved in 1/, documents from maxDirID * to 2*maxDirID-1 are stored in 2/ and so on. * * This function must be called right after creating an instance of * LetoDMS_Core_DMS * * @param interger $id id of root folder */ function setMaxDirID($id) { /* {{{ */ $this->maxDirID = $id; } /* }}} */ /** * Get root folder * * @return object/boolean return the object of the root folder or false if * the root folder id was not set before with {@link setRootFolderID}. */ function getRootFolder() { /* {{{ */ if(!$this->rootFolderID) return false; return $this->getFolder($this->rootFolderID); } /* }}} */ function setEnableAdminRevApp($enable) { /* {{{ */ $this->enableAdminRevApp = $enable; } /* }}} */ function setEnableConverting($enable) { /* {{{ */ $this->enableConverting = $enable; } /* }}} */ function setConvertFileTypes($types) { /* {{{ */ $this->convertFileTypes = $types; } /* }}} */ function setViewOnlineFileTypes($types) { /* {{{ */ $this->viewOnlineFileTypes = $types; } /* }}} */ /** * Login as a user * * Checks if the given credentials are valid and returns a user object. * It also sets the property $user for later access on the currently * logged in user * * @param string $username login name of user * @param string $password password of user * * @return object instance of class LetoDMS_Core_User or false */ function login($username, $password) { /* {{{ */ } /* }}} */ /** * Set the logged in user * * If user authentication was done externally, this function can * be used to tell the dms who is currently logged in. * * @param object $user * */ function setUser($user) { /* {{{ */ $this->user = $user; } /* }}} */ /** * Return a document by its id * * This function retrieves a document from the database by its id. * * @param integer $id internal id of document * @return object instance of LetoDMS_Core_Document or false */ function getDocument($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblDocuments WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; // New Locking mechanism uses a separate table to track the lock. $queryStr = "SELECT * FROM tblDocumentLocks WHERE document = " . (int) $id; $lockArr = $this->db->getResultArray($queryStr); if ((is_bool($lockArr) && $lockArr==false) || (count($lockArr)==0)) { // Could not find a lock on the selected document. $lock = -1; } else { // A lock has been identified for this document. $lock = $lockArr[0]["userID"]; } $document = new LetoDMS_Core_Document($resArr["id"], $resArr["name"], $resArr["comment"], $resArr["date"], $resArr["expires"], $resArr["owner"], $resArr["folder"], $resArr["inheritAccess"], $resArr["defaultAccess"], $lock, $resArr["keywords"], $resArr["sequence"]); $document->setDMS($this); return $document; } /* }}} */ /** * Returns all documents of a given user * * @param object $user * @return array list of documents */ function getDocumentsByUser($user) { /* {{{ */ $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". "FROM `tblDocuments` ". "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". "WHERE `tblDocuments`.`owner` = " . $user->getID() . " ORDER BY `sequence`"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $documents = array(); foreach ($resArr as $row) { $document = new LetoDMS_Core_Document($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); $document->setDMS($this); $documents[] = $document; } return $documents; } /* }}} */ /** * Returns a document by its name * * This function searches a document by its name and restricts the search * to given folder if passed as the second parameter. * * @param string $name * @param object $folder * @return object/boolean found document or false */ function getDocumentByName($name, $folder=null) { /* {{{ */ if (!$name) return false; $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ". "FROM `tblDocuments` ". "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". "WHERE `tblDocuments`.`name` = " . $this->db->qstr($name); if($folder) $queryStr .= " AND `tblDocuments`.`folder` = ". $folder->getID(); $queryStr .= " LIMIT 1"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; if(!$resArr) return false; $row = $resArr[0]; $document = new LetoDMS_Core_Document($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]); $document->setDMS($this); return $document; } /* }}} */ /* * Search the database for documents * * @param query string seach query with space separated words * @param limit integer number of items in result set * @param offset integer index of first item in result set * @param logicalmode string either AND or OR * @param searchin array() list of fields to search in * 1 = keywords, 2=name, 3=comment * @param startFolder object search in the folder only (null for root folder) * @param owner object search for documents owned by this user * @param status array list of status * @param creationstartdate array search for documents created after this date * @param creationenddate array search for documents created before this date * @param categories array list of categories the documents must have assigned * @param mode int decide whether to search for documents/folders * 0x1 = documents only * 0x2 = folders only * 0x3 = both * @return array containing the elements total and docs */ function search($query, $limit=0, $offset=0, $logicalmode='AND', $searchin=array(), $startFolder=null, $owner=null, $status = array(), $creationstartdate=array(), $creationenddate=array(), $categories=array(), $mode=0x3) { /* {{{ */ // Split the search string into constituent keywords. $tkeys=array(); if (strlen($query)>0) { $tkeys = preg_split("/[\t\r\n ,]+/", $query); } // if none is checkd search all if (count($searchin)==0) $searchin=array( 0, 1, 2, 3); /*--------- Do it all over again for folders -------------*/ if($mode & 0x2) { $searchKey = ""; // Assemble the arguments for the concatenation function. This allows the // search to be carried across all the relevant fields. $concatFunction = ""; if (in_array(2, $searchin)) { $concatFunction = (strlen($concatFunction) == 0 ? "" : $concatFunction.", ")."`tblFolders`.`name`"; } if (in_array(3, $searchin)) { $concatFunction = (strlen($concatFunction) == 0 ? "" : $concatFunction.", ")."`tblFolders`.`comment`"; } if (strlen($concatFunction)>0 && count($tkeys)>0) { $concatFunction = "CONCAT_WS(' ', ".$concatFunction.")"; foreach ($tkeys as $key) { $key = trim($key); if (strlen($key)>0) { $searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ").$concatFunction." LIKE ".$this->db->qstr('%'.$key.'%'); } } } // Check to see if the search has been restricted to a particular sub-tree in // the folder hierarchy. $searchFolder = ""; if ($startFolder) { $searchFolder = "`tblFolders`.`folderList` LIKE '%:".$startFolder->getID().":%'"; } // Check to see if the search has been restricted to a particular // document owner. $searchOwner = ""; if ($owner) { $searchOwner = "`tblFolders`.`owner` = '".$owner->getId()."'"; } // Is the search restricted to documents created between two specific dates? $searchCreateDate = ""; if ($creationstartdate) { $startdate = makeTimeStamp(0, 0, 0, $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]); if ($startdate) { $searchCreateDate .= "`tblFolders`.`date` >= ".$startdate; } } if ($creationenddate) { $stopdate = makeTimeStamp(23, 59, 59, $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]); if ($stopdate) { if($startdate) $searchCreateDate .= " AND "; $searchCreateDate .= "`tblFolders`.`date` <= ".$stopdate; } } $searchQuery = "FROM `tblFolders` WHERE 1=1"; if (strlen($searchKey)>0) { $searchQuery .= " AND (".$searchKey.")"; } if (strlen($searchFolder)>0) { $searchQuery .= " AND ".$searchFolder; } if (strlen($searchOwner)>0) { $searchQuery .= " AND (".$searchOwner.")"; } if (strlen($searchCreateDate)>0) { $searchQuery .= " AND (".$searchCreateDate.")"; } // Count the number of rows that the search will produce. $resArr = $this->db->getResultArray("SELECT COUNT(*) AS num ".$searchQuery); $totalFolders = 0; if (is_numeric($resArr[0]["num"]) && $resArr[0]["num"]>0) { $totalFolders = (integer)$resArr[0]["num"]; } // If there are no results from the count query, then there is no real need // to run the full query. TODO: re-structure code to by-pass additional // queries when no initial results are found. // Only search if the offset is not beyond the number of folders if($totalFolders > $offset) { // Prepare the complete search query, including the LIMIT clause. $searchQuery = "SELECT `tblFolders`.* ".$searchQuery; if($limit) { $searchQuery .= " LIMIT ".$offset.",".$limit; } // Send the complete search query to the database. $resArr = $this->db->getResultArray($searchQuery); } else { $resArr = array(); } // ------------------- Ausgabe der Ergebnisse ---------------------------- $numResults = count($resArr); if ($numResults == 0) { $folderresult = array('totalFolders'=>$totalFolders, 'folders'=>array()); } else { foreach ($resArr as $folderArr) { $folders[] = $this->getFolder($folderArr['id']); } $folderresult = array('totalFolders'=>$totalFolders, 'folders'=>$folders); } } else { $folderresult = array('totalFolders'=>0, 'folders'=>array()); } /*--------- Do it all over again for documents -------------*/ if($mode & 0x1) { $searchKey = ""; // Assemble the arguments for the concatenation function. This allows the // search to be carried across all the relevant fields. $concatFunction = ""; if (in_array(1, $searchin)) { $concatFunction = "`tblDocuments`.`keywords`"; } if (in_array(2, $searchin)) { $concatFunction = (strlen($concatFunction) == 0 ? "" : $concatFunction.", ")."`tblDocuments`.`name`"; } if (in_array(3, $searchin)) { $concatFunction = (strlen($concatFunction) == 0 ? "" : $concatFunction.", ")."`tblDocuments`.`comment`"; } if (strlen($concatFunction)>0 && count($tkeys)>0) { $concatFunction = "CONCAT_WS(' ', ".$concatFunction.")"; foreach ($tkeys as $key) { $key = trim($key); if (strlen($key)>0) { $searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ").$concatFunction." LIKE ".$this->db->qstr('%'.$key.'%'); } } } // Check to see if the search has been restricted to a particular sub-tree in // the folder hierarchy. $searchFolder = ""; if ($startFolder) { $searchFolder = "`tblDocuments`.`folderList` LIKE '%:".$startFolder->getID().":%'"; } // Check to see if the search has been restricted to a particular // document owner. $searchOwner = ""; if ($owner) { $searchOwner = "`tblDocuments`.`owner` = '".$owner->getId()."'"; } // Check to see if the search has been restricted to a particular // document category. $searchCategories = ""; if ($categories) { $catids = array(); foreach($categories as $category) $catids[] = $category->getId(); $searchCategories = "`tblDocumentCategory`.`categoryID` in (".implode(',', $catids).")"; } // Is the search restricted to documents created between two specific dates? $searchCreateDate = ""; if ($creationstartdate) { $startdate = makeTimeStamp(0, 0, 0, $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]); if ($startdate) { $searchCreateDate .= "`tblDocuments`.`date` >= ".$startdate; } } if ($creationenddate) { $stopdate = makeTimeStamp(23, 59, 59, $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]); if ($stopdate) { if($startdate) $searchCreateDate .= " AND "; $searchCreateDate .= "`tblDocuments`.`date` <= ".$stopdate; } } // ---------------------- Suche starten ---------------------------------- // // Construct the SQL query that will be used to search the database. // if (!$this->db->createTemporaryTable("ttcontentid") || !$this->db->createTemporaryTable("ttstatid")) { return false; } $searchQuery = "FROM `tblDocumentContent` ". "LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentContent`.`document` ". "LEFT JOIN `tblDocumentStatus` ON `tblDocumentStatus`.`documentID` = `tblDocumentContent`.`document` ". "LEFT JOIN `tblDocumentStatusLog` ON `tblDocumentStatusLog`.`statusID` = `tblDocumentStatus`.`statusID` ". "LEFT JOIN `ttstatid` ON `ttstatid`.`maxLogID` = `tblDocumentStatusLog`.`statusLogID` ". "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentStatus`.`version` AND `ttcontentid`.`document` = `tblDocumentStatus`.`documentID` ". "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ". "LEFT JOIN `tblDocumentCategory` ON `tblDocuments`.`id`=`tblDocumentCategory`.`documentID` ". "WHERE `ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` ". "AND `ttcontentid`.`maxVersion` = `tblDocumentContent`.`version`"; if (strlen($searchKey)>0) { $searchQuery .= " AND (".$searchKey.")"; } if (strlen($searchFolder)>0) { $searchQuery .= " AND ".$searchFolder; } if (strlen($searchOwner)>0) { $searchQuery .= " AND (".$searchOwner.")"; } if (strlen($searchCategories)>0) { $searchQuery .= " AND (".$searchCategories.")"; } if (strlen($searchCreateDate)>0) { $searchQuery .= " AND (".$searchCreateDate.")"; } // status if ($status) { $searchQuery .= " AND `tblDocumentStatusLog`.`status` IN (".implode(',', $status).")"; } // Count the number of rows that the search will produce. $resArr = $this->db->getResultArray("SELECT COUNT(*) AS num ".$searchQuery); $totalDocs = 0; if (is_numeric($resArr[0]["num"]) && $resArr[0]["num"]>0) { $totalDocs = (integer)$resArr[0]["num"]; } // If there are no results from the count query, then there is no real need // to run the full query. TODO: re-structure code to by-pass additional // queries when no initial results are found. // Prepare the complete search query, including the LIMIT clause. $searchQuery = "SELECT `tblDocuments`.*, ". "`tblDocumentContent`.`version`, ". "`tblDocumentStatusLog`.`status`, `tblDocumentLocks`.`userID` as `lockUser` ".$searchQuery; // calculate the remaining entrŅ—es of the current page // If page is not full yet, get remaining entries $remain = $limit - count($folderresult['folders']); if($remain) { if($remain == $limit) $offset -= $totalFolders; else $offset = 0; if($limit) $searchQuery .= " LIMIT ".$offset.",".$remain; // Send the complete search query to the database. $resArr = $this->db->getResultArray($searchQuery); } else { $resArr = array(); } // ------------------- Ausgabe der Ergebnisse ---------------------------- $numResults = count($resArr); if ($numResults == 0) { $docresult = array('totalDocs'=>$totalDocs, 'docs'=>array()); } else { foreach ($resArr as $docArr) { $docs[] = $this->getDocument($docArr['id']); } $docresult = array('totalDocs'=>$totalDocs, 'docs'=>$docs); } } else { $docresult = array('totalDocs'=>0, 'docs'=>array()); } if($limit) { $totalPages = (integer)(($totalDocs+$totalFolders)/$limit); if ((($totalDocs+$totalFolders)%$limit) > 0) { $totalPages++; } } else { $totalPages = 1; } return array_merge($docresult, $folderresult, array('totalPages'=>$totalPages)); } /* }}} */ /** * Return a folder by its id * * This function retrieves a folder from the database by its id. * * @param integer $id internal id of folder * @return object instance of LetoDMS_Core_Folder or false */ function getFolder($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblFolders WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; else if (count($resArr) != 1) return false; $resArr = $resArr[0]; $folder = new LetoDMS_Core_Folder($resArr["id"], $resArr["name"], $resArr["parent"], $resArr["comment"], $resArr["date"], $resArr["owner"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr["sequence"]); $folder->setDMS($this); return $folder; } /* }}} */ /** * Return a folder by its name * * This function retrieves a folder from the database by its name. The * search covers the whole database. If * the parameter $folder is not null, it will search for the name * only within this parent folder. It will not be done recursively. * * @param string $name name of the folder * @param object $folder parent folder * @return object/boolean found folder or false */ function getFolderByName($name, $folder=null) { /* {{{ */ if (!$name) return false; $queryStr = "SELECT * FROM tblFolders WHERE name = " . $this->db->qstr($name); if($folder) $queryStr .= " AND `parent` = ". $folder->getID(); $queryStr .= " LIMIT 1"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if(!$resArr) return false; $resArr = $resArr[0]; $folder = new LetoDMS_Core_Folder($resArr["id"], $resArr["name"], $resArr["parent"], $resArr["comment"], $resArr["date"], $resArr["owner"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr["sequence"]); $folder->setDMS($this); return $folder; } /* }}} */ /** * Return a user by its id * * This function retrieves a user from the database by its id. * * @param integer $id internal id of user * @return object instance of LetoDMS_Core_User or false */ function getUser($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblUsers WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; $user = new LetoDMS_Core_User($resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $resArr["role"], $resArr["hidden"]); $user->setDMS($this); return $user; } /* }}} */ /** * Return a user by its login * * This function retrieves a user from the database by its login. * If the second optional parameter $email is not empty, the user must * also have the given email. * * @param string $login internal login of user * @param string $email email of user * @return object instance of LetoDMS_Core_User or false */ function getUserByLogin($login, $email='') { /* {{{ */ $queryStr = "SELECT * FROM tblUsers WHERE login = ".$this->db->qstr($login); if($email) $queryStr .= " AND email=".$this->db->qstr($email); $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; $user = new LetoDMS_Core_User($resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $resArr["role"], $resArr["hidden"]); $user->setDMS($this); return $user; } /* }}} */ /** * Return a user by its email * * This function retrieves a user from the database by its email. * It is needed when the user requests a new password. * * @param integer $email email address of user * @return object instance of LetoDMS_Core_User or false */ function getUserByEmail($email) { /* {{{ */ $queryStr = "SELECT * FROM tblUsers WHERE email = ".$this->db->qstr($email); $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; $user = new LetoDMS_Core_User($resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $resArr["role"], $resArr["hidden"]); $user->setDMS($this); return $user; } /* }}} */ /** * Return list of all users * * @return array of instances of LetoDMS_Core_User or false */ function getAllUsers() { /* {{{ */ $queryStr = "SELECT * FROM tblUsers ORDER BY login"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $users = array(); for ($i = 0; $i < count($resArr); $i++) { $user = new LetoDMS_Core_User($resArr[$i]["id"], $resArr[$i]["login"], $resArr[$i]["pwd"], $resArr[$i]["fullName"], $resArr[$i]["email"], (isset($resArr["language"])?$resArr["language"]:NULL), (isset($resArr["theme"])?$resArr["theme"]:NULL), $resArr[$i]["comment"], $resArr[$i]["role"], $resArr[$i]["hidden"]); $user->setDMS($this); $users[$i] = $user; } return $users; } /* }}} */ /** * Add a new user * * @param string $login login name * @param string $pwd password of new user * @param string $email Email of new user * @param string $language language of new user * @param string $comment comment of new user * @param integer $role role of new user (can be 0=normal, 1=admin, 2=guest) * @param integer $isHidden hide user in all lists, if this is set login * is still allowed * @return object of LetoDMS_Core_User */ function addUser($login, $pwd, $fullName, $email, $language, $theme, $comment, $role='0', $isHidden=0) { /* {{{ */ $db = $this->db; if (is_object($this->getUserByLogin($login))) { return false; } if($role == '') $role = '0'; $queryStr = "INSERT INTO tblUsers (login, pwd, fullName, email, language, theme, comment, role, hidden) VALUES (".$db->qstr($login).", ".$db->qstr($pwd).", ".$db->qstr($fullName).", ".$db->qstr($email).", '".$language."', '".$theme."', ".$db->qstr($comment).", '".intval($role)."', '".intval($isHidden)."')"; $res = $this->db->getResult($queryStr); if (!$res) return false; return $this->getUser($this->db->getInsertID()); } /* }}} */ /** * Get a group by its id * * @param integer $id id of group * @return object/boolean group or false if no group was found */ function getGroup($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblGroups WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; else if (count($resArr) != 1) //wenn, dann wohl eher 0 als > 1 ;-) return false; $resArr = $resArr[0]; $group = new LetoDMS_Core_Group($resArr["id"], $resArr["name"], $resArr["comment"]); $group->setDMS($this); return $group; } /* }}} */ /** * Get a group by its name * * @param string $name name of group * @return object/boolean group or false if no group was found */ function getGroupByName($name) { /* {{{ */ $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` WHERE `tblGroups`.`name` = ".$this->db->qstr($name); $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; else if (count($resArr) != 1) //wenn, dann wohl eher 0 als > 1 ;-) return false; $resArr = $resArr[0]; $group = new LetoDMS_Core_Group($resArr["id"], $resArr["name"], $resArr["comment"]); $group->setDMS($this); return $group; } /* }}} */ /** * Get a list of all groups * * @return array array of instances of {@link LetoDMS_Core_Group} */ function getAllGroups() { /* {{{ */ $queryStr = "SELECT * FROM tblGroups ORDER BY name"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $groups = array(); for ($i = 0; $i < count($resArr); $i++) { $group = new LetoDMS_Core_Group($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["comment"]); $group->setDMS($this); $groups[$i] = $group; } return $groups; } /* }}} */ /** * Create a new user group * * @param string $name name of group * @param string $comment comment of group * @return object/boolean instance of {@link LetoDMS_Core_Group} or false in * case of an error. */ function addGroup($name, $comment) { /* {{{ */ if (is_object($this->getGroupByName($name))) { return false; } $queryStr = "INSERT INTO tblGroups (name, comment) VALUES (".$this->db->qstr($name).", ".$this->db->qstr($comment).")"; if (!$this->db->getResult($queryStr)) return false; return $this->getGroup($this->db->getInsertID()); } /* }}} */ function getKeywordCategory($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblKeywordCategories WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if ((is_bool($resArr) && !$resArr) || (count($resArr) != 1)) return false; $resArr = $resArr[0]; $cat = new LetoDMS_Core_Keywordcategory($resArr["id"], $resArr["owner"], $resArr["name"]); $cat->setDMS($this); return $cat; } /* }}} */ function getKeywordCategoryByName($name, $userID) { /* {{{ */ $queryStr = "SELECT * FROM tblKeywordCategories WHERE name = " . $this->db->qstr($name) . " AND owner = " . (int) $userID; $resArr = $this->db->getResultArray($queryStr); if ((is_bool($resArr) && !$resArr) || (count($resArr) != 1)) return false; $resArr = $resArr[0]; $cat = new LetoDMS_Core_Keywordcategory($resArr["id"], $resArr["owner"], $resArr["name"]); $cat->setDMS($this); return $cat; } /* }}} */ function getAllKeywordCategories($userIDs = array()) { /* {{{ */ $queryStr = "SELECT * FROM tblKeywordCategories"; if ($userIDs) $queryStr .= " WHERE owner in (".implode(',', $userIDs).")"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $categories = array(); foreach ($resArr as $row) { $cat = new LetoDMS_Core_KeywordCategory($row["id"], $row["owner"], $row["name"]); $cat->setDMS($this); array_push($categories, $cat); } return $categories; } /* }}} */ /** * This function should be replaced by getAllKeywordCategories() */ function getAllUserKeywordCategories($userID) { /* {{{ */ $queryStr = "SELECT * FROM tblKeywordCategories"; if ($userID != -1) $queryStr .= " WHERE owner = " . (int) $userID; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $categories = array(); foreach ($resArr as $row) { $cat = new LetoDMS_Core_KeywordCategory($row["id"], $row["owner"], $row["name"]); $cat->setDMS($this); array_push($categories, $cat); } return $categories; } /* }}} */ function addKeywordCategory($userID, $name) { /* {{{ */ if (is_object($this->getKeywordCategoryByName($name, $userID))) { return false; } $queryStr = "INSERT INTO tblKeywordCategories (owner, name) VALUES (".(int) $userID.", ".$this->db->qstr($name).")"; if (!$this->db->getResult($queryStr)) return false; return $this->getKeywordCategory($this->db->getInsertID()); } /* }}} */ function getDocumentCategory($id) { /* {{{ */ if (!is_numeric($id)) return false; $queryStr = "SELECT * FROM tblCategory WHERE id = " . (int) $id; $resArr = $this->db->getResultArray($queryStr); if ((is_bool($resArr) && !$resArr) || (count($resArr) != 1)) return false; $resArr = $resArr[0]; $cat = new LetoDMS_Core_DocumentCategory($resArr["id"], $resArr["name"]); $cat->setDMS($this); return $cat; } /* }}} */ function getDocumentCategories() { /* {{{ */ $queryStr = "SELECT * FROM tblCategory"; $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $categories = array(); foreach ($resArr as $row) { $cat = new LetoDMS_Core_DocumentCategory($row["id"], $row["name"]); $cat->setDMS($this); array_push($categories, $cat); } return $categories; } /* }}} */ /** * Get a category by its name * * The name of a category is by default unique. * * @param string $name human readable name of category * @return object instance of LetoDMS_Core_DocumentCategory */ function getDocumentCategoryByName($name) { /* {{{ */ $queryStr = "SELECT * FROM tblCategory where name=".$this->db->qstr($name); $resArr = $this->db->getResultArray($queryStr); if (!$resArr) return false; $row = $resArr[0]; $cat = new LetoDMS_Core_DocumentCategory($row["id"], $row["name"]); $cat->setDMS($this); return $cat; } /* }}} */ function addDocumentCategory($name) { /* {{{ */ if (is_object($this->getDocumentCategoryByName($name))) { return false; } $queryStr = "INSERT INTO tblCategory (name) VALUES (".$this->db->qstr($name).")"; if (!$this->db->getResult($queryStr)) return false; return $this->getDocumentCategory($this->db->getInsertID()); } /* }}} */ /** * Get all notifications for a group * * @param object $group group for which notifications are to be retrieved * @param integer $type type of item (T_DOCUMENT or T_FOLDER) * @return array array of notifications */ function getNotificationsByGroup($group, $type=0) { /* {{{ */ $queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ". "WHERE `tblNotify`.`groupID` = ". $group->getID(); if($type) { $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type; } $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $notifications = array(); foreach ($resArr as $row) { $not = new LetoDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]); $not->setDMS($this); array_push($notifications, $cat); } return $notifications; } /* }}} */ /** * Get all notifications for a user * * @param object $user user for which notifications are to be retrieved * @param integer $type type of item (T_DOCUMENT or T_FOLDER) * @return array array of notifications */ function getNotificationsByUser($user, $type=0) { /* {{{ */ $queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ". "WHERE `tblNotify`.`userID` = ". $user->getID(); if($type) { $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type; } $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $notifications = array(); foreach ($resArr as $row) { $not = new LetoDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]); $not->setDMS($this); array_push($notifications, $cat); } return $notifications; } /* }}} */ /** * Create a token to request a new password. * This function will not delete the password but just creates an entry * in tblUserRequestPassword indicating a password request. * * @return string hash value of false in case of an error */ function createPasswordRequest($user) { /* {{{ */ $hash = md5(uniqid(time())); $queryStr = "INSERT INTO tblUserPasswordRequest (userID, hash, `date`) VALUES (" . $user->getId() . ", " . $this->db->qstr($hash) .", now())"; $resArr = $this->db->getResult($queryStr); if (is_bool($resArr) && !$resArr) return false; return $hash; } /* }}} */ /** * Check if hash for a password request is valid. * This function searches a previously create password request and * returns the user. * * @param string $hash */ function checkPasswordRequest($hash) { /* {{{ */ /* Get the password request from the database */ $queryStr = "SELECT * FROM tblUserPasswordRequest where hash=".$this->db->qstr($hash); $resArr = $this->db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; return $this->getUser($resArr['userID']); } /* }}} */ /** * Delete a password request * * @param string $hash */ function deletePasswordRequest($hash) { /* {{{ */ /* Delete the request, so nobody can use it a second time */ $queryStr = "DELETE FROM tblUserPasswordRequest WHERE hash=".$this->db->qstr($hash); if (!$this->db->getResult($queryStr)) return false; return true; } } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassDocument.php000066400000000000000000002562231205716546300246610ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * The different states a document can be in */ define("S_DRAFT_REV", 0); define("S_DRAFT_APP", 1); define("S_RELEASED", 2); define("S_REJECTED", -1); define("S_OBSOLETE", -2); define("S_EXPIRED", -3); /** * Class to represent a document in the document management system * * A document in LetoDMS is similar to files in a regular file system. * Documents may have any number of content elements * ({@link LetoDMS_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 LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, * Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_Document { /* {{{ */ /** * @var integer unique id of document */ var $_id; /** * @var string name of document */ var $_name; /** * @var string comment of document */ var $_comment; /** * @var integer unix timestamp of creation date */ var $_date; /** * @var integer id of user who is the owner */ var $_ownerID; /** * @var integer id of folder this document belongs to */ var $_folderID; /** * @var integer timestamp of expiration date */ var $_expires; /** * @var boolean true if access is inherited, otherwise false */ var $_inheritAccess; /** * @var integer default access if access rights are not inherited */ var $_defaultAccess; /** * @var array list of notifications for users and groups */ var $_notifyList; /** * @var boolean true if document is locked, otherwise false */ var $_locked; /** * @var string list of keywords */ var $_keywords; /** * @var array list of categories */ var $_categories; /** * @var integer position of document within the parent folder */ var $_sequence; /** * @var object back reference to document management system */ var $_dms; function LetoDMS_Core_Document($id, $name, $comment, $date, $expires, $ownerID, $folderID, $inheritAccess, $defaultAccess, $locked, $keywords, $sequence) { /* {{{ */ $this->_id = $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->_dms = null; } /* }}} */ /* * Set dms this document belongs to. * * Each document needs a reference to the dms it belongs to. It will be * set when the folder is created by LetoDMS::getDocument() or * LetoDMS::search(). The dms has a * references to the currently logged in user and the database connection. * * @param object $dms reference to dms */ function setDMS($dms) { /* {{{ */ $this->_dms = $dms; } /* }}} */ /* * 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 internal id of the document * * @return integer id of document */ function getID() { 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 */ 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 */ 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; } /* }}} */ function getKeywords() { return $this->_keywords; } 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 array list of category objects */ 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 LetoDMS_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 array $newCategories list of category objects */ function setCategories($newCategories) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE from tblDocumentCategory WHERE documentID = ". $this->_id; if (!$db->getResult($queryStr)) return false; foreach($newCategories as $cat) { $queryStr = "INSERT INTO tblDocumentCategory (categoryID, documentID) VALUES (". $cat->getId() .", ". $this->_id .")"; if (!$db->getResult($queryStr)) return false; } $this->_categories = $newCategories; return true; } /* }}} */ /** * Return creation date of the document * * @return integer unix timestamp of creation date */ function getDate() { /* {{{ */ return $this->_date; } /* }}} */ /** * Return the parent folder of the document * * @return object parent folder */ 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 object $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(); $this->_folder = $newFolder; // Make sure that the folder search path is also updated. $path = $newFolder->getPath(); $flist = ""; 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 object owner of document as an instance of {@link LetoDMS_Core_User} */ function getOwner() { /* {{{ */ if (!isset($this->_owner)) $this->_owner = $this->_dms->getUser($this->_ownerID); return $this->_owner; } /* }}} */ /** * Set owner of a document * * @param object $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(); $this->_owner = $newOwner; return true; } /* }}} */ function getDefaultAccess() { /* {{{ */ if ($this->inheritsAccess()) { $res = $this->getFolder(); if (!$res) return false; return $this->_folder->getDefaultAccess(); } return $this->_defaultAccess; } /* }}} */ function setDefaultAccess($mode) { /* {{{ */ $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 any of the notification subscribers no longer have read access, // remove their subscription. foreach ($this->_notifyList["users"] as $u) { if ($this->getAccessMode($u) < M_READ) { $this->removeNotify($u->getID(), true); } } foreach ($this->_notifyList["groups"] as $g) { if ($this->getGroupAccessMode($g) < M_READ) { $this->removeNotify($g->getID(), false); } } return true; } /* }}} */ 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 * @return boolean true if operation was successful otherwise false */ function setInheritAccess($inheritAccess) { /* {{{ */ $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 any of the notification subscribers no longer have read access, // remove their subscription. if(isset($this->_notifyList["users"])) { foreach ($this->_notifyList["users"] as $u) { if ($this->getAccessMode($u) < M_READ) { $this->removeNotify($u->getID(), true); } } } if(isset($this->_notifyList["groups"])) { foreach ($this->_notifyList["groups"] as $g) { if ($this->getGroupAccessMode($g) < M_READ) { $this->removeNotify($g->getID(), false); } } } 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 unix timestamp of expiration date */ 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 * * @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; } /* }}} */ // return true if status has changed (to reload page) function verifyLastestContentExpriry(){ /* {{{ */ $lc=$this->getLatestContent(); if($lc) { $st=$lc->getStatus(); if (($st["status"]==S_DRAFT_REV || $st["status"]==S_DRAFT_APP) && $this->hasExpired()){ $lc->setStatus(S_EXPIRED,"", $this->getOwner()); return true; } else if ($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 $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 object 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; } /* }}} */ function getSequence() { return $this->_sequence; } 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 * * @return boolean true if operation was successful otherwise false */ function clearAccessList() { /* {{{ */ $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); 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 LetoDMS_Core_UserAccess} and * {@link LetoDMS_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 integer $mode access mode (defaults to M_ANY) * @param integer $op operation (defaults to O_EQ) * @return array multi dimensional 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 LetoDMS_Core_UserAccess($this->_dms->getUser($row["userID"]), $row["mode"])); else //if ($row["groupID"] != -1) array_push($this->_accessList[$mode]["groups"], new LetoDMS_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 */ 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 */ 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 * * @param $user object instance of class LetoDMS_Core_User * @return integer access mode */ function getAccessMode($user) { /* {{{ */ /* 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; /* The guest users do not have more than read access */ if ($user->isGuest()) { $mode = $this->getDefaultAccess(); if ($mode >= M_READ) return M_READ; else return M_NONE; } /* Check ACLs */ $accessList = $this->getAccessList(); if (!$accessList) return false; foreach ($accessList["users"] as $userAccess) { if ($userAccess->getUserID() == $user->getID()) { return $userAccess->getMode(); } } /* Get the highest right defined by a group */ $result = 0; foreach ($accessList["groups"] as $groupAccess) { if ($user->isMemberOfGroup($groupAccess->getGroup())) { if ($groupAccess->getMode() > $result) $result = $groupAccess->getMode(); // return $groupAccess->getMode(); } } if($result) return $result; $result = $this->getDefaultAccess(); return $result; } /* }}} */ /** * 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 $group object instance of class LetoDMS_Core_Group * @return integer access mode */ function getGroupAccessMode($group) { /* {{{ */ $highestPrivileged = M_NONE; //ACLs durchforsten $foundInACL = false; $accessList = $this->getAccessList(); if (!$accessList) return false; 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 LetoDMS_Core_User and * LetoDMS_Core_Group. * * @return array list of notifications */ function getNotifyList() { /* {{{ */ 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) array_push($this->_notifyList["users"], $this->_dms->getUser($row["userID"]) ); else //if ($row["groupID"] != -1) array_push($this->_notifyList["groups"], $this->_dms->getGroup($row["groupID"]) ); } } return $this->_notifyList; } /* }}} */ /** * 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; 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; 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 $userOrGroupID id of user or group * @param $isUser boolean true if a user is passed in $userOrGroupID, false * if a group is passed in $userOrGroupID * @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) { /* {{{ */ $db = $this->_dms->getDB(); /* Verify that user / group exists. */ $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 (!$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 $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. * @return bool/array false in case of an error or a result set */ function addContent($comment, $user, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers=array(), $approvers=array(), $version=0) { /* {{{ */ $db = $this->_dms->getDB(); // the doc path is id/version.filetype $dir = $this->getDir(); $date = mktime(); /* 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) && !$res) return false; $version = $resArr[0]['m']+1; } $queryStr = "INSERT INTO tblDocumentContent (document, version, comment, date, createdBy, dir, orgFileName, fileType, mimeType) VALUES ". "(".$this->_id.", ".(int)$version.",".$db->qstr($comment).", ".$date.", ".$user->getID().", ".$db->qstr($dir).", ".$db->qstr($orgFileName).", ".$db->qstr($fileType).", ".$db->qstr($mimeType).")"; if (!$db->getResult($queryStr)) return false; // copy file if (!LetoDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) return false; if (!LetoDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $dir . $version . $fileType)) return false; unset($this->_content); unset($this->_latestContent); $docResultSet = new LetoDMS_Core_AddContentResultSet(new LetoDMS_Core_DocumentContent($this, $version, $comment, $date, $user->getID(), $dir, $orgFileName, $fileType, $mimeType)); // TODO - verify if ($this->_dms->enableConverting && in_array($docResultSet->_content->getFileType(), array_keys($this->_dms->convertFileTypes))) $docResultSet->_content->convert(); // Even if if fails, do not return false $queryStr = "INSERT INTO `tblDocumentStatus` (`documentID`, `version`) ". "VALUES (". $this->_id .", ". (int) $version .")"; if (!$db->getResult($queryStr)) return false; $statusID = $db->getInsertID(); // 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; $reviewRes = array(); 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->_content->addIndReviewer($reviewer, $user, true) : $docResultSet->_content->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; $approveRes = array(); 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->_content->addIndApprover($approver, $user, !$pendingReview) : $docResultSet->_content->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 = ""; } else if ($pendingApproval) { $status = S_DRAFT_APP; $comment = ""; } else { $status = S_RELEASED; $comment=""; } $queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $statusID ."', '". $status."', 'New document content submitted". $comment ."', NOW(), '". $user->getID() ."')"; if (!$db->getResult($queryStr)) return false; $docResultSet->setStatus($status,$comment,$user); return $docResultSet; } /* }}} */ /** * Return all content elements of a document * * This functions returns an array of content elements ordered by version * * @return array list of objects of class LetoDMS_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) && !$res) return false; $this->_content = array(); foreach ($resArr as $row) array_push($this->_content, new LetoDMS_Core_DocumentContent($this, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"])); } return $this->_content; } /* }}} */ /** * Return the content element of a document with a given version number * * @param integer $version version number of content element * @return object object of class LetoDMS_Core_DocumentContent */ 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) && !$res) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; return new LetoDMS_Core_DocumentContent($this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"]); } /* }}} */ function getLatestContent() { /* {{{ */ if (!isset($this->_latestContent)) { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblDocumentContent WHERE document = ".$this->_id." ORDER BY version DESC LIMIT 0,1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; if (count($resArr) != 1) return false; $resArr = $resArr[0]; $this->_latestContent = new LetoDMS_Core_DocumentContent($this, $resArr["version"], $resArr["comment"], $resArr["date"], $resArr["createdBy"], $resArr["dir"], $resArr["orgFileName"], $resArr["fileType"], $resArr["mimeType"]); } return $this->_latestContent; } /* }}} */ function removeContent($version) { /* {{{ */ $db = $this->_dms->getDB(); $emailList = array(); $emailList[] = $version->_userID; if (file_exists( $this->_dms->contentDir.$version->getPath() )) if (!LetoDMS_Core_File::removeFile( $this->_dms->contentDir.$version->getPath() )) return false; $status = $version->getStatus(); $stID = $status["statusID"]; $queryStr = "DELETE FROM tblDocumentContent WHERE `document` = " . $this->getID() . " AND `version` = " . $version->_version; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM `tblDocumentStatusLog` WHERE `statusID` = '".$stID."'"; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM `tblDocumentStatus` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->_version."'"; if (!$db->getResult($queryStr)) return false; $status = $version->getReviewStatus(); $stList = ""; foreach ($status as $st) { $stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["reviewID"]."'"; if ($st["status"]==0 && !in_array($st["required"], $emailList)) { $emailList[] = $st["required"]; } } if (strlen($stList)>0) { $queryStr = "DELETE FROM `tblDocumentReviewLog` WHERE `tblDocumentReviewLog`.`reviewID` IN (".$stList.")"; if (!$db->getResult($queryStr)) return false; } $queryStr = "DELETE FROM `tblDocumentReviewers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->_version."'"; if (!$db->getResult($queryStr)) return false; $status = $version->getApprovalStatus(); $stList = ""; foreach ($status as $st) { $stList .= (strlen($stList)==0 ? "" : ", "). "'".$st["approveID"]."'"; if ($st["status"]==0 && !in_array($st["required"], $emailList)) { $emailList[] = $st["required"]; } } if (strlen($stList)>0) { $queryStr = "DELETE FROM `tblDocumentApproveLog` WHERE `tblDocumentApproveLog`.`approveID` IN (".$stList.")"; if (!$db->getResult($queryStr)) return false; } $queryStr = "DELETE FROM `tblDocumentApprovers` WHERE `documentID` = '". $this->getID() ."' AND `version` = '" . $version->_version."'"; if (!$db->getResult($queryStr)) return false; return true; } /* }}} */ 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"]); return new LetoDMS_Core_DocumentLink($resArr["id"], $document, $target, $resArr["userID"], $resArr["public"]); } /* }}} */ function getDocumentLinks() { /* {{{ */ if (!isset($this->_documentLinks)) { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblDocumentLinks WHERE document = " . $this->_id; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $this->_documentLinks = array(); foreach ($resArr as $row) { $target = $this->_dms->getDocument($row["target"]); array_push($this->_documentLinks, new LetoDMS_Core_DocumentLink($row["id"], $this, $target, $row["userID"], $row["public"])); } } return $this->_documentLinks; } /* }}} */ 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; } /* }}} */ 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]; return new LetoDMS_Core_DocumentFile($resArr["id"], $this, $resArr["userID"], $resArr["comment"], $resArr["date"], $resArr["dir"], $resArr["fileType"], $resArr["mimeType"], $resArr["orgFileName"], $resArr["name"]); } /* }}} */ function getDocumentFiles() { /* {{{ */ if (!isset($this->_documentFiles)) { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblDocumentFiles WHERE document = " . $this->_id." ORDER BY `date` DESC"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $this->_documentFiles = array(); foreach ($resArr as $row) { array_push($this->_documentFiles, new LetoDMS_Core_DocumentFile($row["id"], $this, $row["userID"], $row["comment"], $row["date"], $row["dir"], $row["fileType"], $row["mimeType"], $row["orgFileName"], $row["name"])); } } return $this->_documentFiles; } /* }}} */ function addDocumentFile($name, $comment, $user, $tmpFile, $orgFileName,$fileType, $mimeType ) { /* {{{ */ $db = $this->_dms->getDB(); $dir = $this->getDir(); $queryStr = "INSERT INTO tblDocumentFiles (comment, date, dir, document, fileType, mimeType, orgFileName, userID, name) VALUES ". "(".$db->qstr($comment).", '".mktime()."', ".$db->qstr($dir).", ".$this->_id.", ".$db->qstr($fileType).", ".$db->qstr($mimeType).", ".$db->qstr($orgFileName).",".$user->getID().",".$db->qstr($name).")"; if (!$db->getResult($queryStr)) return false; $id = $db->getInsertID(); $file = $this->getDocumentFile($id); if (is_bool($file) && !$file) return false; // copy file if (!LetoDMS_Core_File::makeDir($this->_dms->contentDir . $dir)) return false; if (!LetoDMS_Core_File::copyFile($tmpFile, $this->_dms->contentDir . $file->getPath() )) return false; return true; } /* }}} */ 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 (!LetoDMS_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; } /* }}} */ function remove() { /* {{{ */ $db = $this->_dms->getDB(); $res = $this->getContent(); if (is_bool($res) && !$res) return false; // FIXME: call a new function removeContent instead foreach ($this->_content as $version) if (!$this->removeContent($version)) return false; // remove document file $res = $this->getDocumentFiles(); if (is_bool($res) && !$res) return false; foreach ($res as $documentfile) if(!$this->removeDocumentFile($documentfile->getId())) return false; // TODO: versioning file? if (file_exists( $this->_dms->contentDir . $this->getDir() )) if (!LetoDMS_Core_File::removeDir( $this->_dms->contentDir . $this->getDir() )) return false; $queryStr = "DELETE FROM tblDocuments WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblACLs WHERE target = " . $this->_id . " AND targetType = " . T_DOCUMENT; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblDocumentLinks WHERE document = " . $this->_id . " OR target = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblDocumentLocks WHERE document = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblDocumentFiles WHERE document = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblDocumentCategory WHERE documentID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // Delete the notification list. $queryStr = "DELETE FROM tblNotify WHERE target = " . $this->_id . " AND targetType = " . T_DOCUMENT; if (!$db->getResult($queryStr)) return false; return true; } /* }}} */ function getApproversList() { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_approversList)) { $this->_approversList = array("groups" => array(), "users" => array()); $userIDs = ""; $groupIDs = ""; $defAccess = $this->getDefaultAccess(); if ($defAccessgetAccessList(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); } foreach ($tmpList["groups"] as $group) { $groupIDs .= (strlen($groupIDs)==0 ? "" : ", ") . $group->getGroupID(); } foreach ($tmpList["users"] as $c_user) { if (!$this->_dms->enableAdminRevApp && $c_user->isAdmin()) continue; $userIDs .= (strlen($userIDs)==0 ? "" : ", ") . $c_user->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 ($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` != ".LetoDMS_Core_User::role_guest.")"; } $queryStr .= (strlen($queryStr)==0 ? "" : " UNION "). "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE (`tblUsers`.`role` != ".LetoDMS_Core_User::role_guest.") ". "AND ((`tblUsers`.`id` = ". $this->_ownerID . ") ". "OR (`tblUsers`.`role` = ".LetoDMS_Core_User::role_admin.")". (strlen($userIDs) == 0 ? "" : " OR (`tblUsers`.`id` IN (". $userIDs ."))"). ")) ORDER BY `login`"; } 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` != ".LetoDMS_Core_User::role_guest . (strlen($userIDs) == 0 ? ")" : " AND (`tblUsers`.`id` NOT IN (". $userIDs .")))"); } $queryStr .= (strlen($queryStr)==0 ? "" : " UNION "). "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE (`tblUsers`.`id` = ". $this->_ownerID . ") ". "OR (`tblUsers`.`role` = ".LetoDMS_Core_User::role_admin."))". "UNION ". "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE `tblUsers`.`role` != ".LetoDMS_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 (!$this->_dms->enableAdminRevApp && $user->isAdmin()) continue; $this->_approversList["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 .")"; } } else { if (strlen($groupIDs)>0) { $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". "WHERE `tblGroups`.`id` NOT IN (". $groupIDs .")"; } else { $queryStr = "SELECT `tblGroups`.* FROM `tblGroups`"; } } if (strlen($queryStr)>0) { $resArr = $db->getResultArray($queryStr); if (!is_bool($resArr)) { foreach ($resArr as $row) { $group = $this->_dms->getGroup($row["id"]); $this->_approversList["groups"][] = $group; } } } } return $this->_approversList; } /* }}} */ /** * 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; } /* }}} */ } /* }}} */ /** * 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 LetoDMS_Core_Document::removeContent()}. * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, * Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DocumentContent { /* {{{ */ // if status is released and there are reviewers set status draft_rev // if status is released or draft_rev and there are approves set status draft_app // if status is draft and there are no approver and no reviewers set status to release function verifyStatus($ignorecurrentstatus=false, $user=null) { /* {{{ */ unset($this->_status); $st=$this->getStatus(); if (!$ignorecurrentstatus && ($st["status"]==S_OBSOLETE || $st["status"]==S_REJECTED || $st["status"]==S_EXPIRED )) return; $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=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; } } } if ($pendingReview) $this->setStatus(S_DRAFT_REV,"",$user); else if ($pendingApproval) $this->setStatus(S_DRAFT_APP,"",$user); else $this->setStatus(S_RELEASED,"",$user); } /* }}} */ function LetoDMS_Core_DocumentContent($document, $version, $comment, $date, $userID, $dir, $orgFileName, $fileType, $mimeType) { /* {{{ */ $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; } /* }}} */ 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 "data" . $this->_fileType; } function getDir() { return $this->_dir; } function getMimeType() { return $this->_mimeType; } function getUser() { /* {{{ */ if (!isset($this->_user)) $this->_user = $this->_document->_dms->getUser($this->_userID); return $this->_user; } /* }}} */ function getPath() { return $this->_document->getDir() . $this->_version . $this->_fileType; } function setComment($newComment) { /* {{{ */ $db = $this->_document->_dms->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; } /* }}} */ function convert() { /* {{{ */ if (file_exists($this->_document->_dms->contentDir . $this->_document->getID() .'/' . "index.html")) return true; if (!in_array($this->_fileType, array_keys($this->_document->_dms->convertFileTypes))) return false; $source = $this->_document->_dms->contentDir . $this->_document->getID() .'/' . $this->getFileName(); $target = $this->_document->_dms->contentDir . $this->_document->getID() .'/' . "index.html"; // $source = str_replace("/", "\\", $source); // $target = str_replace("/", "\\", $target); $command = $this->_document->_dms->convertFileTypes[$this->_fileType]; $command = str_replace("{SOURCE}", "\"$source\"", $command); $command = str_replace("{TARGET}", "\"$target\"", $command); $output = array(); $res = 0; exec($command, $output, $res); if ($res != 0) { print (implode("\n", $output)); return false; } return true; } /* }}} */ /* FIXME: this function should not be part of the DMS. It lies in the duty * of the application whether a file can viewed online or not. */ function viewOnline() { /* {{{ */ if (!isset($this->_document->_dms->_viewOnlineFileTypes) || !is_array($this->_document->_dms->_viewOnlineFileTypes)) { return false; } if (in_array(strtolower($this->_fileType), $this->_document->_dms->_viewOnlineFileTypes)) return true; if ($this->_document->_dms->enableConverting && in_array($this->_fileType, array_keys($this->_document->_dms->convertFileTypes))) if ($this->wasConverted()) return true; return false; } /* }}} */ function wasConverted() { /* {{{ */ return file_exists($this->_document->_dms->contentDir . $this->_document->getID() .'/' . "index.html"); } /* }}} */ function getURL() { /* {{{ */ if (!$this->viewOnline())return false; if (in_array(strtolower($this->_fileType), $this->_document->_dms->_viewOnlineFileTypes)) return "/" . $this->_document->getID() . "/" . $this->_version . "/" . $this->getOriginalFileName(); else return "/" . $this->_document->getID() . "/" . $this->_version . "/index.html"; } /* }}} */ /** * Get the latest status of the content * * The status of the content reflects its current review and approval * 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 but not necessarily * a release. * S_DRAFT_REV, 0 * S_DRAFT_APP, 1 * S_RELEASED, 2 * 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. */ function getStatus($limit=1) { /* {{{ */ $db = $this->_document->_dms->getDB(); if (!is_numeric($limit)) return false; // Retrieve the current overall status of the content represented by // this object. if (!isset($this->_status)) { /* if (!$db->createTemporaryTable("ttstatid", $forceTemporaryTable)) { return false; } $queryStr="SELECT `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ". "`tblDocumentStatusLog`.`comment`, `tblDocumentStatusLog`.`date`, ". "`tblDocumentStatusLog`.`userID` ". "FROM `tblDocumentStatus` ". "LEFT JOIN `tblDocumentStatusLog` USING (`statusID`) ". "LEFT JOIN `ttstatid` ON `ttstatid`.`maxLogID` = `tblDocumentStatusLog`.`statusLogID` ". "WHERE `ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` ". "AND `tblDocumentStatus`.`documentID` = '". $this->_document->getID() ."' ". "AND `tblDocumentStatus`.`version` = '". $this->_version ."' "; */ $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; } /* }}} */ /** * Set the status of the content * Setting the status means to add another entry into the table * tblDocumentStatusLog * * @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) { /* {{{ */ $db = $this->_document->_dms->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 > 2) { 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 false; } $queryStr = "INSERT INTO `tblDocumentStatusLog` (`statusID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $this->_status["statusID"] ."', '". (int) $status ."', ".$db->qstr($comment).", NOW(), '". $updateUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) return false; return true; } /* }}} */ /** * Get the current review status of the document content * The review status is a list of reviewers 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->_dms->getDB(); if (!is_numeric($limit)) return false; // Retrieve the current status of each assigned reviewer for the content // represented by this object. if (!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`.`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; } $this->_reviewStatus = array_merge($this->_reviewStatus, $res); } } } return $this->_reviewStatus; } /* }}} */ function getApprovalStatus($limit=1) { /* {{{ */ $db = $this->_document->_dms->getDB(); if (!is_numeric($limit)) return false; // Retrieve the current status of each assigned approver for the content // represented by this object. if (!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`.`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; } $this->_approvalStatus = array_merge($this->_approvalStatus, $res); } } } return $this->_approvalStatus; } /* }}} */ function addIndReviewer($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $userID = $user->getID(); // Get the list of users and groups with write access to this document. if (!isset($this->_approversList)) { $this->_approversList = $this->_document->getApproversList(); } $approved = false; foreach ($this->_approversList["users"] as $appUser) { if ($userID == $appUser->getID()) { $approved = true; break; } } if (!$approved) { 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; } if (count($reviewStatus["indstatus"]) > 0 && $reviewStatus["indstatus"][0]["status"]!=-2) { // User is already on the list of reviewers; return an error. return -3; } // Add the user into the review database. if (! isset($reviewStatus["indstatus"][0]["status"])|| (isset($reviewStatus["indstatus"][0]["status"]) && $reviewStatus["indstatus"][0]["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(); } else { $reviewID = isset($reviewStatus["indstatus"][0]["reviewID"])?$reviewStatus["indstatus"][0]["reviewID"]:NULL; } $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $reviewID ."', '0', '', NOW(), '". $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->_dms->getDB(); $groupID = $group->getID(); // Get the list of users and groups with write access to this document. if (!isset($this->_approversList)) { // TODO: error checking. $this->_approversList = $this->_document->getApproversList(); } $approved = false; foreach ($this->_approversList["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(); } else { $reviewID = isset($reviewStatus[0]["reviewID"])?$reviewStatus[0]["reviewID"]:NULL; } $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $reviewID ."', '0', '', NOW(), '". $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; } /* }}} */ function setReviewByInd($user, $requestUser, $status, $comment) { /* {{{ */ $db = $this->_document->_dms->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; } if ($reviewStatus["indstatus"][0]["status"]==-2) { // User has been deleted from reviewers return -4; } // Check if the status is really different from the current status if ($reviewStatus["indstatus"][0]["status"] == $status) return 0; $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $reviewStatus["indstatus"][0]["reviewID"] ."', '". (int) $status ."', ".$db->qstr($comment).", NOW(), '". $requestUser->getID() ."')"; $res=$db->getResult($queryStr); if (is_bool($res) && !$res) return -1; else return 0; } /* }}} */ function setReviewByGrp($group, $requestUser, $status, $comment) { /* {{{ */ $db = $this->_document->_dms->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).", NOW(), '". $requestUser->getID() ."')"; $res=$db->getResult($queryStr); if (is_bool($res) && !$res) return -1; else return 0; } /* }}} */ function addIndApprover($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $userID = $user->getID(); // Get the list of users and groups with write access to this document. if (!isset($this->_approversList)) { // TODO: error checking. $this->_approversList = $this->_document->getApproversList(); } $approved = false; foreach ($this->_approversList["users"] as $appUser) { if ($userID == $appUser->getID()) { $approved = true; break; } } if (!$approved) { 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; } if (count($approvalStatus["indstatus"]) > 0 && $approvalStatus["indstatus"][0]["status"]!=-2) { // User is already on the list of approvers; return an error. return -3; } if ( !isset($approvalStatus["indstatus"][0]["status"]) || (isset($approvalStatus["indstatus"][0]["status"]) && $approvalStatus["indstatus"][0]["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(); } else { $approveID = isset($approvalStatus["indstatus"][0]["approveID"]) ? $approvalStatus["indstatus"][0]["approveID"] : NULL; } $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $approveID ."', '0', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } return 0; } /* }}} */ function addGrpApprover($group, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $groupID = $group->getID(); // Get the list of users and groups with write access to this document. if (!isset($this->_approversList)) { // TODO: error checking. $this->_approversList = $this->_document->getApproversList(); } $approved = false; foreach ($this->_approversList["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(); } else { $approveID = isset($approvalStatus[0]["approveID"])?$approvalStatus[0]["approveID"]:NULL; } $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $approveID ."', '0', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } // Add approver to event notification table. //$this->_document->addNotify($groupID, false); return 0; } /* }}} */ /** * 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. The user initiating the approval may * not be the user filled in as an approver of the document content. * In most cases this will be 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. * * @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 * LetoDMS_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) { /* {{{ */ $db = $this->_document->_dms->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; } if ($approvalStatus["indstatus"][0]["status"]==-2) { // User has been deleted from approvers return -4; } // Check if the status is really different from the current status if ($approvalStatus["indstatus"][0]["status"] == $status) return 0; $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $approvalStatus["indstatus"][0]["approveID"] ."', '". (int) $status ."', ".$db->qstr($comment).", NOW(), '". $requestUser->getID() ."')"; $res=$db->getResult($queryStr); if (is_bool($res) && !$res) return -1; else return 0; } /* }}} */ /** * Sets approval status of a document content for a group * The functions behaves like * {link LetoDMS_Core_DocumentContent::setApprovalByInd} but does it for * group instead of a user */ function setApprovalByGrp($group, $requestUser, $status, $comment) { /* {{{ */ $db = $this->_document->_dms->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).", NOW(), '". $requestUser->getID() ."')"; $res=$db->getResult($queryStr); if (is_bool($res) && !$res) return -1; else return 0; } /* }}} */ function delIndReviewer($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->getDB(); $userID = $user->getID(); // 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; } if ($reviewStatus["indstatus"][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["indstatus"][0]["reviewID"] ."', '-2', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } return 0; } /* }}} */ function delGrpReviewer($group, $requestUser) { /* {{{ */ $db = $this->_document->_dms->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 -3; } 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"] ."', '-2', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } return 0; } /* }}} */ function delIndApprover($user, $requestUser) { /* {{{ */ $db = $this->_document->_dms->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 -3; } if ($approvalStatus["indstatus"][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["indstatus"][0]["approveID"] ."', '-2', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } return 0; } /* }}} */ function delGrpApprover($group, $requestUser) { /* {{{ */ $db = $this->_document->_dms->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 -3; } 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"] ."', '-2', '', NOW(), '". $requestUser->getID() ."')"; $res = $db->getResult($queryStr); if (is_bool($res) && !$res) { return -1; } return 0; } /* }}} */ } /* }}} */ /** * 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 LetoDMS_Core_Document::addDocumentLink()} to add a reference * to another document. * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, * Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DocumentLink { /* {{{ */ var $_id; var $_document; var $_target; var $_userID; var $_public; function LetoDMS_Core_DocumentLink($id, $document, $target, $userID, $public) { $this->_id = $id; $this->_document = $document; $this->_target = $target; $this->_userID = $userID; $this->_public = $public; } function getID() { return $this->_id; } function getDocument() { return $this->_document; } function getTarget() { return $this->_target; } function getUser() { if (!isset($this->_user)) $this->_user = $this->_document->_dms->getUser($this->_userID); return $this->_user; } function isPublic() { return $this->_public; } } /* }}} */ /** * 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 LetoDMS_Core_Document::addDocumentFile()} to attach a file. * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, * Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DocumentFile { /* {{{ */ var $_id; var $_document; var $_userID; var $_comment; var $_date; var $_dir; var $_fileType; var $_mimeType; var $_orgFileName; var $_name; function LetoDMS_Core_DocumentFile($id, $document, $userID, $comment, $date, $dir, $fileType, $mimeType, $orgFileName,$name) { $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; } function getID() { return $this->_id; } function getDocument() { return $this->_document; } function getUserID() { return $this->_userID; } function getComment() { return $this->_comment; } function getDate() { return $this->_date; } function getDir() { return $this->_dir; } function getFileType() { return $this->_fileType; } function getMimeType() { return $this->_mimeType; } function getOriginalFileName() { return $this->_orgFileName; } function getName() { return $this->_name; } function getUser() { if (!isset($this->_user)) $this->_user = $this->_document->_dms->getUser($this->_userID); return $this->_user; } function getPath() { return $this->_document->getDir() . "f" .$this->_id . $this->_fileType; } } /* }}} */ // // 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 LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, * Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_AddContentResultSet { /* {{{ */ var $_indReviewers; var $_grpReviewers; var $_indApprovers; var $_grpApprovers; var $_content; var $_status; function LetoDMS_Core_AddContentResultSet($content) { $this->_content = $content; $this->_indReviewers = null; $this->_grpReviewers = null; $this->_indApprovers = null; $this->_grpApprovers = null; $this->_status = null; } function addReviewer($reviewer, $type, $status) { if (!is_object($reviewer) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){ return false; } if (!strcasecmp($type, "i")) { if (strcasecmp(get_class($reviewer), "LetoDMS_Core_User")) { return false; } if ($this->_indReviewers == null) { $this->_indReviewers = array(); } $this->_indReviewers[$status][] = $reviewer; } if (!strcasecmp($type, "g")) { if (strcasecmp(get_class($reviewer), "LetoDMS_Core_Group")) { return false; } if ($this->_grpReviewers == null) { $this->_grpReviewers = array(); } $this->_grpReviewers[$status][] = $reviewer; } return true; } function addApprover($approver, $type, $status) { if (!is_object($approver) || (strcasecmp($type, "i") && strcasecmp($type, "g")) && !is_integer($status)){ return false; } if (!strcasecmp($type, "i")) { if (strcasecmp(get_class($approver), "LetoDMS_Core_User")) { return false; } if ($this->_indApprovers == null) { $this->_indApprovers = array(); } $this->_indApprovers[$status][] = $approver; } if (!strcasecmp($type, "g")) { if (strcasecmp(get_class($approver), "LetoDMS_Core_Group")) { return false; } if ($this->_grpApprovers == null) { $this->_grpApprovers = array(); } $this->_grpApprovers[$status][] = $approver; } return true; } function setStatus($status) { if (!is_integer($status)) { return false; } if ($status<-3 || $status>2) { return false; } $this->_status = $status; return true; } function getStatus() { return $this->_status; } 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); } } 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); } } } /* }}} */ ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassDocumentCategory.php000066400000000000000000000050531205716546300263500ustar00rootroot00000000000000 * @copyright Copyright (C) 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a document category in the document management system * * @category DMS * @package LetoDMS_Core * @author Uwe Steinmann * @copyright Copyright (C)2011 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DocumentCategory { /** * @var integer $_id id of document category * @access protected */ var $_id; /** * @var string $_name name of category * @access protected */ var $_name; /** * @var object $_dms reference to dms this category belongs to * @access protected */ var $_dms; function LetoDMS_Core_DocumentCategory($id, $name) { $this->_id = $id; $this->_name = $name; $this->_dms = null; } function setDMS($dms) { $this->_dms = $dms; } function getID() { return $this->_id; } function getName() { return $this->_name; } function setName($newName) { $db = $this->_dms->getDB(); $queryStr = "UPDATE tblCategory SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id; if (!$db->getResult($queryStr)) return false; $this->_name = $newName; return true; } function isUsed() { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblDocumentCategory WHERE categoryID=".$this->_id; $resArr = $db->getResultArray($queryStr); if (is_array($resArr) && count($resArr) == 0) return false; return true; } function getCategories() { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblCategory"; return $db->getResultArray($queryStr); } function addCategory($keywords) { $db = $this->_dms->getDB(); $queryStr = "INSERT INTO tblCategory (category) VALUES (".$db->qstr($keywords).")"; return $db->getResult($queryStr); } function remove() { $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblCategory WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; return true; } function getDocumentsByCategory() { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblDocumentCategory where categoryID=".$this->_id; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $documents = array(); foreach ($resArr as $row) { array_push($documents, $this->_dms->getDocument($row["id"])); } return $documents; } } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassFolder.php000066400000000000000000001117471205716546300243170ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a folder in the document management system * * A folder in LetoDMS is equivalent to a directory in a regular file * system. It can contain further subfolders and documents. Each folder * has a single parent except for the root folder which has no parent. * * @category DMS * @package LetoDMS_Core * @version @version@ * @author Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_Folder { /** * @var integer unique id of folder */ var $_id; /** * @var string name of folder */ var $_name; /** * @var integer id of parent folder */ var $_parentID; /** * @var string comment of document */ var $_comment; /** * @var integer id of user who is the owner */ var $_ownerID; /** * @var boolean true if access is inherited, otherwise false */ var $_inheritAccess; /** * @var integer default access if access rights are not inherited */ var $_defaultAccess; /** * @var array list of notifications for users and groups */ var $_notifyList; /** * @var integer position of folder within the parent folder */ var $_sequence; /** * @var object back reference to document management system */ var $_dms; function LetoDMS_Core_Folder($id, $name, $parentID, $comment, $date, $ownerID, $inheritAccess, $defaultAccess, $sequence) { /* {{{ */ $this->_id = $id; $this->_name = $name; $this->_parentID = $parentID; $this->_comment = $comment; $this->_date = $date; $this->_ownerID = $ownerID; $this->_inheritAccess = $inheritAccess; $this->_defaultAccess = $defaultAccess; $this->_sequence = $sequence; $this->_notifyList = array(); $this->_dms = null; } /* }}} */ /* * Set dms this folder belongs to. * * Each folder needs a reference to the dms it belongs to. It will be * set when the folder is created by LetoDMS::getFolder(). The dms has a * references to the currently logged in user and the database connection. * * @param object $dms reference to dms */ function setDMS($dms) { /* {{{ */ $this->_dms = $dms; } /* }}} */ /* * Get the internal id of the folder. * * @return integer id of folder */ function getID() { return $this->_id; } /* * Get the name of the folder. * * @return string name of folder */ function getName() { return $this->_name; } /* * Set the name of the folder. * * @param string $newName set a new name of the folder */ function setName($newName) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblFolders SET name = " . $db->qstr($newName) . " WHERE id = ". $this->_id; if (!$db->getResult($queryStr)) return false; $this->_name = $newName; return true; } /* }}} */ function getComment() { return $this->_comment; } function setComment($newComment) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblFolders SET comment = " . $db->qstr($newComment) . " WHERE id = ". $this->_id; if (!$db->getResult($queryStr)) return false; $this->_comment = $newComment; return true; } /* }}} */ /** * Return creation date of folder * * @return integer unix timestamp of creation date */ function getDate() { /* {{{ */ return $this->_date; } /* }}} */ /** * Returns the parent * * @return object parent folder or false if there is no parent folder */ function getParent() { /* {{{ */ if ($this->_id == $this->_dms->rootFolderID || empty($this->_parentID)) { return false; } if (!isset($this->_parent)) { $this->_parent = $this->_dms->getFolder($this->_parentID); } return $this->_parent; } /* }}} */ /** * Set a new folder * * This function moves a folder from one parent folder into another parent * folder. It will fail if the root folder is moved. * * @param object new parent folder * @return boolean true if operation was successful otherwise false */ function setParent($newParent) { /* {{{ */ $db = $this->_dms->getDB(); if ($this->_id == $this->_dms->rootFolderID || empty($this->_parentID)) { return false; } // Update the folderList of the folder $pathPrefix=""; $path = $newParent->getPath(); foreach ($path as $f) { $pathPrefix .= ":".$f->getID(); } if (strlen($pathPrefix)>1) { $pathPrefix .= ":"; } $queryStr = "UPDATE tblFolders SET parent = ".$newParent->getID().", folderList='".$pathPrefix."' WHERE id = ". $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_parentID = $newParent->getID(); $this->_parent = $newParent; // Must also ensure that any documents in this folder tree have their // folderLists updated. $pathPrefix=""; $path = $this->getPath(); foreach ($path as $f) { $pathPrefix .= ":".$f->getID(); } if (strlen($pathPrefix)>1) { $pathPrefix .= ":"; } $queryStr = "SELECT `tblDocuments`.`id`, `tblDocuments`.`folderList` FROM `tblDocuments` WHERE `folderList` LIKE '%:".$this->_id.":%'"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; foreach ($resArr as $row) { $newPath = preg_replace("/^.*:".$this->_id.":(.*$)/", $pathPrefix."\\1", $row["folderList"]); $queryStr="UPDATE `tblDocuments` SET `folderList` = '".$newPath."' WHERE `tblDocuments`.`id` = '".$row["id"]."'"; $res = $db->getResult($queryStr); } return true; } /* }}} */ /** * Returns the owner * * @return object owner of the folder */ function getOwner() { /* {{{ */ if (!isset($this->_owner)) $this->_owner = $this->_dms->getUser($this->_ownerID); return $this->_owner; } /* }}} */ /** * Set the owner * * @param object new owner of the folder * @return boolean true if successful otherwise false */ function setOwner($newOwner) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblFolders set owner = " . $newOwner->getID() . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_ownerID = $newOwner->getID(); $this->_owner = $newOwner; return true; } /* }}} */ function getDefaultAccess() { /* {{{ */ if ($this->inheritsAccess()) { $res = $this->getParent(); if (!$res) return false; return $this->_parent->getDefaultAccess(); } return $this->_defaultAccess; } /* }}} */ function setDefaultAccess($mode) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblFolders set defaultAccess = " . (int) $mode . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_defaultAccess = $mode; // If any of the notification subscribers no longer have read access, // remove their subscription. if (empty($this->_notifyList)) $this->getNotifyList(); foreach ($this->_notifyList["users"] as $u) { if ($this->getAccessMode($u) < M_READ) { $this->removeNotify($u->getID(), true); } } foreach ($this->_notifyList["groups"] as $g) { if ($this->getGroupAccessMode($g) < M_READ) { $this->removeNotify($g->getID(), false); } } return true; } /* }}} */ function inheritsAccess() { return $this->_inheritAccess; } function setInheritAccess($inheritAccess) { /* {{{ */ $db = $this->_dms->getDB(); $inheritAccess = ($inheritAccess) ? "1" : "0"; $queryStr = "UPDATE tblFolders SET inheritAccess = " . (int) $inheritAccess . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_inheritAccess = $inheritAccess; // If any of the notification subscribers no longer have read access, // remove their subscription. if (empty($this->_notifyList)) $this->getNotifyList(); foreach ($this->_notifyList["users"] as $u) { if ($this->getAccessMode($u) < M_READ) { $this->removeNotify($u->getID(), true); } } foreach ($this->_notifyList["groups"] as $g) { if ($this->getGroupAccessMode($g) < M_READ) { $this->removeNotify($g->getID(), false); } } return true; } /* }}} */ function getSequence() { return $this->_sequence; } function setSequence($seq) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblFolders SET sequence = " . $seq . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_sequence = $seq; return true; } /* }}} */ /** * Returns a list of subfolders * This function does not check for access rights. Use * {@link LetoDMS_Core_DMS::filterAccess} for checking each folder against * the currently logged in user and the access rights. * * @param string $orderby if set to 'n' the list is ordered by name, otherwise * it will be ordered by sequence * @return array list of folder objects or false in case of an error */ function getSubFolders($orderby="") { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_subFolders)) { if ($orderby=="n") $queryStr = "SELECT * FROM tblFolders WHERE parent = " . $this->_id . " ORDER BY name"; else $queryStr = "SELECT * FROM tblFolders WHERE parent = " . $this->_id . " ORDER BY sequence"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $this->_subFolders = array(); for ($i = 0; $i < count($resArr); $i++) // $this->_subFolders[$i] = new LetoDMS_Core_Folder($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["parent"], $resArr[$i]["comment"], $resArr[$i]["owner"], $resArr[$i]["inheritAccess"], $resArr[$i]["defaultAccess"], $resArr[$i]["sequence"]); $this->_subFolders[$i] = $this->_dms->getFolder($resArr[$i]["id"]); } return $this->_subFolders; } /* }}} */ function addSubFolder($name, $comment, $owner, $sequence) { /* {{{ */ $db = $this->_dms->getDB(); // Set the folderList of the folder $pathPrefix=""; $path = $this->getPath(); foreach ($path as $f) { $pathPrefix .= ":".$f->getID(); } if (strlen($pathPrefix)>1) { $pathPrefix .= ":"; } //inheritAccess = true, defaultAccess = M_READ $queryStr = "INSERT INTO tblFolders (name, parent, folderList, comment, date, owner, inheritAccess, defaultAccess, sequence) ". "VALUES (".$db->qstr($name).", ".$this->_id.", ".$db->qstr($pathPrefix).", ".$db->qstr($comment).", ".mktime().", ".$owner->getID().", 1, ".M_READ.", ". $sequence.")"; if (!$db->getResult($queryStr)) return false; $newFolder = $this->_dms->getFolder($db->getInsertID()); unset($this->_subFolders); return $newFolder; } /* }}} */ /** * Returns an array of all parents, grand parent, etc. up to root folder. * The folder itself is the last element of the array. * * @return array Array of parents */ function getPath() { /* {{{ */ if (!isset($this->_parentID) || ($this->_parentID == "") || ($this->_parentID == 0)) { return array($this); } else { $res = $this->getParent(); if (!$res) return false; $path = $this->_parent->getPath(); if (!$path) return false; array_push($path, $this); return $path; } } /* }}} */ /** * Returns a unix file system path * * @return string path separated with '/' */ function getFolderPathPlain() { /* {{{ */ $path=""; $folderPath = $this->getPath(); for ($i = 0; $i < count($folderPath); $i++) { $path .= $folderPath[$i]->getName(); if ($i +1 < count($folderPath)) $path .= " / "; } return $path; } /* }}} */ /** * Check, if this folder is a subfolder of a given folder * * @param object $folder parent folder * @return boolean true if folder is a subfolder */ function isDescendant($folder) { /* {{{ */ if ($this->_parentID == $folder->getID()) return true; elseif (isset($this->_parentID)) { $res = $this->getParent(); if (!$res) return false; return $this->_parent->isDescendant($folder); } else return false; } /* }}} */ /** * Get all documents of the folder * This function does not check for access rights. Use * {@link LetoDMS_Core_DMS::filterAccess} for checking each document against * the currently logged in user and the access rights. * * @param string $orderby if set to 'n' the list is ordered by name, otherwise * it will be ordered by sequence * @return array list of documents or false in case of an error */ function getDocuments($orderby="") { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_documents)) { if ($orderby=="n") $queryStr = "SELECT * FROM tblDocuments WHERE folder = " . $this->_id . " ORDER BY name"; else $queryStr = "SELECT * FROM tblDocuments WHERE folder = " . $this->_id . " ORDER BY sequence"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && !$resArr) return false; $this->_documents = array(); foreach ($resArr as $row) { // array_push($this->_documents, new LetoDMS_Core_Document($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], isset($row["lockUser"])?$row["lockUser"]:NULL, $row["keywords"], $row["sequence"])); array_push($this->_documents, $this->_dms->getDocument($row["id"])); } } return $this->_documents; } /* }}} */ // $comment will be used for both document and version leaving empty the version_comment /** * Add a new document to the folder * This function will add a new document and its content from a given file. * It does not check for access rights on the folder. The new documents * default access right is read only and the access right is inherited. * * @param string $name name of new document * @param string $comment comment of new document * @param integer $expires expiration date as a unix timestamp or 0 for no * expiration date * @param object $owner owner of the new document * @param string $keywords keywords of new document * @param array $categories list of category ids * @param string $tmpFile the path of the file containing the content * @param string $orgFileName the original file name * @param string $fileType usually the extension of the filename * @param string $mimeType mime type of the content * @param float $sequence position of new document within the folder * @param array $reviewers list of users who must review this document * @param array $approvers list of users who must approve this document * @param string $reqversion version number of the content * @param string $version_comment comment of the content. If left empty * the $comment will be used. * @return array/boolean false in case of error, otherwise an array * containing two elements. The first one is the new document, the * second one is the result set returned when inserting the content. */ function addDocument($name, $comment, $expires, $owner, $keywords, $categories, $tmpFile, $orgFileName, $fileType, $mimeType, $sequence, $reviewers=array(), $approvers=array(),$reqversion,$version_comment="") { /* {{{ */ $db = $this->_dms->getDB(); $expires = (!$expires) ? 0 : $expires; // Must also ensure that the document has a valid folderList. $pathPrefix=""; $path = $this->getPath(); foreach ($path as $f) { $pathPrefix .= ":".$f->getID(); } if (strlen($pathPrefix)>1) { $pathPrefix .= ":"; } $queryStr = "INSERT INTO tblDocuments (name, comment, date, expires, owner, folder, folderList, inheritAccess, defaultAccess, locked, keywords, sequence) VALUES ". "(".$db->qstr($name).", ".$db->qstr($comment).", " . mktime().", ".(int) $expires.", ".$owner->getID().", ".$this->_id.",".$db->qstr($pathPrefix).", 1, ".M_READ.", -1, ".$db->qstr($keywords).", " . $sequence . ")"; if (!$db->getResult($queryStr)) return false; $document = $this->_dms->getDocument($db->getInsertID()); if ($version_comment!="") $res = $document->addContent($version_comment, $owner, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers, $approvers,$reqversion); else $res = $document->addContent($comment, $owner, $tmpFile, $orgFileName, $fileType, $mimeType, $reviewers, $approvers,$reqversion); if (is_bool($res) && !$res) { $queryStr = "DELETE FROM tblDocuments WHERE id = " . $document->getID(); $db->getResult($queryStr); return false; } if($categories) { $document->setCategories($categories); } return array($document, $res); } /* }}} */ function remove() { /* {{{ */ $db = $this->_dms->getDB(); // Do not delete the root folder. if ($this->_id == $this->_dms->rootFolderID || !isset($this->_parentID) || ($this->_parentID == null) || ($this->_parentID == "") || ($this->_parentID == 0)) { return false; } //Entfernen der Unterordner und Dateien $res = $this->getSubFolders(); if (is_bool($res) && !$res) return false; $res = $this->getDocuments(); if (is_bool($res) && !$res) return false; foreach ($this->_subFolders as $subFolder) { $res = $subFolder->remove(FALSE); if (!$res) return false; } foreach ($this->_documents as $document) { $res = $document->remove(FALSE); if (!$res) return false; } //Entfernen der Datenbankeinträge $queryStr = "DELETE FROM tblFolders WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblACLs WHERE target = ". $this->_id. " AND targetType = " . T_FOLDER; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblNotify WHERE target = ". $this->_id. " AND targetType = " . T_FOLDER; if (!$db->getResult($queryStr)) return false; 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 LetoDMS_Core_UserAccess} and * {@link LetoDMS_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 integer $mode access mode (defaults to M_ANY) * @param integer $op operation (defaults to O_EQ) * @return array multi dimensional array */ function getAccessList($mode = M_ANY, $op = O_EQ) { /* {{{ */ $db = $this->_dms->getDB(); if ($this->inheritsAccess()) { $res = $this->getParent(); if (!$res) return false; return $this->_parent->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_FOLDER. " 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 LetoDMS_Core_UserAccess($this->_dms->getUser($row["userID"]), $row["mode"])); else //if ($row["groupID"] != -1) array_push($this->_accessList[$mode]["groups"], new LetoDMS_Core_GroupAccess($this->_dms->getGroup($row["groupID"]), $row["mode"])); } } return $this->_accessList[$mode]; } /* }}} */ /** * Delete all entries for this folder from the access control list * * @return boolean true if operation was successful otherwise false */ function clearAccessList() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblACLs WHERE targetType = " . T_FOLDER . " AND target = " . $this->_id; if (!$db->getResult($queryStr)) return false; unset($this->_accessList); return true; } /* }}} */ /** * 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 */ 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_FOLDER.", " . (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 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 $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 */ function changeAccess($newMode, $userOrGroupID, $isUser) { /* {{{ */ $db = $this->_dms->getDB(); $userOrGroup = ($isUser) ? "userID" : "groupID"; $queryStr = "UPDATE tblACLs SET mode = " . (int) $newMode . " WHERE targetType = ".T_FOLDER." 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; } /* }}} */ function removeAccess($userOrGroupID, $isUser) { /* {{{ */ $db = $this->_dms->getDB(); $userOrGroup = ($isUser) ? "userID" : "groupID"; $queryStr = "DELETE FROM tblACLs WHERE targetType = ".T_FOLDER." AND target = ".$this->_id." AND ".$userOrGroup." = " . (int) $userOrGroupID; if (!$db->getResult($queryStr)) return false; unset($this->_accessList); // Update the notify list, if necessary. $mode = ($isUser ? $this->getAccessMode($this->_dms->getUser($userOrGroupID)) : $this->getGroupAccessMode($this->_dms->getGroup($userOrGroupID))); if ($mode == M_NONE) { $this->removeNotify($userOrGroupID, $isUser); } return true; } /* }}} */ /** * Get the access mode of a user on the folder * * 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. * * 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. * * @param object $user user for which access shall be checked * @return integer access mode */ function getAccessMode($user) { /* {{{ */ /* Admins have full access */ if ($user->isAdmin()) return M_ALL; /* User has full access if he/she is the owner of the document */ if ($user->getID() == $this->_ownerID) return M_ALL; /* Guest has read access by default, if guest login is allowed at all */ if ($user->isGuest()) { $mode = $this->getDefaultAccess(); if ($mode >= M_READ) return M_READ; else return M_NONE; } /* check ACLs */ $accessList = $this->getAccessList(); if (!$accessList) return false; foreach ($accessList["users"] as $userAccess) { if ($userAccess->getUserID() == $user->getID()) { return $userAccess->getMode(); } } /* Get the highest right defined by a group */ $result = 0; foreach ($accessList["groups"] as $groupAccess) { if ($user->isMemberOfGroup($groupAccess->getGroup())) { if ($groupAccess->getMode() > $result) $result = $groupAccess->getMode(); // return $groupAccess->getMode(); } } if($result) return $result; $result = $this->getDefaultAccess(); return $result; } /* }}} */ /** * Get the access mode for a group on the folder * This function returns the access mode for a given group. The algorithmn * applied to get the access mode is the same as describe at * {@link getAccessMode} * * @param object $group group for which access shall be checked * @return integer access mode */ function getGroupAccessMode($group) { /* {{{ */ $highestPrivileged = M_NONE; $foundInACL = false; $accessList = $this->getAccessList(); if (!$accessList) return false; foreach ($accessList["groups"] as $groupAccess) { if ($groupAccess->getGroupID() == $group->getID()) { $foundInACL = true; if ($groupAccess->getMode() > $highestPrivileged) $highestPrivileged = $groupAccess->getMode(); if ($highestPrivileged == M_ALL) /* no need to check further */ return $highestPrivileged; } } if ($foundInACL) return $highestPrivileged; /* Take default access */ return $this->getDefaultAccess(); } /* }}} */ /** * Get a list of all notification * This function returns all users and groups that have registerd a * notification for the folder * * @return array array with a the elements 'users' and 'groups' which * contain a list of users and groups. */ function getNotifyList() { /* {{{ */ if (empty($this->_notifyList)) { $db = $this->_dms->getDB(); $queryStr ="SELECT * FROM tblNotify WHERE targetType = " . T_FOLDER . " 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) array_push($this->_notifyList["users"], $this->_dms->getUser($row["userID"]) ); else //if ($row["groupID"] != -1) array_push($this->_notifyList["groups"], $this->_dms->getGroup($row["groupID"]) ); } } return $this->_notifyList; } /* }}} */ /* * 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 integer $userOrGroupID * @param boolean $isUser true if $userOrGroupID is a user id otherwise false * @return integer error code * -1: Invalid User/Group ID. * -2: Target User / Group does not have read access. * -3: User is already subscribed. * -4: Database / internal error. * 0: Update successful. */ 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 user / group has read access to the document. // if ($isUser) { // Users are straightforward to check. if ($this->getAccessMode($obj) < M_READ) { return -2; } } else { // FIXME: Why not check the access list first and if this returns // not result, then use the default access? // 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; 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; 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_FOLDER."' ". "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_FOLDER . ", " . (int) $userOrGroupID . ")"; if (!$db->getResult($queryStr)) return -4; unset($this->_notifyList); return 0; } /* }}} */ /* * Removes notify for a user or group to folder * 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 * @param boolean $isUser true if $userOrGroupID is a user id otherwise false * @return integer error code * -1: Invalid User/Group ID. * -3: User is not subscribed. * -4: Database / internal error. * 0: Update successful. */ function removeNotify($userOrGroupID, $isUser) { /* {{{ */ $db = $this->_dms->getDB(); /* Verify that user / group exists. */ $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_FOLDER."' ". "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_FOLDER . " AND " . $userOrGroup . " = " . (int) $userOrGroupID; if (!$db->getResult($queryStr)) return -4; unset($this->_notifyList); return 0; } /* }}} */ function getApproversList() { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_approversList)) { $this->_approversList = array("groups" => array(), "users" => array()); $userIDs = ""; $groupIDs = ""; $defAccess = $this->getDefaultAccess(); if ($defAccessgetAccessList(M_READ, O_GTEQ); } else { // Get the list of all users and groups that DO NOT have write access // to the folder. $tmpList = $this->getAccessList(M_NONE, O_LTEQ); } foreach ($tmpList["groups"] as $groupAccess) { $groupIDs .= (strlen($groupIDs)==0 ? "" : ", ") . $groupAccess->getGroupID(); } foreach ($tmpList["users"] as $userAccess) { $user = $userAccess->getUser(); if (!$user->isGuest()) { $userIDs .= (strlen($userIDs)==0 ? "" : ", ") . $userAccess->getUserID(); } } // Construct a query against the users table to identify those users // that have write access to this folder, either directly through an // ACL entry, by virtue of ownership or by having administrative rights // on the database. $queryStr=""; 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` != ".LetoDMS_Core_User::role_guest.")"; } $queryStr .= (strlen($queryStr)==0 ? "" : " UNION "). "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE (`tblUsers`.`role` != ".LetoDMS_Core_User::role_guest.") ". "AND ((`tblUsers`.`id` = ". $this->_ownerID . ") ". "OR (`tblUsers`.`role` = ".LetoDMS_Core_User::role_admin.")". (strlen($userIDs) == 0 ? "" : " OR (`tblUsers`.`id` IN (". $userIDs ."))"). ")) ORDER BY `login`"; } 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` != ".LetoDMS_Core_User::role_guest." ". (strlen($userIDs) == 0 ? ")" : " AND (`tblUsers`.`id` NOT IN (". $userIDs .")))"); } $queryStr .= (strlen($queryStr)==0 ? "" : " UNION "). "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE (`tblUsers`.`id` = ". $this->_ownerID . ") ". "OR (`tblUsers`.`role` = ".LetoDMS_Core_User::role_admin."))". "UNION ". "(SELECT `tblUsers`.* FROM `tblUsers` ". "WHERE `tblUsers`.`role` != ".LetoDMS_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 (!$this->_dms->enableAdminRevApp && $user->isAdmin()) continue; $this->_approversList["users"][] = $user; } } // Assemble the list of groups that have write access to the folder. $queryStr=""; if ($defAccess < M_READ) { if (strlen($groupIDs)>0) { $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". "WHERE `tblGroups`.`id` IN (". $groupIDs .")"; } } else { if (strlen($groupIDs)>0) { $queryStr = "SELECT `tblGroups`.* FROM `tblGroups` ". "WHERE `tblGroups`.`id` NOT IN (". $groupIDs .")"; } else { $queryStr = "SELECT `tblGroups`.* FROM `tblGroups`"; } } if (strlen($queryStr)>0) { $resArr = $db->getResultArray($queryStr); if (!is_bool($resArr)) { foreach ($resArr as $row) { $group = $this->_dms->getGroup($row["id"]); $this->_approversList["groups"][] = $group; } } } } return $this->_approversList; } /* }}} */ /** * 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 tblFolders 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 folder 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->getParent(); $pathPrefix=""; $path = $parent->getPath(); foreach ($path as $f) { $pathPrefix .= ":".$f->getID(); } if (strlen($pathPrefix)>1) { $pathPrefix .= ":"; } if($curfolderlist != $pathPrefix) { $queryStr = "UPDATE tblFolders SET folderList='".$pathPrefix."' WHERE id = ". $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; } return true; } /* }}} */ } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassGroup.php000066400000000000000000000227611205716546300241750ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a user group in the document management system * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_Group { /** * The id of the user group * * @var integer */ var $_id; /** * The name of the user group * * @var string */ var $_name; /** * Back reference to DMS this user group belongs to * * @var object */ var $_dms; function LetoDMS_Core_Group($id, $name, $comment) { /* {{{ */ $this->_id = $id; $this->_name = $name; $this->_comment = $comment; $this->_dms = null; } /* }}} */ function setDMS($dms) { /* {{{ */ $this->_dms = $dms; } /* }}} */ function getID() { return $this->_id; } function getName() { return $this->_name; } function setName($newName) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblGroups SET name = ".$db->qstr($newName)." WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_name = $newName; return true; } /* }}} */ function getComment() { return $this->_comment; } function setComment($newComment) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblGroups SET comment = ".$db->qstr($newComment)." WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_comment = $newComment; return true; } /* }}} */ function getUsers() { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_users)) { $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". "WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."'"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $this->_users = array(); foreach ($resArr as $row) { $user = new LetoDMS_Core_User($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']); array_push($this->_users, $user); } } return $this->_users; } /* }}} */ function getManagers() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ". "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ". "WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."' AND tblGroupMembers.manager = 1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $managers = array(); foreach ($resArr as $row) { $user = new LetoDMS_Core_User($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']); array_push($managers, $user); } return $managers; } /* }}} */ function addUser($user,$asManager=false) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "INSERT INTO tblGroupMembers (groupID, userID, manager) VALUES (".$this->_id.", ".$user->getID(). ", " . ($asManager?"1":"0") ." )"; $res = $db->getResult($queryStr); if ($res) return false; unset($this->_users); return true; } /* }}} */ function removeUser($user) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblGroupMembers WHERE groupID = ".$this->_id." AND userID = ".$user->getID(); $res = $db->getResult($queryStr); if ($res) return false; unset($this->_users); return true; } /* }}} */ // $asManager=false: verify if user is in group // $asManager=true : verify if user is in group as manager function isMember($user,$asManager=false) { /* {{{ */ if (isset($this->_users)&&!$asManager) { foreach ($this->_users as $usr) if ($usr->getID() == $user->getID()) return true; return false; } $db = $this->_dms->getDB(); if ($asManager) $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID() . " AND manager = 1"; else $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID(); $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr) != 1) return false; return true; } /* }}} */ function toggleManager($user) { /* {{{ */ $db = $this->_dms->getDB(); if (!$this->isMember($user)) return false; if ($this->isMember($user,true)) $queryStr = "UPDATE tblGroupMembers SET manager = 0 WHERE groupID = ".$this->_id." AND userID = ".$user->getID(); else $queryStr = "UPDATE tblGroupMembers SET manager = 1 WHERE groupID = ".$this->_id." AND userID = ".$user->getID(); if (!$db->getResult($queryStr)) return false; return true; } /* }}} */ /** * Delete user group * This function deletes the user group and all it references, like access * control lists, notifications, as a child of other groups, etc. * * @param object $user the user doing the removal (needed for entry in * review log. * @return boolean true on success or false in case of an error */ function remove($user) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblGroups WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblGroupMembers WHERE groupID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblACLs WHERE groupID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblNotify WHERE groupID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblMandatoryReviewers WHERE reviewerGroupID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblMandatoryApprovers WHERE approverGroupID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // TODO : update document status if reviewer/approver has been deleted $reviewStatus = $this->getReviewStatus(); foreach ($reviewStatus as $r) { $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $r["reviewID"] ."', '-2', 'Review group removed from process', NOW(), '". $user->getID() ."')"; $res=$db->getResult($queryStr); } $approvalStatus = $this->getApprovalStatus(); foreach ($approvalStatus as $a) { $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $a["approveID"] ."', '-2', 'Approval group removed from process', NOW(), '". $user->getID() ."')"; $res=$db->getResult($queryStr); } return true; } /* }}} */ function getReviewStatus($documentID=null, $version=null) { /* {{{ */ $db = $this->_dms->getDB(); if (!$db->createTemporaryTable("ttreviewid")) { return false; } $status = array(); // See if the group is assigned as a reviewer. $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ". "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ". "`tblDocumentReviewLog`.`userID` ". "FROM `tblDocumentReviewers` ". "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ". "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ". "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ". ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' "). "AND `tblDocumentReviewers`.`type`='1' ". "AND `tblDocumentReviewers`.`required`='". $this->_id ."' "; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status[] = $res; } return $status; } /* }}} */ function getApprovalStatus($documentID=null, $version=null) { /* {{{ */ $db = $this->_dms->getDB(); if (!$db->createTemporaryTable("ttapproveid")) { return false; } $status = array(); // See if the group is assigned as an approver. $queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ". "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". "`tblDocumentApproveLog`.`userID` ". "FROM `tblDocumentApprovers` ". "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ". "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ". ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' "). "AND `tblDocumentApprovers`.`type`='1' ". "AND `tblDocumentApprovers`.`required`='". $this->_id ."' "; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status[] = $res; } return $status; } /* }}} */ } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassKeywords.php000066400000000000000000000065221205716546300247050ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a keyword category in the document management system * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_KeywordCategory { /** * @var integer $_id id of keyword category * @access protected */ var $_id; /** * @var integer $_ownerID id of user who is the owner * @access protected */ var $_ownerID; /** * @var string $_name name of category * @access protected */ var $_name; /** * @var object $_dms reference to dms this category belongs to * @access protected */ var $_dms; function LetoDMS_Core_KeywordCategory($id, $ownerID, $name) { $this->_id = $id; $this->_name = $name; $this->_ownerID = $ownerID; $this->_dms = null; } function setDMS($dms) { $this->_dms = $dms; } function getID() { return $this->_id; } function getName() { return $this->_name; } function getOwner() { if (!isset($this->_owner)) $this->_owner = $this->_dms->getUser($this->_ownerID); return $this->_owner; } function setName($newName) { $db = $this->_dms->getDB(); $queryStr = "UPDATE tblKeywordCategories SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id; if (!$db->getResult($queryStr)) return false; $this->_name = $newName; return true; } function setOwner($user) { $db = $this->_dms->getDB(); $queryStr = "UPDATE tblKeywordCategories SET owner = " . $user->getID() . " WHERE id " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_ownerID = $user->getID(); $this->_owner = $user; return true; } function getKeywordLists() { $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblKeywords WHERE category = " . $this->_id; return $db->getResultArray($queryStr); } function editKeywordList($listID, $keywords) { $db = $this->_dms->getDB(); $queryStr = "UPDATE tblKeywords SET keywords = ".$db->qstr($keywords)." WHERE id = $listID"; return $db->getResult($queryStr); } function addKeywordList($keywords) { $db = $this->_dms->getDB(); $queryStr = "INSERT INTO tblKeywords (category, keywords) VALUES (" . $this->_id . ", ".$db->qstr($keywords).")"; return $db->getResult($queryStr); } function removeKeywordList($listID) { $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblKeywords WHERE id = $listID"; return $db->getResult($queryStr); } function remove() { $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblKeywords WHERE category = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblKeywordCategories WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; return true; } } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassNotification.php000066400000000000000000000030311205716546300255140ustar00rootroot00000000000000 * @copyright Copyright (C) 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a notification * * @category DMS * @package LetoDMS_Core * @author Uwe Steinmann * @copyright Copyright (C) 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_Notification { /* {{{ */ /** * @var integer id of target (document or folder) * * @access protected */ var $_target; /** * @var integer document or folder * * @access protected */ var $_targettype; /** * @var integer id of user to notify * * @access protected */ var $_userid; /** * @var integer id of group to notify * * @access protected */ var $_groupid; /** * @var object reference to the dms instance this user belongs to * * @access protected */ var $_dms; function LetoDMS_Core_Notification($target, $targettype, $userid, $groupid) { $this->_target = $target; $this->_targettype = $targettype; $this->_userid = $userid; $this->_groupid = $groupid; } function setDMS($dms) { $this->_dms = $dms; } function getTarget() { return $this->_target; } function getTargetType() { return $this->_targettype; } function getUser() { return $this->_dms->getUser($this->_userid); } function getGroup() { return $this->_dms->getGroup($this->_groupid); } } /* }}} */ ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.ClassUser.php000066400000000000000000000660211205716546300240140ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a user in the document management system * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_User { /** * @var integer id of user * * @access protected */ var $_id; /** * @var string login name of user * * @access protected */ var $_login; /** * @var string password of user as saved in database (md5) * * @access protected */ var $_pwd; /** * @var string full human readable name of user * * @access protected */ var $_fullName; /** * @var string email address of user * * @access protected */ var $_email; /** * @var string prefered language of user * possible values are 'English', 'German', 'Chinese_ZH_TW', 'Czech' * 'Francais', 'Hungarian', 'Italian', 'Portuguese_BR', 'Slovak', * 'Spanish' * * @access protected */ var $_language; /** * @var string preselected theme of user * * @access protected */ var $_theme; /** * @var string comment of user * * @access protected */ var $_comment; /** * @var string role of user. Can be one of LetoDMS_Core_User::role_user, * LetoDMS_Core_User::role_admin, LetoDMS_Core_User::role_guest * * @access protected */ var $_role; /** * @var string true if user shall be hidden * * @access protected */ var $_isHidden; /** * @var object reference to the dms instance this user belongs to * * @access protected */ var $_dms; const role_user = '0'; const role_admin = '1'; const role_guest = '2'; function LetoDMS_Core_User($id, $login, $pwd, $fullName, $email, $language, $theme, $comment, $role, $isHidden=0) { $this->_id = $id; $this->_login = $login; $this->_pwd = $pwd; $this->_fullName = $fullName; $this->_email = $email; $this->_language = $language; $this->_theme = $theme; $this->_comment = $comment; $this->_role = $role; $this->_isHidden = $isHidden; $this->_dms = null; } function setDMS($dms) { $this->_dms = $dms; } function getID() { return $this->_id; } function getLogin() { return $this->_login; } function setLogin($newLogin) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET login =".$db->qstr($newLogin)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_login = $newLogin; return true; } /* }}} */ function getFullName() { return $this->_fullName; } function setFullName($newFullName) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET fullname = ".$db->qstr($newFullName)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_fullName = $newFullName; return true; } /* }}} */ function getPwd() { return $this->_pwd; } function setPwd($newPwd) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET pwd =".$db->qstr($newPwd)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_pwd = $newPwd; return true; } /* }}} */ function getEmail() { return $this->_email; } function setEmail($newEmail) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET email =".$db->qstr($newEmail)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_email = $newEmail; return true; } /* }}} */ function getLanguage() { return $this->_language; } function setLanguage($newLanguage) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET language =".$db->qstr($newLanguage)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_language = $newLanguage; return true; } /* }}} */ function getTheme() { return $this->_theme; } function setTheme($newTheme) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET theme =".$db->qstr($newTheme)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_theme = $newTheme; return true; } /* }}} */ function getComment() { return $this->_comment; } function setComment($newComment) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET comment =".$db->qstr($newComment)." WHERE id = " . $this->_id; $res = $db->getResult($queryStr); if (!$res) return false; $this->_comment = $newComment; return true; } /* }}} */ function getRole() { return $this->_role; } function setRole($newrole) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET role = " . $newrole . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_role = $newrole; return true; } /* }}} */ function isAdmin() { return ($this->_role == LetoDMS_Core_User::role_admin); } function setAdmin($isAdmin) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET role = " . LetoDMS_Core_User::role_admin . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_role = LetoDMS_Core_User::role_admin; return true; } /* }}} */ function isGuest() { return ($this->_role == LetoDMS_Core_User::role_guest); } function setGuest($isGuest) { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "UPDATE tblUsers SET role = " . LetoDMS_Core_User::role_guest . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_role = LetoDMS_Core_User::role_guest; return true; } /* }}} */ function isHidden() { return $this->_isHidden; } function setHidden($isHidden) { /* {{{ */ $db = $this->_dms->getDB(); $isHidden = ($isHidden) ? "1" : "0"; $queryStr = "UPDATE tblUsers SET hidden = " . $isHidden . " WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; $this->_isHidden = $isHidden; return true; } /* }}} */ /** * Remove the user and also remove all its keywords, notifies, etc. * Do not remove folders and documents of the user, but assign them * to a different user. * * @param object $user the user doing the removal (needed for entry in * review log. * @param object $assignToUser the user who is new owner of folders and * documents which previously were owned by the delete user. * @return boolean true on success or false in case of an error */ function remove($user, $assignToUser=null) { /* {{{ */ $db = $this->_dms->getDB(); /* Records like folders and documents that formely have belonged to * the user will assign to another user. If no such user is set, * the function now returns false and will not use the admin user * anymore. */ if(!$assignToUser) return; $assignTo = $assignToUser->getID(); // delete private keyword lists $queryStr = "SELECT tblKeywords.id FROM tblKeywords, tblKeywordCategories WHERE tblKeywords.category = tblKeywordCategories.id AND tblKeywordCategories.owner = " . $this->_id; $resultArr = $db->getResultArray($queryStr); if (count($resultArr) > 0) { $queryStr = "DELETE FROM tblKeywords WHERE "; for ($i = 0; $i < count($resultArr); $i++) { $queryStr .= "id = " . $resultArr[$i]["id"]; if ($i + 1 < count($resultArr)) $queryStr .= " OR "; } if (!$db->getResult($queryStr)) return false; } $queryStr = "DELETE FROM tblKeywordCategories WHERE owner = " . $this->_id; if (!$db->getResult($queryStr)) return false; //Benachrichtigungen entfernen $queryStr = "DELETE FROM tblNotify WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; /* Assign documents of the removed user to the given user */ $queryStr = "UPDATE tblFolders SET owner = " . $assignTo . " WHERE owner = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "UPDATE tblDocuments SET owner = " . $assignTo . " WHERE owner = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "UPDATE tblDocumentContent SET createdBy = " . $assignTo . " WHERE createdBy = " . $this->_id; if (!$db->getResult($queryStr)) return false; // Remove private links on documents ... $queryStr = "DELETE FROM tblDocumentLinks WHERE userID = " . $this->_id . " AND public = 0"; if (!$db->getResult($queryStr)) return false; // ... but keep public links $queryStr = "UPDATE tblDocumentLinks SET userID = " . $assignTo . " WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // set administrator for deleted user's attachments $queryStr = "UPDATE tblDocumentFiles SET userID = " . $assignTo . " WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; //Evtl. von diesem Benutzer gelockte Dokumente werden freigegeben $queryStr = "DELETE FROM tblDocumentLocks WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // Delete user from all groups $queryStr = "DELETE FROM tblGroupMembers WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // User aus allen ACLs streichen $queryStr = "DELETE FROM tblACLs WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // Delete image of user $queryStr = "DELETE FROM tblUserImages WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // Delete user itself $queryStr = "DELETE FROM tblUsers WHERE id = " . $this->_id; if (!$db->getResult($queryStr)) return false; // mandatory review/approve $queryStr = "DELETE FROM tblMandatoryReviewers WHERE reviewerUserID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblMandatoryApprovers WHERE approverUserID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblMandatoryReviewers WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; $queryStr = "DELETE FROM tblMandatoryApprovers WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // set administrator for deleted user's events $queryStr = "UPDATE tblEvents SET userID = " . $assignTo . " WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; // TODO : update document status if reviewer/approver has been deleted // "DELETE FROM tblDocumentApproveLog WHERE userID = " . $this->_id; // "DELETE FROM tblDocumentReviewLog WHERE userID = " . $this->_id; $reviewStatus = $this->getReviewStatus(); foreach ($reviewStatus["indstatus"] as $ri) { $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $ri["reviewID"] ."', '-2', 'Reviewer removed from process', NOW(), '". $user->getID() ."')"; $res=$db->getResult($queryStr); } $approvalStatus = $this->getApprovalStatus(); foreach ($approvalStatus["indstatus"] as $ai) { $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ". "VALUES ('". $ai["approveID"] ."', '-2', 'Approver removed from process', NOW(), '". $user->getID() ."')"; $res=$db->getResult($queryStr); } // unset($this); return true; } /* }}} */ /** * Make the user a member of a group * This function uses {@link LetoDMS_Group::addUser} but checks before if * the user is already a member of the group. * * @param object $group group to be the member of * @return boolean true on success or false in case of an error or the user * is already a member of the group */ function joinGroup($group) { /* {{{ */ if ($group->isMember($this)) return false; if (!$group->addUser($this)) return false; unset($this->_groups); return true; } /* }}} */ /** * Removes the user from a group * This function uses {@link LetoDMS_Group::removeUser} but checks before if * the user is a member of the group at all. * * @param object $group group to leave * @return boolean true on success or false in case of an error or the user * is not a member of the group */ function leaveGroup($group) { /* {{{ */ if (!$group->isMember($this)) return false; if (!$group->removeUser($this)) return false; unset($this->_groups); return true; } /* }}} */ /** * Get all groups the user is a member of * * @return array list of groups */ function getGroups() { /* {{{ */ $db = $this->_dms->getDB(); if (!isset($this->_groups)) { $queryStr = "SELECT `tblGroups`.*, `tblGroupMembers`.`userID` FROM `tblGroups` ". "LEFT JOIN `tblGroupMembers` ON `tblGroups`.`id` = `tblGroupMembers`.`groupID` ". "WHERE `tblGroupMembers`.`userID`='". $this->_id ."'"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; $this->_groups = array(); foreach ($resArr as $row) { $group = new LetoDMS_Core_Group($row["id"], $row["name"], $row["comment"]); array_push($this->_groups, $group); } } return $this->_groups; } /* }}} */ /** * Checks if user is member of a given group * * @param object $group * @return boolean true if user is member of the given group otherwise false */ function isMemberOfGroup($group) { /* {{{ */ return $group->isMember($this); } /* }}} */ /** * Check if user has an image in its profile * * @return boolean true if user has a picture of itself */ function hasImage() { /* {{{ */ if (!isset($this->_hasImage)) { $db = $this->_dms->getDB(); $queryStr = "SELECT COUNT(*) AS num FROM tblUserImages WHERE userID = " . $this->_id; $resArr = $db->getResultArray($queryStr); if ($resArr === false) return false; if ($resArr[0]["num"] == 0) $this->_hasImage = false; else $this->_hasImage = true; } return $this->_hasImage; } /* }}} */ /** * Get the image from the users profile * * @return array image data */ function getImage() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblUserImages WHERE userID = " . $this->_id; $resArr = $db->getResultArray($queryStr); if ($resArr === false) return false; if($resArr) $resArr = $resArr[0]; return $resArr; } /* }}} */ function setImage($tmpfile, $mimeType) { /* {{{ */ $db = $this->_dms->getDB(); $fp = fopen($tmpfile, "rb"); if (!$fp) return false; $content = fread($fp, filesize($tmpfile)); fclose($fp); if ($this->hasImage()) $queryStr = "UPDATE tblUserImages SET image = '".base64_encode($content)."', mimeType = ".$db->qstr($mimeType)." WHERE userID = " . $this->_id; else $queryStr = "INSERT INTO tblUserImages (userID, image, mimeType) VALUES (" . $this->_id . ", '".base64_encode($content)."', ".$db->qstr($mimeType).")"; if (!$db->getResult($queryStr)) return false; $this->_hasImage = true; return true; } /* }}} */ /** * Get a list of reviews * This function returns a list of all reviews seperated by individual * and group reviews. If the document id * is passed, then only this document will be checked for approvals. The * same is true for the version of a document which limits the list * further. * * For a detaile description of the result array see * {link LetoDMS_User::getApprovalStatus} * * @param int $documentID optional document id for which to retrieve the * reviews * @param int $version optional version of the document * @return array list of all reviews */ function getReviewStatus($documentID=null, $version=null) { /* {{{ */ $db = $this->_dms->getDB(); /* if (!$db->createTemporaryTable("ttreviewid")) { return false; } */ $status = array("indstatus"=>array(), "grpstatus"=>array()); // See if the user is assigned as an individual reviewer. $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ". "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ". "`tblDocumentReviewLog`.`userID` ". "FROM `tblDocumentReviewers` ". "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ". "WHERE `tblDocumentReviewers`.`type`='0' ". ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' "). "AND `tblDocumentReviewers`.`required`='". $this->_id ."' ". "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC LIMIT 1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status["indstatus"][] = $res; } // See if the user is the member of a group that has been assigned to // review the document version. $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ". "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ". "`tblDocumentReviewLog`.`userID` ". "FROM `tblDocumentReviewers` ". "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ". "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentReviewers`.`required` ". "WHERE `tblDocumentReviewers`.`type`='1' ". ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' "). "AND `tblGroupMembers`.`userID`='". $this->_id ."' ". "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC LIMIT 1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status["grpstatus"][] = $res; } return $status; } /* }}} */ /** * Get a list of approvals * This function returns a list of all approvals seperated by individual * and group approvals. If the document id * is passed, then only this document will be checked for approvals. The * same is true for the version of a document which limits the list * further. * * The result array has two elements: * - indstatus: which contains the approvals by individuals (users) * - grpstatus: which contains the approvals by groups * * Each element is itself an array of approvals with the following elements: * - approveID: unique id of approval * - documentID: id of document, that needs to be approved * - version: version of document, that needs to be approved * - type: 0 for individual approval, 1 for group approval * - required: id of user who is required to do the approval * - status: 0 not approved, .... * - comment: comment given during approval * - date: date of approval * - userID: id of user who has done the approval * * @param int $documentID optional document id for which to retrieve the * approvals * @param int $version optional version of the document * @return array list of all approvals */ function getApprovalStatus($documentID=null, $version=null) { /* {{{ */ $db = $this->_dms->getDB(); /* if (!$db->createTemporaryTable("ttapproveid")) { return false; } */ $status = array("indstatus"=>array(), "grpstatus"=>array()); // See if the user is assigned as an individual approver. /* $queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ". "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". "`tblDocumentApproveLog`.`userID` ". "FROM `tblDocumentApprovers` ". "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ". "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ". ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". $documentID ."' "). ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". $version ."' "). "AND `tblDocumentApprovers`.`type`='0' ". "AND `tblDocumentApprovers`.`required`='". $this->_id ."' "; */ $queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ". "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". "`tblDocumentApproveLog`.`userID` ". "FROM `tblDocumentApprovers` ". "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". "WHERE `tblDocumentApprovers`.`type`='0' ". ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' "). "AND `tblDocumentApprovers`.`required`='". $this->_id ."' ". "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC LIMIT 1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status["indstatus"][] = $res; } // See if the user is the member of a group that has been assigned to // approve the document version. /* $queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ". "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". "`tblDocumentApproveLog`.`userID` ". "FROM `tblDocumentApprovers` ". "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ". "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ". "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ". ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". $documentID ."' "). ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". $version ."' "). "AND `tblDocumentApprovers`.`type`='1' ". "AND `tblGroupMembers`.`userID`='". $this->_id ."'"; */ $queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ". "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ". "`tblDocumentApproveLog`.`userID` ". "FROM `tblDocumentApprovers` ". "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ". "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ". "WHERE `tblDocumentApprovers`.`type`='1' ". ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' "). ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' "). "AND `tblGroupMembers`.`userID`='". $this->_id ."' ". "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC LIMIT 1"; $resArr = $db->getResultArray($queryStr); if (is_bool($resArr) && $resArr == false) return false; if (count($resArr)>0) { foreach ($resArr as $res) $status["grpstatus"][] = $res; } return $status; } /* }}} */ /** * Get a list of mandatory reviewers * A user which isn't trusted completely may have assigned mandatory * reviewers (both users and groups). * Whenever the user inserts a new document the mandatory reviewers are * filled in as reviewers. * * @return array list of arrays with two elements containing the user id * (reviewerUserID) and group id (reviewerGroupID) of the reviewer. */ function getMandatoryReviewers() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblMandatoryReviewers WHERE userID = " . $this->_id; $resArr = $db->getResultArray($queryStr); return $resArr; } /* }}} */ /** * Get a list of mandatory approvers * See {link LetoDMS_User::getMandatoryReviewers} * * @return array list of arrays with two elements containing the user id * (approverUserID) and group id (approverGroupID) of the approver. */ function getMandatoryApprovers() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "SELECT * FROM tblMandatoryApprovers WHERE userID = " . $this->_id; $resArr = $db->getResultArray($queryStr); return $resArr; } /* }}} */ /** * Set a mandatory reviewer * This function sets a mandatory reviewer if it isn't already set. * * @param integer $id id of reviewer * @param boolean $isgroup true if $id is a group * @return boolean true on success, otherwise false */ function setMandatoryReviewer($id, $isgroup=false) { /* {{{ */ $db = $this->_dms->getDB(); if ($isgroup){ $queryStr = "SELECT * FROM tblMandatoryReviewers WHERE userID = " . $this->_id . " AND reviewerGroupID = " . $id; $resArr = $db->getResultArray($queryStr); if (count($resArr)!=0) return true; $queryStr = "INSERT INTO tblMandatoryReviewers (userID, reviewerGroupID) VALUES (" . $this->_id . ", " . $id .")"; $resArr = $db->getResult($queryStr); if (is_bool($resArr) && !$resArr) return false; }else{ $queryStr = "SELECT * FROM tblMandatoryReviewers WHERE userID = " . $this->_id . " AND reviewerUserID = " . $id; $resArr = $db->getResultArray($queryStr); if (count($resArr)!=0) return true; $queryStr = "INSERT INTO tblMandatoryReviewers (userID, reviewerUserID) VALUES (" . $this->_id . ", " . $id .")"; $resArr = $db->getResult($queryStr); if (is_bool($resArr) && !$resArr) return false; } } /* }}} */ /** * Set a mandatory approver * This function sets a mandatory approver if it isn't already set. * * @param integer $id id of approver * @param boolean $isgroup true if $id is a group * @return boolean true on success, otherwise false */ function setMandatoryApprover($id, $isgroup=false) { /* {{{ */ $db = $this->_dms->getDB(); if ($isgroup){ $queryStr = "SELECT * FROM tblMandatoryApprovers WHERE userID = " . $this->_id . " AND approverGroupID = " . (int) $id; $resArr = $db->getResultArray($queryStr); if (count($resArr)!=0) return; $queryStr = "INSERT INTO tblMandatoryApprovers (userID, approverGroupID) VALUES (" . $this->_id . ", " . $id .")"; $resArr = $db->getResult($queryStr); if (is_bool($resArr) && !$resArr) return false; }else{ $queryStr = "SELECT * FROM tblMandatoryApprovers WHERE userID = " . $this->_id . " AND approverUserID = " . (int) $id; $resArr = $db->getResultArray($queryStr); if (count($resArr)!=0) return; $queryStr = "INSERT INTO tblMandatoryApprovers (userID, approverUserID) VALUES (" . $this->_id . ", " . $id .")"; $resArr = $db->getResult($queryStr); if (is_bool($resArr) && !$resArr) return false; } } /* }}} */ /** * Deletes all mandatory reviewers * * @return boolean true on success, otherwise false */ function delMandatoryReviewers() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblMandatoryReviewers WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; return true; } /* }}} */ /** * Deletes all mandatory approvers * * @return boolean true on success, otherwise false */ function delMandatoryApprovers() { /* {{{ */ $db = $this->_dms->getDB(); $queryStr = "DELETE FROM tblMandatoryApprovers WHERE userID = " . $this->_id; if (!$db->getResult($queryStr)) return false; return true; } /* }}} */ } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.DBAccess.php000066400000000000000000000203501205716546300235120ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, * 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Include the adodb database abstraction */ require_once "adodb/adodb.inc.php"; /** * Class to represent the database access for the document management * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_DatabaseAccess { var $_debug; var $_driver; var $_hostname; var $_database; var $_user; var $_passw; var $_conn; var $_connected; var $_ttreviewid; var $_ttapproveid; var $_ttstatid; var $_ttcontentid; /* Backup functions */ /** * Return list of all database tables * * This function is used to retrieve a list of database tables for backup * * @return array list of table names */ function TableList() { return $this->_conn->MetaTables("TABLES"); } /** * Constructor of LetoDMS_Core_DatabaseAccess * * Sets all database parameters but does not connect. * * @param string $driver the database type e.g. mysql, sqlite * @param string $hostname host of database server * @param string $user name of user having access to database * @param string $passw password of user * @param string $database name of database */ function LetoDMS_Core_DatabaseAccess($driver, $hostname, $user, $passw, $database = false) { $this->_driver = $driver; $this->_hostname = $hostname; $this->_database = $database; $this->_user = $user; $this->_passw = $passw; $this->_connected = false; // $tt*****id is a hack to ensure that we do not try to create the // temporary table twice during a single connection. Can be fixed by // using Views (MySQL 5.0 onward) instead of temporary tables. // CREATE ... IF NOT EXISTS cannot be used because it has the // unpleasant side-effect of performing the insert again even if the // table already exists. // // See createTemporaryTable() method for implementation. $this->_ttreviewid = false; $this->_ttapproveid = false; $this->_ttstatid = false; $this->_ttcontentid = false; $this->_debug = false; } /** * Connect to database * * @return boolean true if connection could be established, otherwise false */ function connect() { /* {{{ */ $this->_conn = ADONewConnection($this->_driver); if ($this->_database) $this->_conn->Connect($this->_hostname, $this->_user, $this->_passw, $this->_database); else $this->_conn->Connect($this->_hostname, $this->_user, $this->_passw); if (!$this->_conn) return false; $this->_conn->SetFetchMode(ADODB_FETCH_ASSOC); $this->_conn->Execute('SET NAMES utf8'); $this->_connected = true; return true; } /* }}} */ /** * Make sure a database connection exisits * * This function checks for a database connection. If it does not exists * it will reconnect. * * @return boolean true if connection is established, otherwise false */ function ensureConnected() { /* {{{ */ if (!$this->_connected) return $this->connect(); else return true; } /* }}} */ /** * Sanitize String used in database operations * * @param string text * @return string sanitized string */ function qstr($text) { /* {{{ */ return $this->_conn->qstr($text); } /* }}} */ /** * Execute SQL query and return result * * Call this function only with sql query which return data records. * * @param string $queryStr sql query * @return array/boolean data if query could be executed otherwise false */ function getResultArray($queryStr) { /* {{{ */ $resArr = array(); $res = $this->_conn->Execute($queryStr); if (!$res) { if($this->_debug) echo "error: ".$queryStr."
"; return false; } $resArr = $res->GetArray(); $res->Close(); return $resArr; } /* }}} */ /** * Execute SQL query * * Call this function only with sql query which do not return data records. * * @param string $queryStr sql query * @param boolean $silent not used anymore. This was used when this method * still issued an error message * @return boolean true if query could be executed otherwise false */ function getResult($queryStr, $silent=false) { /* {{{ */ $res = $this->_conn->Execute($queryStr); if(!$res) { if($this->_debug) echo "error: ".$queryStr."
"; } return $res; } /* }}} */ /** * Return the id of the last instert record * * @return integer id used in last autoincrement */ function getInsertID() { /* {{{ */ return $this->_conn->Insert_ID(); } /* }}} */ function getErrorMsg() { /* {{{ */ return $this->_conn->ErrorMsg(); } /* }}} */ function getErrorNo() { /* {{{ */ return $this->_conn->ErrorNo(); } /* }}} */ /** * Create various temporary tables to speed up and simplify sql queries */ function createTemporaryTable($tableName, $override=false) { /* {{{ */ if (!strcasecmp($tableName, "ttreviewid")) { $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ". "SELECT `tblDocumentReviewLog`.`reviewID`, ". "MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ". "FROM `tblDocumentReviewLog` ". "GROUP BY `tblDocumentReviewLog`.`reviewID` ". "ORDER BY `tblDocumentReviewLog`.`reviewLogID`"; if (!$this->_ttreviewid) { if (!$this->getResult($queryStr)) return false; $this->_ttreviewid=true; } else { if (is_bool($override) && $override) { if (!$this->getResult("DELETE FROM `ttreviewid`")) return false; if (!$this->getResult($queryStr)) return false; } } return $this->_ttreviewid; } else if (!strcasecmp($tableName, "ttapproveid")) { $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ". "SELECT `tblDocumentApproveLog`.`approveID`, ". "MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ". "FROM `tblDocumentApproveLog` ". "GROUP BY `tblDocumentApproveLog`.`approveID` ". "ORDER BY `tblDocumentApproveLog`.`approveLogID`"; if (!$this->_ttapproveid) { if (!$this->getResult($queryStr)) return false; $this->_ttapproveid=true; } else { if (is_bool($override) && $override) { if (!$this->getResult("DELETE FROM `ttapproveid`")) return false; if (!$this->getResult($queryStr)) return false; } } return $this->_ttapproveid; } else if (!strcasecmp($tableName, "ttstatid")) { $queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ". "SELECT `tblDocumentStatusLog`.`statusID`, ". "MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ". "FROM `tblDocumentStatusLog` ". "GROUP BY `tblDocumentStatusLog`.`statusID` ". "ORDER BY `tblDocumentStatusLog`.`statusLogID`"; if (!$this->_ttstatid) { if (!$this->getResult($queryStr)) return false; $this->_ttstatid=true; } else { if (is_bool($override) && $override) { if (!$this->getResult("DELETE FROM `ttstatid`")) return false; if (!$this->getResult($queryStr)) return false; } } return $this->_ttstatid; } else if (!strcasecmp($tableName, "ttcontentid")) { $queryStr = "CREATE TEMPORARY TABLE `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ". "SELECT `tblDocumentContent`.`document`, ". "MAX(`tblDocumentContent`.`version`) AS `maxVersion` ". "FROM `tblDocumentContent` ". "GROUP BY `tblDocumentContent`.`document` ". "ORDER BY `tblDocumentContent`.`document`"; if (!$this->_ttcontentid) { if (!$this->getResult($queryStr)) return false; $this->_ttcontentid=true; } else { if (is_bool($override) && $override) { if (!$this->getResult("DELETE FROM `ttcontentid`")) return false; if (!$this->getResult($queryStr)) return false; } } return $this->_ttcontentid; } return false; } /* }}} */ } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/Core/inc.FileUtils.php000066400000000000000000000074001205716546300240040ustar00rootroot00000000000000 * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ /** * Class to represent a user in the document management system * * @category DMS * @package LetoDMS_Core * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann * @copyright Copyright (C) 2002-2005 Markus Westphal, * 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, * 2010 Uwe Steinmann * @version Release: 3.3.11 */ class LetoDMS_Core_File { function renameFile($old, $new) { return @rename($old, $new); } function removeFile($file) { return @unlink($file); } function copyFile($source, $target) { return @copy($source, $target); } function moveFile($source, $target) { if (!@copyFile($source, $target)) return false; return @removeFile($source); } function renameDir($old, $new) { return @rename($old, $new); } function makeDir($path) { if( !is_dir( $path ) ){ $res=@mkdir( $path , 0777, true); if (!$res) return false; } return true; /* some old code if (strncmp($path, DIRECTORY_SEPARATOR, 1) == 0) { $mkfolder = DIRECTORY_SEPARATOR; } else { $mkfolder = ""; } $path = preg_split( "/[\\\\\/]/" , $path ); for( $i=0 ; isset( $path[$i] ) ; $i++ ) { if(!strlen(trim($path[$i])))continue; $mkfolder .= $path[$i]; if( !is_dir( $mkfolder ) ){ $res=@mkdir( "$mkfolder" , 0777); if (!$res) return false; } $mkfolder .= DIRECTORY_SEPARATOR; } return true; // patch from alekseynfor safe_mod or open_basedir global $settings; $path = substr_replace ($path, "/", 0, strlen($settings->_contentDir)); $mkfolder = $settings->_contentDir; $path = preg_split( "/[\\\\\/]/" , $path ); for( $i=0 ; isset( $path[$i] ) ; $i++ ) { if(!strlen(trim($path[$i])))continue; $mkfolder .= $path[$i]; if( !is_dir( $mkfolder ) ){ $res= @mkdir( "$mkfolder" , 0777); if (!$res) return false; } $mkfolder .= DIRECTORY_SEPARATOR; } return true; */ } function removeDir($path) { $handle = @opendir($path); while ($entry = @readdir($handle) ) { if ($entry == ".." || $entry == ".") continue; else if (is_dir($path . $entry)) { if (!self::removeDir($path . $entry . "/")) return false; } else { if (!@unlink($path . $entry)) return false; } } @closedir($handle); return @rmdir($path); } function copyDir($sourcePath, $targetPath) { if (mkdir($targetPath, 0777)) { $handle = @opendir($sourcePath); while ($entry = @readdir($handle) ) { if ($entry == ".." || $entry == ".") continue; else if (is_dir($sourcePath . $entry)) { if (!self::copyDir($sourcePath . $entry . "/", $targetPath . $entry . "/")) return false; } else { if (!@copy($sourcePath . $entry, $targetPath . $entry)) return false; } } @closedir($handle); } else return false; return true; } function moveDir($sourcePath, $targetPath) { if (!copyDir($sourcePath, $targetPath)) return false; return removeDir($sourcePath); } // code by Kioob (php.net manual) function gzcompressfile($source,$level=false) { $dest=$source.'.gz'; $mode='wb'.$level; $error=false; if($fp_out=@gzopen($dest,$mode)) { if($fp_in=@fopen($source,'rb')) { while(!feof($fp_in)) @gzwrite($fp_out,fread($fp_in,1024*512)); @fclose($fp_in); } else $error=true; @gzclose($fp_out); } else $error=true; if($error) return false; else return $dest; } } ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/tests/000077500000000000000000000000001205716546300210745ustar00rootroot00000000000000php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/tests/getfoldertree.php000066400000000000000000000013751205716546300244460ustar00rootroot00000000000000connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\""); $dms = new LetoDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']); function tree($folder, $indent='') { echo $indent."D ".$folder->getName()."\n"; $subfolders = $folder->getSubFolders(); foreach($subfolders as $subfolder) { tree($subfolder, $indent.' '); } $documents = $folder->getDocuments(); foreach($documents as $document) { echo $indent." ".$document->getName()."\n"; } } $folder = $dms->getFolder(1); tree($folder); ?> php-letodms-core-3.3.11/LetoDMS_Core-3.3.11/tests/getusers.php000066400000000000000000000010141205716546300234420ustar00rootroot00000000000000connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\""); $dms = new LetoDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']); $users = $dms->getAllUsers(); foreach($users as $user) echo $user->getId()." ".$user->getLogin()." ".$user->getFullname()."\n"; ?> php-letodms-core-3.3.11/package.xml000066400000000000000000000230361205716546300171130ustar00rootroot00000000000000 LetoDMS_Core pear.php.net Document management system LetoDMS is a web based document management system (DMS). This is the core of it, providing the basic functionality to create/update and delete folders and documents. It also contains a user and group managment Uwe Steinmann steinm uwe@steinmann.cx yes Matteo Lucarelli matteo no 2012-11-30 3.3.11 3.3.11 stable stable GPL License - fixed bug when adding a new document category 4.3.0 1.5.4 3.0.0 3.0.0 stable stable 2010-04-27 GPL License Initial release 3.2.0 3.2.0 stable stable 2011-07-23 GPL License New release 2012-02-08 3.3.0 3.3.0 beta stable GPL License - added methods to find and repair errors in document and folder records - removed sendmail parameter from some methods in LetoDMS_Core_Document - do not use some of the temporay tables anymore - SetFetchMode(ADODB_FETCH_ASSOC) in LetoDMS_Core_DatabaseAccess::connect() 2012-03-21 3.3.1 3.3.1 beta stable GPL License - new release 2012-03-22 3.3.2 3.3.2 beta stable GPL License - fixed bug in LetoDMS_Core_Document::getDir() 2012-03-28 3.3.3 3.3.3 beta stable GPL License - fixed bug in LetoDMS_Core_Document::getPath() 2012-04-11 3.3.4 3.3.4 beta stable GPL License - fixed bug in LetoDMS_Core_DocumentFile::getPath() 2012-04-30 3.3.5 3.3.5 beta stable GPL License - minor corrections 2012-07-16 3.3.6 3.3.6 beta stable GPL License - no changes, just keep same version as letodms application 2012-08-25 3.3.7 3.3.7 beta stable GPL License - no changes, just keep same version as letodms application 2012-09-16 3.3.8 3.3.8 beta stable GPL License - more sql injection protection in LetoDMS_Core_User 2012-09-19 3.3.9 3.3.9 beta stable GPL License - version update to be in sync with letodms application 2012-10-17 3.3.10 3.3.10 stable stable GPL License - fixed bug when adding a new document category