mirror of
https://git.code.sf.net/p/seeddms/code
synced 2025-02-06 15:14:58 +00:00
2659 lines
94 KiB
PHP
2659 lines
94 KiB
PHP
<?php
|
||
/**
|
||
* Implementation of the document management system
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @license GPL 2
|
||
* @version @version@
|
||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
|
||
/**
|
||
* Include some files
|
||
*/
|
||
require_once("inc.AccessUtils.php");
|
||
require_once("inc.FileUtils.php");
|
||
require_once("inc.ClassAccess.php");
|
||
require_once("inc.ClassObject.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");
|
||
require_once("inc.ClassAttribute.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 SeedDMS_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 SeedDMS_Core_Folder::getAccessMode()} and
|
||
* {@link SeedDMS_Core_Document::getAccessMode()} and interpret them as desired.
|
||
* Though, there are two convenient functions to filter a list of
|
||
* documents/folders for which users have access rights for. See
|
||
* {@link filterAccess()}
|
||
* and {@link filterUsersByAccess()}
|
||
*
|
||
* Though, this class has a method to set the currently logged in user
|
||
* ({@link setUser}), it does not have to be called, because
|
||
* there is currently no class within the SeedDMS core which needs the logged
|
||
* in user. {@link SeedDMS_Core_DMS} itself does not do any user authentication.
|
||
* It is up to the application using this class.
|
||
*
|
||
* <code>
|
||
* <?php
|
||
* include("inc/inc.ClassDMS.php");
|
||
* $db = new SeedDMS_Core_DatabaseAccess($type, $hostname, $user, $passwd, $name);
|
||
* $db->connect() or die ("Could not connect to db-server");
|
||
* $dms = new SeedDMS_Core_DMS($db, $contentDir);
|
||
* $dms->setRootFolderID(1);
|
||
* ...
|
||
* ?>
|
||
* </code>
|
||
*
|
||
* @category DMS
|
||
* @package SeedDMS_Core
|
||
* @version @version@
|
||
* @author Uwe Steinmann <uwe@steinmann.cx>
|
||
* @copyright Copyright (C) 2010, Uwe Steinmann
|
||
* @version Release: @package_version@
|
||
*/
|
||
class SeedDMS_Core_DMS {
|
||
/**
|
||
* @var object $db reference to database object. This must be an instance
|
||
* of {@link SeedDMS_Core_DatabaseAccess}.
|
||
* @access protected
|
||
*/
|
||
protected $db;
|
||
|
||
/**
|
||
* @var array $classnames list of classnames for objects being instanciate
|
||
* by the dms
|
||
* @access protected
|
||
*/
|
||
protected $classnames;
|
||
|
||
/**
|
||
* @var object $user reference to currently logged in user. This must be
|
||
* an instance of {@link SeedDMS_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 integer $maxDirID maximum number of documents per folder on the
|
||
* filesystem. If this variable is set to a value != 0, the content
|
||
* directory will have a two level hierarchy for document storage.
|
||
* @access public
|
||
*/
|
||
public $maxDirID;
|
||
|
||
/**
|
||
* @var boolean $enableConverting set to true if conversion of content
|
||
* is desired
|
||
* @access public
|
||
*/
|
||
public $enableConverting;
|
||
|
||
/**
|
||
* @var boolean $forceRename use renameFile() instead of copyFile() when
|
||
* copying the document content into the data store. The default is
|
||
* to copy the file. This parameter only affects the methods
|
||
* SeedDMS_Core_Document::addDocument() and
|
||
* SeedDMS_Core_Document::addDocumentFile(). Setting this to true
|
||
* may save resources especially for large files.
|
||
* @access public
|
||
*/
|
||
public $forceRename;
|
||
|
||
/**
|
||
* @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;
|
||
|
||
/**
|
||
* @var array $callbacks list of methods called when certain operations,
|
||
* like removing a document, are executed. Set a callback with
|
||
* {@link SeedDMS_Core_DMS::setCallback()}.
|
||
* The key of the array is the internal callback function name. Each
|
||
* array element is an array with two elements: the function name
|
||
* and the parameter passed to the function.
|
||
*
|
||
* Currently implemented callbacks are:
|
||
*
|
||
* onPreRemoveDocument($user_param, $document);
|
||
* called before deleting a document. If this function returns false
|
||
* the document will not be deleted.
|
||
*
|
||
* onPostRemoveDocument($user_param, $document_id);
|
||
* called after the successful deletion of a document.
|
||
*
|
||
* @access public
|
||
*/
|
||
public $callbacks;
|
||
|
||
|
||
/**
|
||
* Checks if two objects are equal by comparing their IDs
|
||
*
|
||
* The regular php check done by '==' compares all attributes of
|
||
* two objects, which is often not required. The method will first check
|
||
* if the objects are instances of the same class and than if they
|
||
* have the same id.
|
||
*
|
||
* @param object $object1 first object to be compared
|
||
* @param object $object2 second object to be compared
|
||
* @return boolean true if objects are equal, otherwise false
|
||
*/
|
||
static function checkIfEqual($object1, $object2) { /* {{{ */
|
||
if(get_class($object1) != get_class($object2))
|
||
return false;
|
||
if($object1->getID() != $object2->getID())
|
||
return false;
|
||
return true;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Checks if a list of objects contains a single object by comparing their IDs
|
||
*
|
||
* This function is only applicable on list containing objects which have
|
||
* a method getID() because it is used to check if two objects are equal.
|
||
* The regular php check on objects done by '==' compares all attributes of
|
||
* two objects, which isn't required. The method will first check
|
||
* if the objects are instances of the same class.
|
||
*
|
||
* The result of the function can be 0 which happens if the first element
|
||
* of an indexed array matches.
|
||
*
|
||
* @param object $object1 object to look for (needle)
|
||
* @param array $list list of objects (haystack)
|
||
* @return boolean/integer index in array if object was found, otherwise false
|
||
*/
|
||
static function inList($object, $list) { /* {{{ */
|
||
foreach($list as $i=>$item) {
|
||
if(get_class($item) == get_class($object) && $item->getID() == $object->getID())
|
||
return $i;
|
||
}
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Checks if date conforms to a given format
|
||
*
|
||
* @param string $date date to be checked
|
||
* @param string $format format of date. Will default to 'Y-m-d H:i:s' if
|
||
* format is not given.
|
||
* @return boolean true if date is in propper format, otherwise false
|
||
*/
|
||
static function checkDate($date, $format='Y-m-d H:i:s') { /* {{{ */
|
||
$d = DateTime::createFromFormat($format, $date);
|
||
return $d && $d->format($format) == $date;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Filter out objects which are not accessible in a given mode by a user.
|
||
*
|
||
* The list of objects to be checked can be of any class, but has to have
|
||
* a method getAccessMode($user) which checks if the given user has at
|
||
* least access rights to the object as passed in $minMode.
|
||
*
|
||
* @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 (M_ANY, M_NONE,
|
||
* M_READ, M_READWRITE, M_ALL)
|
||
* @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 out users which cannot access an object in a given mode.
|
||
*
|
||
* The list of users to be checked can be of any class, but has to have
|
||
* a method getAccessMode($user) which checks if a user has at least
|
||
* access rights as passed in $minMode.
|
||
*
|
||
* @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
|
||
* (M_ANY, M_NONE, M_READ, M_READWRITE, M_ALL)
|
||
* @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;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Filter out document links which can not be accessed by a given user
|
||
*
|
||
* Returns a filtered list of links which are accessible by the
|
||
* given user. A link is only accessible, if it is publically visible,
|
||
* owned by the user, or the accessing user is an administrator.
|
||
*
|
||
* @param array $links list of objects of type SeedDMS_Core_DocumentLink
|
||
* @param object $user user for which access is being checked
|
||
* @param string $access set if source or target of link shall be checked
|
||
* for sufficient access rights. Set to 'source' if the source document
|
||
* of a link is to be checked, set to 'target' for the target document.
|
||
* If not set, then access right aren't checked at all.
|
||
* @return array filtered list of links
|
||
*/
|
||
static function filterDocumentLinks($user, $links, $access='') { /* {{{ */
|
||
$tmp = array();
|
||
foreach ($links as $link) {
|
||
if ($link->isPublic() || ($link->getUser()->getID() == $user->getID()) || $user->isAdmin()){
|
||
if($access == 'source') {
|
||
$obj = $link->getDocument();
|
||
if ($obj->getAccessMode($user) >= M_READ)
|
||
array_push($tmp, $link);
|
||
} elseif($access == 'target') {
|
||
$obj = $link->getTarget();
|
||
if ($obj->getAccessMode($user) >= M_READ)
|
||
array_push($tmp, $link);
|
||
} else {
|
||
array_push($tmp, $link);
|
||
}
|
||
}
|
||
}
|
||
return $tmp;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Filter out document attachments which can not be accessed by a given user
|
||
*
|
||
* Returns a filtered list of files which are accessible by the
|
||
* given user. A file is only accessible, if it is publically visible,
|
||
* owned by the user, or the accessing user is an administrator.
|
||
*
|
||
* @param array $files list of objects of type SeedDMS_Core_DocumentFile
|
||
* @param object $user user for which access is being checked
|
||
* @return array filtered list of files
|
||
*/
|
||
static function filterDocumentFiles($user, $files) { /* {{{ */
|
||
$tmp = array();
|
||
foreach ($files as $file)
|
||
if ($file->isPublic() || ($file->getUser()->getID() == $user->getID()) || $user->isAdmin() || ($file->getDocument()->getOwner()->getID() == $user->getID()))
|
||
array_push($tmp, $file);
|
||
return $tmp;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Create a new instance of the dms
|
||
*
|
||
* @param object $db object of class {@link SeedDMS_Core_DatabaseAccess}
|
||
* to access the underlying database
|
||
* @param string $contentDir path in filesystem containing the data store
|
||
* all document contents is stored
|
||
* @return object instance of {@link SeedDMS_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->forceRename = false;
|
||
$this->enableConverting = false;
|
||
$this->convertFileTypes = array();
|
||
$this->classnames = array();
|
||
$this->classnames['folder'] = 'SeedDMS_Core_Folder';
|
||
$this->classnames['document'] = 'SeedDMS_Core_Document';
|
||
$this->classnames['documentcontent'] = 'SeedDMS_Core_DocumentContent';
|
||
$this->classnames['user'] = 'SeedDMS_Core_User';
|
||
$this->classnames['group'] = 'SeedDMS_Core_Group';
|
||
$this->callbacks = array();
|
||
$this->version = '@package_version@';
|
||
if($this->version[0] == '@')
|
||
$this->version = '5.1.2';
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return class name of instantiated objects
|
||
*
|
||
* This method returns the class name of those objects being instatiated
|
||
* by the dms. Each class has an internal place holder, which must be
|
||
* passed to function.
|
||
*
|
||
* @param string placeholder (can be one of 'folder', 'document',
|
||
* 'documentcontent', 'user', 'group'
|
||
*
|
||
* @return string/boolean name of class or false if placeholder is invalid
|
||
*/
|
||
function getClassname($objectname) { /* {{{ */
|
||
if(isset($this->classnames[$objectname]))
|
||
return $this->classnames[$objectname];
|
||
else
|
||
return false;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set class name of instantiated objects
|
||
*
|
||
* This method sets the class name of those objects being instatiated
|
||
* by the dms. It is mainly used to create a new class (possible
|
||
* inherited from one of the available classes) implementing new
|
||
* features. The method should be called in the postInitDMS hook.
|
||
*
|
||
* @param string placeholder (can be one of 'folder', 'document',
|
||
* 'documentcontent', 'user', 'group'
|
||
* @param string name of class
|
||
*
|
||
* @return string/boolean name of old class or false if not set
|
||
*/
|
||
function setClassname($objectname, $classname) { /* {{{ */
|
||
if(isset($this->classnames[$objectname]))
|
||
$oldclass = $this->classnames[$objectname];
|
||
else
|
||
$oldclass = false;
|
||
$this->classnames[$objectname] = $classname;
|
||
return $oldclass;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return database where meta data is stored
|
||
*
|
||
* This method returns the database object as it was set by the first
|
||
* parameter of the constructor.
|
||
*
|
||
* @return object database
|
||
*/
|
||
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
|
||
* {@link SeedDMS_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 each document is
|
||
* stored within a directory in the filesystem. Consequently, there can be
|
||
* a maximum number of documents, because depending on the file system
|
||
* the maximum number of subdirectories is limited. Since version 3.3.0 of
|
||
* SeedDMS an additional directory level has been introduced, which
|
||
* will be created when maxDirID is not 0. All documents
|
||
* from 1 to maxDirID-1 will be saved in 1/<docid>, documents from maxDirID
|
||
* to 2*maxDirID-1 are stored in 2/<docid> and so on.
|
||
*
|
||
* Modern file systems like ext4 do not have any restrictions on the number
|
||
* of subdirectories anymore. Therefore it is best if this parameter is
|
||
* set to 0. Never change this parameter if documents has already been
|
||
* created.
|
||
*
|
||
* This function must be called right after creating an instance of
|
||
* {@link SeedDMS_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 setEnableConverting($enable) { /* {{{ */
|
||
$this->enableConverting = $enable;
|
||
} /* }}} */
|
||
|
||
function setConvertFileTypes($types) { /* {{{ */
|
||
$this->convertFileTypes = $types;
|
||
} /* }}} */
|
||
|
||
function setViewOnlineFileTypes($types) { /* {{{ */
|
||
$this->viewOnlineFileTypes = $types;
|
||
} /* }}} */
|
||
|
||
function setForceRename($enable) { /* {{{ */
|
||
$this->forceRename = $enable;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 {@link SeedDMS_Core_Document} or false
|
||
*/
|
||
function getDocument($id) { /* {{{ */
|
||
$classname = $this->classnames['document'];
|
||
return $classname::getInstance($id, $this);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns all documents of a given user
|
||
*
|
||
* @param object $user
|
||
* @return array list of documents
|
||
*/
|
||
function getDocumentsByUser($user) { /* {{{ */
|
||
return $user->getDocuments();
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns all documents locked by a given user
|
||
*
|
||
* @param object $user
|
||
* @return array list of documents
|
||
*/
|
||
function getDocumentsLockedByUser($user) { /* {{{ */
|
||
return $user->getDocumentsLocked();
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 $this->classnames['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;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a document content by its id
|
||
*
|
||
* This function retrieves a document content from the database by its id.
|
||
*
|
||
* @param integer $id internal id of document content
|
||
* @return object instance of {@link SeedDMS_Core_DocumentContent} or false
|
||
*/
|
||
function getDocumentContent($id) { /* {{{ */
|
||
if (!is_numeric($id)) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `id` = ".(int) $id;
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
if (count($resArr) != 1)
|
||
return false;
|
||
$row = $resArr[0];
|
||
|
||
$document = $this->getDocument($row['document']);
|
||
$version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']);
|
||
return $version;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns all documents with a predefined search criteria
|
||
*
|
||
* The records return have the following elements
|
||
*
|
||
* From Table tblDocuments
|
||
* [id] => id of document
|
||
* [name] => name of document
|
||
* [comment] => comment of document
|
||
* [date] => timestamp of creation date of document
|
||
* [expires] => timestamp of expiration date of document
|
||
* [owner] => user id of owner
|
||
* [folder] => id of parent folder
|
||
* [folderList] => column separated list of folder ids, e.g. :1:41:
|
||
* [inheritAccess] => 1 if access is inherited
|
||
* [defaultAccess] => default access mode
|
||
* [locked] => always -1 (TODO: is this field still used?)
|
||
* [keywords] => keywords of document
|
||
* [sequence] => sequence of document
|
||
*
|
||
* From Table tblDocumentLocks
|
||
* [lockUser] => id of user locking the document
|
||
*
|
||
* From Table tblDocumentStatusLog
|
||
* [version] => latest version of document
|
||
* [statusID] => id of latest status log
|
||
* [documentID] => id of document
|
||
* [status] => current status of document
|
||
* [statusComment] => comment of current status
|
||
* [statusDate] => datetime when the status was entered, e.g. 2014-04-17 21:35:51
|
||
* [userID] => id of user who has initiated the status change
|
||
*
|
||
* From Table tblUsers
|
||
* [ownerName] => name of owner of document
|
||
* [statusName] => name of user who has initiated the status change
|
||
*
|
||
* @param string $listtype type of document list, can be 'AppRevByMe',
|
||
* 'AppRevOwner', 'ReceiptByMe', 'ReviseByMe', 'LockedByMe', 'MyDocs'
|
||
* @param object $param1 user
|
||
* @param string $param2 set to true
|
||
* if 'AppRevByMe', 'ReviseByMe', 'ReceiptByMe' shall return even documents
|
||
* І have already taken care of.
|
||
* @param string $param3 sort list by this field
|
||
* @param string $param4 order direction
|
||
* @return array list of documents records
|
||
*/
|
||
function getDocumentList($listtype, $param1=null, $param2=false, $param3='', $param4='') { /* {{{ */
|
||
/* The following query will get all documents and lots of additional
|
||
* information. It requires the two temporary tables ttcontentid and
|
||
* ttstatid.
|
||
*/
|
||
if (!$this->db->createTemporaryTable("ttstatid") || !$this->db->createTemporaryTable("ttcontentid")) {
|
||
return false;
|
||
}
|
||
/* The following statement retrieves the status of the last version of all
|
||
* documents. It must be restricted by further where clauses.
|
||
*/
|
||
$queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser`, ".
|
||
"`tblDocumentContent`.`version`, `tblDocumentStatus`.*, `tblDocumentStatusLog`.`status`, ".
|
||
"`tblDocumentStatusLog`.`comment` AS `statusComment`, `tblDocumentStatusLog`.`date` as `statusDate`, ".
|
||
"`tblDocumentStatusLog`.`userID`, `oTbl`.`fullName` AS `ownerName`, `sTbl`.`fullName` AS `statusName` ".
|
||
"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 `tblUsers` AS `oTbl` on `oTbl`.`id` = `tblDocuments`.`owner` ".
|
||
"LEFT JOIN `tblUsers` AS `sTbl` on `sTbl`.`id` = `tblDocumentStatusLog`.`userID` ".
|
||
"WHERE `ttstatid`.`maxLogID`=`tblDocumentStatusLog`.`statusLogID` ".
|
||
"AND `ttcontentid`.`maxVersion` = `tblDocumentContent`.`version` ";
|
||
|
||
switch($listtype) {
|
||
case 'AppRevByMe': // Documents I have to review/approve {{{
|
||
$user = $param1;
|
||
// Get document list for the current user.
|
||
$reviewStatus = $user->getReviewStatus();
|
||
$approvalStatus = $user->getApprovalStatus();
|
||
|
||
// Create a comma separated list of all the documentIDs whose information is
|
||
// required.
|
||
// Take only those documents into account which hasn't be touched by the user
|
||
$dList = array();
|
||
foreach ($reviewStatus["indstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
foreach ($reviewStatus["grpstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
foreach ($approvalStatus["indstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
foreach ($approvalStatus["grpstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
$docCSV = "";
|
||
foreach ($dList as $d) {
|
||
$docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'";
|
||
}
|
||
|
||
if (strlen($docCSV)>0) {
|
||
$queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_DRAFT_APP.", ".S_EXPIRED.") ".
|
||
"AND `tblDocuments`.`id` IN (" . $docCSV . ") ".
|
||
"ORDER BY `statusDate` DESC";
|
||
} else {
|
||
$queryStr = '';
|
||
}
|
||
break; // }}}
|
||
case 'ReviewByMe': // Documents I have to review {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
|
||
// Get document list for the current user.
|
||
$reviewStatus = $user->getReviewStatus();
|
||
|
||
// Create a comma separated list of all the documentIDs whose information is
|
||
// required.
|
||
// Take only those documents into account which hasn't be touched by the user
|
||
// ($st["status"]==0)
|
||
$dList = array();
|
||
foreach ($reviewStatus["indstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
foreach ($reviewStatus["grpstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
$docCSV = "";
|
||
foreach ($dList as $d) {
|
||
$docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'";
|
||
}
|
||
|
||
if (strlen($docCSV)>0) {
|
||
$queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_EXPIRED.") ".
|
||
"AND `tblDocuments`.`id` IN (" . $docCSV . ") ";
|
||
//$queryStr .= "ORDER BY `statusDate` DESC";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
} else {
|
||
$queryStr = '';
|
||
}
|
||
break; // }}}
|
||
case 'ApproveByMe': // Documents I have to approve {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
|
||
// Get document list for the current user.
|
||
$approvalStatus = $user->getApprovalStatus();
|
||
|
||
// Create a comma separated list of all the documentIDs whose information is
|
||
// required.
|
||
// Take only those documents into account which hasn't be touched by the user
|
||
// ($st["status"]==0)
|
||
$dList = array();
|
||
foreach ($approvalStatus["indstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
foreach ($approvalStatus["grpstatus"] as $st) {
|
||
if (($st["status"]==0 || $param2) && !in_array($st["documentID"], $dList)) {
|
||
$dList[] = $st["documentID"];
|
||
}
|
||
}
|
||
$docCSV = "";
|
||
foreach ($dList as $d) {
|
||
$docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'";
|
||
}
|
||
|
||
if (strlen($docCSV)>0) {
|
||
$queryStr .= "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_APP.", ".S_EXPIRED.") ".
|
||
"AND `tblDocuments`.`id` IN (" . $docCSV . ") ";
|
||
//$queryStr .= "ORDER BY `statusDate` DESC";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
} else {
|
||
$queryStr = '';
|
||
}
|
||
break; // }}}
|
||
case 'WorkflowByMe': // Documents I to trigger in Worklflow {{{
|
||
$user = $param1;
|
||
// Get document list for the current user.
|
||
$workflowStatus = $user->getWorkflowStatus();
|
||
|
||
// Create a comma separated list of all the documentIDs whose information is
|
||
// required.
|
||
$dList = array();
|
||
foreach ($workflowStatus["u"] as $st) {
|
||
if (!in_array($st["document"], $dList)) {
|
||
$dList[] = $st["document"];
|
||
}
|
||
}
|
||
foreach ($workflowStatus["g"] as $st) {
|
||
if (!in_array($st["document"], $dList)) {
|
||
$dList[] = $st["document"];
|
||
}
|
||
}
|
||
$docCSV = "";
|
||
foreach ($dList as $d) {
|
||
$docCSV .= (strlen($docCSV)==0 ? "" : ", ")."'".$d."'";
|
||
}
|
||
|
||
if (strlen($docCSV)>0) {
|
||
$queryStr .=
|
||
//"AND `tblDocumentStatusLog`.`status` IN (".S_IN_WORKFLOW.", ".S_EXPIRED.") ".
|
||
"AND `tblDocuments`.`id` IN (" . $docCSV . ") ".
|
||
"ORDER BY `statusDate` DESC";
|
||
} else {
|
||
$queryStr = '';
|
||
}
|
||
break; // }}}
|
||
case 'AppRevOwner': // Documents waiting for review/approval/revision I'm owning {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
$queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ".
|
||
"AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_DRAFT_APP.", ".S_IN_REVISION.") ";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
// $queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ".
|
||
// "AND `tblDocumentStatusLog`.`status` IN (".S_DRAFT_REV.", ".S_DRAFT_APP.") ".
|
||
// "ORDER BY `statusDate` DESC";
|
||
break; // }}}
|
||
case 'RejectOwner': // Documents that has been rejected and I'm owning {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
$queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ".
|
||
"AND `tblDocumentStatusLog`.`status` IN (".S_REJECTED.") ";
|
||
//$queryStr .= "ORDER BY `statusDate` DESC";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
break; // }}}
|
||
case 'LockedByMe': // Documents locked by me {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
|
||
$qs = 'SELECT `document` FROM `tblDocumentLocks` WHERE `userID`='.$user->getID();
|
||
$ra = $this->db->getResultArray($qs);
|
||
if (is_bool($ra) && !$ra) {
|
||
return false;
|
||
}
|
||
$docs = array();
|
||
foreach($ra as $d) {
|
||
$docs[] = $d['document'];
|
||
}
|
||
|
||
if ($docs) {
|
||
$queryStr .= "AND `tblDocuments`.`id` IN (" . implode(',', $docs) . ") ";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
} else {
|
||
$queryStr = '';
|
||
}
|
||
break; // }}}
|
||
case 'WorkflowOwner': // Documents waiting for workflow trigger I'm owning {{{
|
||
$user = $param1;
|
||
$queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ".
|
||
"AND `tblDocumentStatusLog`.`status` IN (".S_IN_WORKFLOW.") ".
|
||
"ORDER BY `statusDate` DESC";
|
||
break; // }}}
|
||
case 'MyDocs': // Documents owned by me {{{
|
||
$user = $param1;
|
||
$orderby = $param3;
|
||
if($param4 == 'desc')
|
||
$orderdir = 'DESC';
|
||
else
|
||
$orderdir = 'ASC';
|
||
$queryStr .= "AND `tblDocuments`.`owner` = '".$user->getID()."' ";
|
||
if ($orderby=='e') $queryStr .= "ORDER BY `expires`";
|
||
else if ($orderby=='u') $queryStr .= "ORDER BY `statusDate`";
|
||
else if ($orderby=='s') $queryStr .= "ORDER BY `status`";
|
||
else $queryStr .= "ORDER BY `name`";
|
||
$queryStr .= " ".$orderdir;
|
||
break; // }}}
|
||
}
|
||
|
||
if($queryStr) {
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr) {
|
||
return false;
|
||
}
|
||
/*
|
||
$documents = array();
|
||
foreach($resArr as $row)
|
||
$documents[] = $this->getDocument($row["id"]);
|
||
*/
|
||
} else {
|
||
return array();
|
||
}
|
||
|
||
return $resArr;
|
||
} /* }}} */
|
||
|
||
function makeTimeStamp($hour, $min, $sec, $year, $month, $day) { /* {{{ */
|
||
$thirtyone = array (1, 3, 5, 7, 8, 10, 12);
|
||
$thirty = array (4, 6, 9, 11);
|
||
|
||
// Very basic check that the terms are valid. Does not fail for illegal
|
||
// dates such as 31 Feb.
|
||
if (!is_numeric($hour) || !is_numeric($min) || !is_numeric($sec) || !is_numeric($year) || !is_numeric($month) || !is_numeric($day) || $month<1 || $month>12 || $day<1 || $day>31 || $hour<0 || $hour>23 || $min<0 || $min>59 || $sec<0 || $sec>59) {
|
||
return false;
|
||
}
|
||
$year = (int) $year;
|
||
$month = (int) $month;
|
||
$day = (int) $day;
|
||
|
||
if (array_search($month, $thirtyone)) {
|
||
$max=31;
|
||
}
|
||
else if (array_search($month, $thirty)) {
|
||
$max=30;
|
||
}
|
||
else {
|
||
$max=(($year % 4 == 0) && ($year % 100 != 0 || $year % 400 == 0)) ? 29 : 28;
|
||
}
|
||
|
||
// If the date falls out of bounds, set it to the maximum for the given
|
||
// month. Makes assumption about the user's intention, rather than failing
|
||
// for absolutely everything.
|
||
if ($day>$max) {
|
||
$day=$max;
|
||
}
|
||
|
||
return mktime($hour, $min, $sec, $month, $day, $year);
|
||
} /* }}} */
|
||
|
||
/*
|
||
* Search the database for documents
|
||
*
|
||
* Note: the creation date will be used to check againts the
|
||
* date saved with the document
|
||
* or folder. The modification date will only be used for documents. It
|
||
* is checked against the creation date of the document content. This
|
||
* meanѕ that updateѕ of a document will only result in a searchable
|
||
* modification if a new version is uploaded.
|
||
*
|
||
* @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, 4=attributes
|
||
* @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 modificationstartdate array search for documents modified after this date
|
||
* @param modificationenddate array search for documents modified before this date
|
||
* @param categories array list of categories the documents must have assigned
|
||
* @param attributes array list of attributes. The key of this array is the
|
||
* attribute definition id. The value of the array is the value of the
|
||
* attribute. If the attribute may have multiple values it must be an array.
|
||
* @param mode int decide whether to search for documents/folders
|
||
* 0x1 = documents only
|
||
* 0x2 = folders only
|
||
* 0x3 = both
|
||
* @param expirationstartdate array search for documents expiring after this date
|
||
* @param expirationenddate array search for documents expiring before this date
|
||
* @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(), $modificationstartdate=array(), $modificationenddate=array(), $categories=array(), $attributes=array(), $mode=0x3, $expirationstartdate=array(), $expirationenddate=array()) { /* {{{ */
|
||
// 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(1, 2, 3, 4, 5);
|
||
|
||
/*--------- Do it all over again for folders -------------*/
|
||
$totalFolders = 0;
|
||
if($mode & 0x2) {
|
||
$searchKey = "";
|
||
|
||
$classname = $this->classnames['folder'];
|
||
$searchFields = $classname::getSearchFields($this, $searchin);
|
||
|
||
if (count($searchFields)>0) {
|
||
foreach ($tkeys as $key) {
|
||
$key = trim($key);
|
||
if (strlen($key)>0) {
|
||
$searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ")."(".implode(" like ".$this->db->qstr("%".$key."%")." OR ", $searchFields)." 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) {
|
||
if(is_array($owner)) {
|
||
$ownerids = array();
|
||
foreach($owner as $o)
|
||
$ownerids[] = $o->getID();
|
||
if($ownerids)
|
||
$searchOwner = "`tblFolders`.`owner` IN (".implode(',', $ownerids).")";
|
||
} else {
|
||
$searchOwner = "`tblFolders`.`owner` = '".$owner->getId()."'";
|
||
}
|
||
}
|
||
|
||
// Check to see if the search has been restricted to a particular
|
||
// attribute.
|
||
$searchAttributes = array();
|
||
if ($attributes) {
|
||
foreach($attributes as $attrdefid=>$attribute) {
|
||
if($attribute) {
|
||
$attrdef = $this->getAttributeDefinition($attrdefid);
|
||
if($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_folder || $attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_all) {
|
||
if($valueset = $attrdef->getValueSet()) {
|
||
if($attrdef->getMultipleValues()) {
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND (`tblFolderAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblFolderAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)";
|
||
} else
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND `tblFolderAttributes`.`value`='".$attribute."' AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)";
|
||
} else
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblFolderAttributes` WHERE `tblFolderAttributes`.`attrdef`=".$attrdefid." AND `tblFolderAttributes`.`value` like '%".$attribute."%' AND `tblFolderAttributes`.`folder`=`tblFolders`.`id`)";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Is the search restricted to documents created between two specific dates?
|
||
$searchCreateDate = "";
|
||
if ($creationstartdate) {
|
||
$startdate = SeedDMS_Core_DMS::makeTimeStamp($creationstartdate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]);
|
||
if ($startdate) {
|
||
$searchCreateDate .= "`tblFolders`.`date` >= ".$startdate;
|
||
}
|
||
}
|
||
if ($creationenddate) {
|
||
$stopdate = SeedDMS_Core_DMS::makeTimeStamp($creationenddate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]);
|
||
if ($stopdate) {
|
||
if($startdate)
|
||
$searchCreateDate .= " AND ";
|
||
$searchCreateDate .= "`tblFolders`.`date` <= ".$stopdate;
|
||
}
|
||
}
|
||
|
||
$searchQuery = "FROM ".$classname::getSearchTables()." 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.")";
|
||
}
|
||
if ($searchAttributes) {
|
||
$searchQuery .= " AND (".implode(" AND ", $searchAttributes).")";
|
||
}
|
||
|
||
/* Do not search for folders if not at least a search for a key,
|
||
* an owner, or creation date is requested.
|
||
*/
|
||
if($searchKey || $searchOwner || $searchCreateDate || $searchAttributes) {
|
||
// Count the number of rows that the search will produce.
|
||
$resArr = $this->db->getResultArray("SELECT COUNT(*) AS num FROM (SELECT DISTINCT `tblFolders`.id ".$searchQuery.") a");
|
||
if ($resArr && isset($resArr[0]) && 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 DISTINCT `tblFolders`.`id` ".$searchQuery." GROUP BY `tblFolders`.`id`";
|
||
|
||
if($limit) {
|
||
$searchQuery .= " LIMIT ".$limit." OFFSET ".$offset;
|
||
}
|
||
|
||
// 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());
|
||
}
|
||
} else {
|
||
$folderresult = array('totalFolders'=>0, 'folders'=>array());
|
||
}
|
||
|
||
/*--------- Do it all over again for documents -------------*/
|
||
|
||
$totalDocs = 0;
|
||
if($mode & 0x1) {
|
||
$searchKey = "";
|
||
|
||
$classname = $this->classnames['document'];
|
||
$searchFields = $classname::getSearchFields($this, $searchin);
|
||
|
||
if (count($searchFields)>0) {
|
||
foreach ($tkeys as $key) {
|
||
$key = trim($key);
|
||
if (strlen($key)>0) {
|
||
$searchKey = (strlen($searchKey)==0 ? "" : $searchKey." ".$logicalmode." ")."(".implode(" like ".$this->db->qstr("%".$key."%")." OR ", $searchFields)." 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) {
|
||
if(is_array($owner)) {
|
||
$ownerids = array();
|
||
foreach($owner as $o)
|
||
$ownerids[] = $o->getID();
|
||
if($ownerids)
|
||
$searchOwner = "`tblDocuments`.`owner` IN (".implode(',', $ownerids).")";
|
||
} else {
|
||
$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).")";
|
||
}
|
||
|
||
// Check to see if the search has been restricted to a particular
|
||
// attribute.
|
||
$searchAttributes = array();
|
||
if ($attributes) {
|
||
foreach($attributes as $attrdefid=>$attribute) {
|
||
if($attribute) {
|
||
$attrdef = $this->getAttributeDefinition($attrdefid);
|
||
if($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_document || $attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_all) {
|
||
if($valueset = $attrdef->getValueSet()) {
|
||
if($attrdef->getMultipleValues()) {
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblDocumentAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)";
|
||
} else
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentAttributes`.`value`='".$attribute."' AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)";
|
||
} else
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentAttributes` WHERE `tblDocumentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentAttributes`.`value` like '%".$attribute."%' AND `tblDocumentAttributes`.`document` = `tblDocuments`.`id`)";
|
||
} elseif($attrdef->getObjType() == SeedDMS_Core_AttributeDefinition::objtype_documentcontent) {
|
||
if($attrdef->getValueSet()) {
|
||
if($attrdef->getMultipleValues()) {
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND (`tblDocumentContentAttributes`.`value` like '%".$valueset[0].implode("%' OR `tblDocumentContentAttributes`.`value` like '%".$valueset[0], $attribute)."%') AND `tblDocumentContentAttributes`.`document` = `tblDocumentContent`.`id`)";
|
||
} else {
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentContentAttributes`.`value`='".$attribute."' AND `tblDocumentContentAttributes`.content = `tblDocumentContent`.id)";
|
||
}
|
||
} else
|
||
$searchAttributes[] = "EXISTS (SELECT NULL FROM `tblDocumentContentAttributes` WHERE `tblDocumentContentAttributes`.`attrdef`=".$attrdefid." AND `tblDocumentContentAttributes`.`value` like '%".$attribute."%' AND `tblDocumentContentAttributes`.content = `tblDocumentContent`.id)";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Is the search restricted to documents created between two specific dates?
|
||
$searchCreateDate = "";
|
||
if ($creationstartdate) {
|
||
$startdate = SeedDMS_Core_DMS::makeTimeStamp($creationstartdate['hour'], $creationstartdate['minute'], $creationstartdate['second'], $creationstartdate['year'], $creationstartdate["month"], $creationstartdate["day"]);
|
||
if ($startdate) {
|
||
$searchCreateDate .= "`tblDocuments`.`date` >= ".$startdate;
|
||
}
|
||
}
|
||
if ($creationenddate) {
|
||
$stopdate = SeedDMS_Core_DMS::makeTimeStamp($creationenddate['hour'], $creationenddate['minute'], $creationenddate['second'], $creationenddate["year"], $creationenddate["month"], $creationenddate["day"]);
|
||
if ($stopdate) {
|
||
if($searchCreateDate)
|
||
$searchCreateDate .= " AND ";
|
||
$searchCreateDate .= "`tblDocuments`.`date` <= ".$stopdate;
|
||
}
|
||
}
|
||
if ($modificationstartdate) {
|
||
$startdate = SeedDMS_Core_DMS::makeTimeStamp($modificationstartdate['hour'], $modificationstartdate['minute'], $modificationstartdate['second'], $modificationstartdate['year'], $modificationstartdate["month"], $modificationstartdate["day"]);
|
||
if ($startdate) {
|
||
if($searchCreateDate)
|
||
$searchCreateDate .= " AND ";
|
||
$searchCreateDate .= "`tblDocumentContent`.`date` >= ".$startdate;
|
||
}
|
||
}
|
||
if ($modificationenddate) {
|
||
$stopdate = SeedDMS_Core_DMS::makeTimeStamp($modificationenddate['hour'], $modificationenddate['minute'], $modificationenddate['second'], $modificationenddate["year"], $modificationenddate["month"], $modificationenddate["day"]);
|
||
if ($stopdate) {
|
||
if($searchCreateDate)
|
||
$searchCreateDate .= " AND ";
|
||
$searchCreateDate .= "`tblDocumentContent`.`date` <= ".$stopdate;
|
||
}
|
||
}
|
||
$searchExpirationDate = '';
|
||
if ($expirationstartdate) {
|
||
$startdate = SeedDMS_Core_DMS::makeTimeStamp($expirationstartdate['hour'], $expirationstartdate['minute'], $expirationstartdate['second'], $expirationstartdate['year'], $expirationstartdate["month"], $expirationstartdate["day"]);
|
||
if ($startdate) {
|
||
if($searchExpirationDate)
|
||
$searchExpirationDate .= " AND ";
|
||
$searchExpirationDate .= "`tblDocuments`.`expires` >= ".$startdate;
|
||
}
|
||
}
|
||
if ($expirationenddate) {
|
||
$stopdate = SeedDMS_Core_DMS::makeTimeStamp($expirationenddate['hour'], $expirationenddate['minute'], $expirationenddate['second'], $expirationenddate["year"], $expirationenddate["month"], $expirationenddate["day"]);
|
||
if ($stopdate) {
|
||
if($searchExpirationDate)
|
||
$searchExpirationDate .= " AND ";
|
||
$searchExpirationDate .= "`tblDocuments`.`expires` <= ".$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 `tblDocumentAttributes` ON `tblDocuments`.`id` = `tblDocumentAttributes`.`document` ".
|
||
"LEFT JOIN `tblDocumentContentAttributes` ON `tblDocumentContent`.`id` = `tblDocumentContentAttributes`.`content` ".
|
||
"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.")";
|
||
}
|
||
if (strlen($searchExpirationDate)>0) {
|
||
$searchQuery .= " AND (".$searchExpirationDate.")";
|
||
}
|
||
if ($searchAttributes) {
|
||
$searchQuery .= " AND (".implode(" AND ", $searchAttributes).")";
|
||
}
|
||
|
||
// status
|
||
if ($status) {
|
||
$searchQuery .= " AND `tblDocumentStatusLog`.`status` IN (".implode(',', $status).")";
|
||
}
|
||
|
||
if($searchKey || $searchOwner || $searchCategories || $searchCreateDate || $searchExpirationDate || $searchAttributes || $status) {
|
||
// Count the number of rows that the search will produce.
|
||
$resArr = $this->db->getResultArray("SELECT COUNT(*) AS num FROM (SELECT DISTINCT `tblDocuments`.`id` ".$searchQuery.") a");
|
||
$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 DISTINCT `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
|
||
if($limit) {
|
||
$remain = $limit - count($folderresult['folders']);
|
||
if($remain) {
|
||
if($remain == $limit)
|
||
$offset -= $totalFolders;
|
||
else
|
||
$offset = 0;
|
||
if($limit)
|
||
$searchQuery .= " LIMIT ".$limit." OFFSET ".$offset;
|
||
|
||
// Send the complete search query to the database.
|
||
$resArr = $this->db->getResultArray($searchQuery);
|
||
} else {
|
||
$resArr = array();
|
||
}
|
||
} else {
|
||
// Send the complete search query to the database.
|
||
$resArr = $this->db->getResultArray($searchQuery);
|
||
}
|
||
|
||
// ------------------- 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());
|
||
}
|
||
} 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 SeedDMS_Core_Folder or false
|
||
*/
|
||
function getFolder($id) { /* {{{ */
|
||
$classname = $this->classnames['folder'];
|
||
return $classname::getInstance($id, $this);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 $this->classnames['folder']($resArr["id"], $resArr["name"], $resArr["parent"], $resArr["comment"], $resArr["date"], $resArr["owner"], $resArr["inheritAccess"], $resArr["defaultAccess"], $resArr["sequence"]);
|
||
$folder->setDMS($this);
|
||
return $folder;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of folders and error message not linked in the tree
|
||
*
|
||
* This function checks all folders in the database.
|
||
*
|
||
* @return array list of errors
|
||
*/
|
||
function checkFolders() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblFolders`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr === false)
|
||
return false;
|
||
|
||
$cache = array();
|
||
foreach($resArr as $rec) {
|
||
$cache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['parent'], 'folderList'=>$rec['folderList']);
|
||
}
|
||
$errors = array();
|
||
foreach($cache as $id=>$rec) {
|
||
if(!array_key_exists($rec['parent'], $cache) && $rec['parent'] != 0) {
|
||
$errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Missing parent');
|
||
} else {
|
||
$tmparr = explode(':', $rec['folderList']);
|
||
array_shift($tmparr);
|
||
if(count($tmparr) != count(array_unique($tmparr))) {
|
||
$errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Duplicate entry in folder list ('.$rec['folderList'].')');
|
||
}
|
||
}
|
||
}
|
||
|
||
return $errors;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns a list of documents and error message not linked in the tree
|
||
*
|
||
* This function checks all documents in the database.
|
||
*
|
||
* @return array list of errors
|
||
*/
|
||
function checkDocuments() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblFolders`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr === false)
|
||
return false;
|
||
|
||
$fcache = array();
|
||
foreach($resArr as $rec) {
|
||
$fcache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['parent'], 'folderList'=>$rec['folderList']);
|
||
}
|
||
|
||
$queryStr = "SELECT * FROM `tblDocuments`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr === false)
|
||
return false;
|
||
|
||
$dcache = array();
|
||
foreach($resArr as $rec) {
|
||
$dcache[$rec['id']] = array('name'=>$rec['name'], 'parent'=>$rec['folder'], 'folderList'=>$rec['folderList']);
|
||
}
|
||
$errors = array();
|
||
foreach($dcache as $id=>$rec) {
|
||
if(!array_key_exists($rec['parent'], $fcache) && $rec['parent'] != 0) {
|
||
$errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Missing parent');
|
||
} else {
|
||
$tmparr = explode(':', $rec['folderList']);
|
||
array_shift($tmparr);
|
||
if(count($tmparr) != count(array_unique($tmparr))) {
|
||
$errors[$id] = array('id'=>$id, 'name'=>$rec['name'], 'parent'=>$rec['parent'], 'msg'=>'Duplicate entry in folder list ('.$rec['folderList'].'');
|
||
}
|
||
}
|
||
}
|
||
|
||
return $errors;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 {@link SeedDMS_Core_User} or false
|
||
*/
|
||
function getUser($id) { /* {{{ */
|
||
$classname = $this->classnames['user'];
|
||
return $classname::getInstance($id, $this);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 {@link SeedDMS_Core_User} or false
|
||
*/
|
||
function getUserByLogin($login, $email='') { /* {{{ */
|
||
$classname = $this->classnames['user'];
|
||
return $classname::getInstance($login, $this, 'name', $email);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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 {@link SeedDMS_Core_User} or false
|
||
*/
|
||
function getUserByEmail($email) { /* {{{ */
|
||
$classname = $this->classnames['user'];
|
||
return $classname::getInstance($email, $this, 'email');
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return list of all users
|
||
*
|
||
* @return array of instances of {@link SeedDMS_Core_User} or false
|
||
*/
|
||
function getAllUsers($orderby = '') { /* {{{ */
|
||
$classname = $this->classnames['user'];
|
||
return $classname::getAllInstances($orderby, $this);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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
|
||
* @param integer $isDisabled disable user and prevent login
|
||
* @return object of {@link SeedDMS_Core_User}
|
||
*/
|
||
function addUser($login, $pwd, $fullName, $email, $language, $theme, $comment, $role='0', $isHidden=0, $isDisabled=0, $pwdexpiration='', $quota=0, $homefolder=null) { /* {{{ */
|
||
$db = $this->db;
|
||
if (is_object($this->getUserByLogin($login))) {
|
||
return false;
|
||
}
|
||
if($role == '')
|
||
$role = '0';
|
||
if(trim($pwdexpiration) == '' || trim($pwdexpiration) == 'never') {
|
||
$pwdexpiration = 'NULL';
|
||
} elseif(trim($pwdexpiration) == 'now') {
|
||
$pwdexpiration = $db->qstr(date('Y-m-d H:i:s'));
|
||
} else {
|
||
$pwdexpiration = $db->qstr($pwdexpiration);
|
||
}
|
||
$queryStr = "INSERT INTO `tblUsers` (`login`, `pwd`, `fullName`, `email`, `language`, `theme`, `comment`, `role`, `hidden`, `disabled`, `pwdExpiration`, `quota`, `homefolder`) VALUES (".$db->qstr($login).", ".$db->qstr($pwd).", ".$db->qstr($fullName).", ".$db->qstr($email).", '".$language."', '".$theme."', ".$db->qstr($comment).", '".intval($role)."', '".intval($isHidden)."', '".intval($isDisabled)."', ".$pwdexpiration.", '".intval($quota)."', ".($homefolder ? intval($homefolder) : "NULL").")";
|
||
$res = $this->db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
|
||
$user = $this->getUser($this->db->getInsertID('tblUsers'));
|
||
|
||
/* Check if 'onPostAddUser' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostAddUser'])) {
|
||
foreach($this->_dms->callbacks['onPostUser'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $user)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return $user;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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) { /* {{{ */
|
||
$classname = $this->classnames['group'];
|
||
return $classname::getInstance($id, $this, '');
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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) { /* {{{ */
|
||
$classname = $this->classnames['group'];
|
||
return $classname::getInstance($name, $this, 'name');
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get a list of all groups
|
||
*
|
||
* @return array array of instances of {@link SeedDMS_Core_Group}
|
||
*/
|
||
function getAllGroups() { /* {{{ */
|
||
$classname = $this->classnames['group'];
|
||
return $classname::getAllInstances('name', $this);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Create a new user group
|
||
*
|
||
* @param string $name name of group
|
||
* @param string $comment comment of group
|
||
* @return object/boolean instance of {@link SeedDMS_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;
|
||
|
||
$group = $this->getGroup($this->db->getInsertID('tblGroups'));
|
||
|
||
/* Check if 'onPostAddGroup' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostAddGroup'])) {
|
||
foreach($this->_dms->callbacks['onPostAddGroup'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $group)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return $group;
|
||
} /* }}} */
|
||
|
||
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 SeedDMS_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 SeedDMS_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 SeedDMS_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 SeedDMS_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;
|
||
|
||
$category = $this->getKeywordCategory($this->db->getInsertID('tblKeywordCategories'));
|
||
|
||
/* Check if 'onPostAddKeywordCategory' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostAddKeywordCategory'])) {
|
||
foreach($this->_dms->callbacks['onPostAddKeywordCategory'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $category)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return $category;
|
||
} /* }}} */
|
||
|
||
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 SeedDMS_Core_DocumentCategory($resArr["id"], $resArr["name"]);
|
||
$cat->setDMS($this);
|
||
return $cat;
|
||
} /* }}} */
|
||
|
||
function getDocumentCategories() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblCategory` order by `name`";
|
||
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (is_bool($resArr) && !$resArr)
|
||
return false;
|
||
|
||
$categories = array();
|
||
foreach ($resArr as $row) {
|
||
$cat = new SeedDMS_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 {@link SeedDMS_Core_DocumentCategory}
|
||
*/
|
||
function getDocumentCategoryByName($name) { /* {{{ */
|
||
if (!$name) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblCategory` where `name`=".$this->db->qstr($name);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
$row = $resArr[0];
|
||
$cat = new SeedDMS_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;
|
||
|
||
$category = $this->getDocumentCategory($this->db->getInsertID('tblCategory'));
|
||
|
||
/* Check if 'onPostAddDocumentCategory' callback is set */
|
||
if(isset($this->_dms->callbacks['onPostAddDocumentCategory'])) {
|
||
foreach($this->_dms->callbacks['onPostAddDocumentCategory'] as $callback) {
|
||
if(!call_user_func($callback[0], $callback[1], $category)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
return $category;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get all notifications for a group
|
||
*
|
||
* deprecated: User {@link SeedDMS_Core_Group::getNotifications()}
|
||
*
|
||
* @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) { /* {{{ */
|
||
return $group->getNotifications($type);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Get all notifications for a user
|
||
*
|
||
* deprecated: User {@link SeedDMS_Core_User::getNotifications()}
|
||
*
|
||
* @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) { /* {{{ */
|
||
return $user->getNotifications($type);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* 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) .", ".$this->db->getCurrentDatetime().")";
|
||
$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;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a attribute definition by its id
|
||
*
|
||
* This function retrieves a attribute definitionr from the database by
|
||
* its id.
|
||
*
|
||
* @param integer $id internal id of attribute defintion
|
||
* @return object instance of {@link SeedDMS_Core_AttributeDefinition} or false
|
||
*/
|
||
function getAttributeDefinition($id) { /* {{{ */
|
||
if (!is_numeric($id))
|
||
return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblAttributeDefinitions` 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];
|
||
|
||
$attrdef = new SeedDMS_Core_AttributeDefinition($resArr["id"], $resArr["name"], $resArr["objtype"], $resArr["type"], $resArr["multiple"], $resArr["minvalues"], $resArr["maxvalues"], $resArr["valueset"], $resArr["regex"]);
|
||
$attrdef->setDMS($this);
|
||
return $attrdef;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a attribute definition by its name
|
||
*
|
||
* This function retrieves an attribute def. from the database by its name.
|
||
*
|
||
* @param string $name internal name of attribute def.
|
||
* @return object instance of {@link SeedDMS_Core_AttributeDefinition} or false
|
||
*/
|
||
function getAttributeDefinitionByName($name) { /* {{{ */
|
||
if (!$name) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblAttributeDefinitions` WHERE `name` = " . $this->db->qstr($name);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false) return false;
|
||
if (count($resArr) != 1) return false;
|
||
|
||
$resArr = $resArr[0];
|
||
|
||
$attrdef = new SeedDMS_Core_AttributeDefinition($resArr["id"], $resArr["name"], $resArr["objtype"], $resArr["type"], $resArr["multiple"], $resArr["minvalues"], $resArr["maxvalues"], $resArr["valueset"], $resArr["regex"]);
|
||
$attrdef->setDMS($this);
|
||
return $attrdef;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return list of all attributes definitions
|
||
*
|
||
* @param integer $objtype select those attributes defined for an object type
|
||
* @return array of instances of {@link SeedDMS_Core_AttributeDefinition} or false
|
||
*/
|
||
function getAllAttributeDefinitions($objtype=0) { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblAttributeDefinitions`";
|
||
if($objtype) {
|
||
if(is_array($objtype))
|
||
$queryStr .= ' WHERE `objtype` in (\''.implode("','", $objtype).'\')';
|
||
else
|
||
$queryStr .= ' WHERE `objtype`='.intval($objtype);
|
||
}
|
||
$queryStr .= ' ORDER BY `name`';
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
$attrdefs = array();
|
||
|
||
for ($i = 0; $i < count($resArr); $i++) {
|
||
$attrdef = new SeedDMS_Core_AttributeDefinition($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["objtype"], $resArr[$i]["type"], $resArr[$i]["multiple"], $resArr[$i]["minvalues"], $resArr[$i]["maxvalues"], $resArr[$i]["valueset"], $resArr[$i]["regex"]);
|
||
$attrdef->setDMS($this);
|
||
$attrdefs[$i] = $attrdef;
|
||
}
|
||
|
||
return $attrdefs;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a new attribute definition
|
||
*
|
||
* @param string $name name of attribute
|
||
* @param string $type type of attribute
|
||
* @param boolean $multiple set to 1 if attribute has multiple attributes
|
||
* @param integer $minvalues minimum number of values
|
||
* @param integer $maxvalues maximum number of values if multiple is set
|
||
* @param string $valueset list of allowed values (csv format)
|
||
* @return object of {@link SeedDMS_Core_User}
|
||
*/
|
||
function addAttributeDefinition($name, $objtype, $type, $multiple=0, $minvalues=0, $maxvalues=1, $valueset='', $regex='') { /* {{{ */
|
||
if (is_object($this->getAttributeDefinitionByName($name))) {
|
||
return false;
|
||
}
|
||
if(!$type)
|
||
return false;
|
||
if(trim($valueset)) {
|
||
$valuesetarr = array_map('trim', explode($valueset[0], substr($valueset, 1)));
|
||
$valueset = $valueset[0].implode($valueset[0], $valuesetarr);
|
||
} else {
|
||
$valueset = '';
|
||
}
|
||
$queryStr = "INSERT INTO `tblAttributeDefinitions` (`name`, `objtype`, `type`, `multiple`, `minvalues`, `maxvalues`, `valueset`, `regex`) VALUES (".$this->db->qstr($name).", ".intval($objtype).", ".intval($type).", ".intval($multiple).", ".intval($minvalues).", ".intval($maxvalues).", ".$this->db->qstr($valueset).", ".$this->db->qstr($regex).")";
|
||
$res = $this->db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
|
||
return $this->getAttributeDefinition($this->db->getInsertID('tblAttributeDefinitions'));
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return list of all workflows
|
||
*
|
||
* @return array of instances of {@link SeedDMS_Core_Workflow} or false
|
||
*/
|
||
function getAllWorkflows() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblWorkflows` ORDER BY `name`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowStates` ORDER BY `name`";
|
||
$ressArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($ressArr) && $ressArr == false)
|
||
return false;
|
||
|
||
for ($i = 0; $i < count($ressArr); $i++) {
|
||
$wkfstates[$ressArr[$i]["id"]] = new SeedDMS_Core_Workflow_State($ressArr[$i]["id"], $ressArr[$i]["name"], $ressArr[$i]["maxtime"], $ressArr[$i]["precondfunc"], $ressArr[$i]["documentstatus"]);
|
||
}
|
||
|
||
$workflows = array();
|
||
for ($i = 0; $i < count($resArr); $i++) {
|
||
$workflow = new SeedDMS_Core_Workflow($resArr[$i]["id"], $resArr[$i]["name"], $wkfstates[$resArr[$i]["initstate"]]);
|
||
$workflow->setDMS($this);
|
||
$workflows[$i] = $workflow;
|
||
}
|
||
|
||
return $workflows;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return workflow by its Id
|
||
*
|
||
* @param integer $id internal id of workflow
|
||
* @return object of instances of {@link SeedDMS_Core_Workflow} or false
|
||
*/
|
||
function getWorkflow($id) { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblWorkflows` WHERE `id`=".intval($id);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
if(!$resArr)
|
||
return false;
|
||
|
||
$initstate = $this->getWorkflowState($resArr[0]['initstate']);
|
||
|
||
$workflow = new SeedDMS_Core_Workflow($resArr[0]["id"], $resArr[0]["name"], $initstate);
|
||
$workflow->setDMS($this);
|
||
|
||
return $workflow;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return workflow by its name
|
||
*
|
||
* @param string $name name of workflow
|
||
* @return object of instances of {@link SeedDMS_Core_Workflow} or false
|
||
*/
|
||
function getWorkflowByName($name) { /* {{{ */
|
||
if (!$name) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflows` WHERE `name`=".$this->db->qstr($name);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
if(!$resArr)
|
||
return false;
|
||
|
||
$initstate = $this->getWorkflowState($resArr[0]['initstate']);
|
||
|
||
$workflow = new SeedDMS_Core_Workflow($resArr[0]["id"], $resArr[0]["name"], $initstate);
|
||
$workflow->setDMS($this);
|
||
|
||
return $workflow;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a new workflow
|
||
*
|
||
* @param string $name name of workflow
|
||
* @param string $initstate initial state of workflow
|
||
*/
|
||
function addWorkflow($name, $initstate) { /* {{{ */
|
||
$db = $this->db;
|
||
if (is_object($this->getWorkflowByName($name))) {
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblWorkflows` (`name`, `initstate`) VALUES (".$db->qstr($name).", ".$initstate->getID().")";
|
||
$res = $db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
|
||
return $this->getWorkflow($db->getInsertID('tblWorkflows'));
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a workflow state by its id
|
||
*
|
||
* This function retrieves a workflow state from the database by its id.
|
||
*
|
||
* @param integer $id internal id of workflow state
|
||
* @return object instance of {@link SeedDMS_Core_Workflow_State} or false
|
||
*/
|
||
function getWorkflowState($id) { /* {{{ */
|
||
if (!is_numeric($id))
|
||
return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowStates` 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];
|
||
|
||
$state = new SeedDMS_Core_Workflow_State($resArr["id"], $resArr["name"], $resArr["maxtime"], $resArr["precondfunc"], $resArr["documentstatus"]);
|
||
$state->setDMS($this);
|
||
return $state;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return workflow state by its name
|
||
*
|
||
* @param string $name name of workflow state
|
||
* @return object of instances of {@link SeedDMS_Core_Workflow_State} or false
|
||
*/
|
||
function getWorkflowStateByName($name) { /* {{{ */
|
||
if (!$name) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowStates` WHERE `name`=".$this->db->qstr($name);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
if(!$resArr)
|
||
return false;
|
||
|
||
$resArr = $resArr[0];
|
||
|
||
$state = new SeedDMS_Core_Workflow_State($resArr["id"], $resArr["name"], $resArr["maxtime"], $resArr["precondfunc"], $resArr["documentstatus"]);
|
||
$state->setDMS($this);
|
||
|
||
return $state;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return list of all workflow states
|
||
*
|
||
* @return array of instances of {@link SeedDMS_Core_Workflow_State} or false
|
||
*/
|
||
function getAllWorkflowStates() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblWorkflowStates` ORDER BY `name`";
|
||
$ressArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($ressArr) && $ressArr == false)
|
||
return false;
|
||
|
||
$wkfstates = array();
|
||
for ($i = 0; $i < count($ressArr); $i++) {
|
||
$wkfstate = new SeedDMS_Core_Workflow_State($ressArr[$i]["id"], $ressArr[$i]["name"], $ressArr[$i]["maxtime"], $ressArr[$i]["precondfunc"], $ressArr[$i]["documentstatus"]);
|
||
$wkfstate->setDMS($this);
|
||
$wkfstates[$i] = $wkfstate;
|
||
}
|
||
|
||
return $wkfstates;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add new workflow state
|
||
*
|
||
* @param string $name name of workflow state
|
||
* @param integer $docstatus document status when this state is reached
|
||
* @return object instance of new workflow state
|
||
*/
|
||
function addWorkflowState($name, $docstatus) { /* {{{ */
|
||
$db = $this->db;
|
||
if (is_object($this->getWorkflowStateByName($name))) {
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblWorkflowStates` (`name`, `documentstatus`) VALUES (".$db->qstr($name).", ".(int) $docstatus.")";
|
||
$res = $db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
|
||
return $this->getWorkflowState($db->getInsertID('tblWorkflowStates'));
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a workflow action by its id
|
||
*
|
||
* This function retrieves a workflow action from the database by its id.
|
||
*
|
||
* @param integer $id internal id of workflow action
|
||
* @return object instance of {@link SeedDMS_Core_Workflow_Action} or false
|
||
*/
|
||
function getWorkflowAction($id) { /* {{{ */
|
||
if (!is_numeric($id))
|
||
return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowActions` 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];
|
||
|
||
$action = new SeedDMS_Core_Workflow_Action($resArr["id"], $resArr["name"]);
|
||
$action->setDMS($this);
|
||
return $action;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a workflow action by its name
|
||
*
|
||
* This function retrieves a workflow action from the database by its name.
|
||
*
|
||
* @param string $name name of workflow action
|
||
* @return object instance of {@link SeedDMS_Core_Workflow_Action} or false
|
||
*/
|
||
function getWorkflowActionByName($name) { /* {{{ */
|
||
if (!$name) return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowActions` WHERE `name` = " . $this->db->qstr($name);
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false) return false;
|
||
if (count($resArr) != 1) return false;
|
||
|
||
$resArr = $resArr[0];
|
||
|
||
$action = new SeedDMS_Core_Workflow_Action($resArr["id"], $resArr["name"]);
|
||
$action->setDMS($this);
|
||
return $action;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return list of workflow action
|
||
*
|
||
* @return array list of instances of {@link SeedDMS_Core_Workflow_Action} or false
|
||
*/
|
||
function getAllWorkflowActions() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblWorkflowActions`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
|
||
if (is_bool($resArr) && $resArr == false)
|
||
return false;
|
||
|
||
$wkfactions = array();
|
||
for ($i = 0; $i < count($resArr); $i++) {
|
||
$action = new SeedDMS_Core_Workflow_Action($resArr[$i]["id"], $resArr[$i]["name"]);
|
||
$action->setDMS($this);
|
||
$wkfactions[$i] = $action;
|
||
}
|
||
|
||
return $wkfactions;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add new workflow action
|
||
*
|
||
* @param string $name name of workflow action
|
||
* @return object instance new workflow action
|
||
*/
|
||
function addWorkflowAction($name) { /* {{{ */
|
||
$db = $this->db;
|
||
if (is_object($this->getWorkflowActionByName($name))) {
|
||
return false;
|
||
}
|
||
$queryStr = "INSERT INTO `tblWorkflowActions` (`name`) VALUES (".$db->qstr($name).")";
|
||
$res = $db->getResult($queryStr);
|
||
if (!$res)
|
||
return false;
|
||
|
||
return $this->getWorkflowAction($db->getInsertID('tblWorkflowActions'));
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Return a workflow transition by its id
|
||
*
|
||
* This function retrieves a workflow transition from the database by its id.
|
||
*
|
||
* @param integer $id internal id of workflow transition
|
||
* @return object instance of {@link SeedDMS_Core_Workflow_Transition} or false
|
||
*/
|
||
function getWorkflowTransition($id) { /* {{{ */
|
||
if (!is_numeric($id))
|
||
return false;
|
||
|
||
$queryStr = "SELECT * FROM `tblWorkflowTransitions` 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];
|
||
|
||
$transition = new SeedDMS_Core_Workflow_Transition($resArr["id"], $this->getWorkflow($resArr["workflow"]), $this->getWorkflowState($resArr["state"]), $this->getWorkflowAction($resArr["action"]), $this->getWorkflowState($resArr["nextstate"]), $resArr["maxtime"]);
|
||
$transition->setDMS($this);
|
||
return $transition;
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns document content which is not linked to a document
|
||
*
|
||
* This method is for finding straying document content without
|
||
* a parent document. In normal operation this should not happen
|
||
* but little checks for database consistency and possible errors
|
||
* in the application may have left over document content though
|
||
* the document is gone already.
|
||
*/
|
||
function getUnlinkedDocumentContent() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `document` NOT IN (SELECT id FROM `tblDocuments`)";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if ($resArr === false)
|
||
return false;
|
||
|
||
$versions = array();
|
||
foreach($resArr as $row) {
|
||
$document = new $this->classnames['document']($row['document'], '', '', '', '', '', '', '', '', '', '', '');
|
||
$document->setDMS($this);
|
||
$version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']);
|
||
$versions[] = $version;
|
||
}
|
||
return $versions;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns document content which has no file size set
|
||
*
|
||
* This method is for finding document content without a file size
|
||
* set in the database. The file size of a document content was introduced
|
||
* in version 4.0.0 of SeedDMS for implementation of user quotas.
|
||
*/
|
||
function getNoFileSizeDocumentContent() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `fileSize` = 0 OR `fileSize` is null";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if ($resArr === false)
|
||
return false;
|
||
|
||
$versions = array();
|
||
foreach($resArr as $row) {
|
||
$document = new $this->classnames['document']($row['document'], '', '', '', '', '', '', '', '', '', '', '');
|
||
$document->setDMS($this);
|
||
$version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum'], $row['fileSize'], $row['checksum']);
|
||
$versions[] = $version;
|
||
}
|
||
return $versions;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns document content which has no checksum set
|
||
*
|
||
* This method is for finding document content without a checksum
|
||
* set in the database. The checksum of a document content was introduced
|
||
* in version 4.0.0 of SeedDMS for finding duplicates.
|
||
*/
|
||
function getNoChecksumDocumentContent() { /* {{{ */
|
||
$queryStr = "SELECT * FROM `tblDocumentContent` WHERE `checksum` = '' OR `checksum` is null";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if ($resArr === false)
|
||
return false;
|
||
|
||
$versions = array();
|
||
foreach($resArr as $row) {
|
||
$document = new $this->classnames['document']($row['document'], '', '', '', '', '', '', '', '', '', '', '');
|
||
$document->setDMS($this);
|
||
$version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']);
|
||
$versions[] = $version;
|
||
}
|
||
return $versions;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns document content which is duplicated
|
||
*
|
||
* This method is for finding document content which is available twice
|
||
* in the database. The checksum of a document content was introduced
|
||
* in version 4.0.0 of SeedDMS for finding duplicates.
|
||
*/
|
||
function getDuplicateDocumentContent() { /* {{{ */
|
||
$queryStr = "SELECT a.*, b.`id` as dupid FROM `tblDocumentContent` a LEFT JOIN `tblDocumentContent` b ON a.`checksum`=b.`checksum` where a.`id`!=b.`id` ORDER by a.`id` LIMIT 1000";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
$versions = array();
|
||
foreach($resArr as $row) {
|
||
$document = $this->getDocument($row['document']);
|
||
$version = new $this->classnames['documentcontent']($row['id'], $document, $row['version'], $row['comment'], $row['date'], $row['createdBy'], $row['dir'], $row['orgFileName'], $row['fileType'], $row['mimeType'], $row['fileSize'], $row['checksum']);
|
||
if(!isset($versions[$row['dupid']])) {
|
||
$versions[$row['id']]['content'] = $version;
|
||
$versions[$row['id']]['duplicates'] = array();
|
||
} else
|
||
$versions[$row['dupid']]['duplicates'][] = $version;
|
||
}
|
||
return $versions;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns statitical information
|
||
*
|
||
* This method returns all kind of statistical information like
|
||
* documents or used space per user, recent activity, etc.
|
||
*
|
||
* @param string $type type of statistic
|
||
* @return array statistical data
|
||
*/
|
||
function getStatisticalData($type='') { /* {{{ */
|
||
switch($type) {
|
||
case 'docsperuser':
|
||
$queryStr = "select b.`fullName` as `key`, count(`owner`) as total from `tblDocuments` a left join `tblUsers` b on a.`owner`=b.`id` group by `owner`, b.`fullName`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
case 'docspermimetype':
|
||
$queryStr = "select b.`mimeType` as `key`, count(`mimeType`) as total from `tblDocuments` a left join `tblDocumentContent` b on a.`id`=b.`document` group by b.`mimeType`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
case 'docspercategory':
|
||
$queryStr = "select b.`name` as `key`, count(a.`categoryID`) as total from `tblDocumentCategory` a left join `tblCategory` b on a.`categoryID`=b.id group by a.`categoryID`, b.`name`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
case 'docsperstatus':
|
||
$queryStr = "select b.`status` as `key`, count(b.`status`) as total from (select a.id, max(b.version), max(c.`statusLogID`) as maxlog from `tblDocuments` a left join `tblDocumentStatus` b on a.id=b.`documentID` left join `tblDocumentStatusLog` c on b.`statusID`=c.`statusID` group by a.`id`, b.`version` order by a.`id`, b.`statusID`) a left join `tblDocumentStatusLog` b on a.`maxlog`=b.`statusLogID` group by b.`status`";
|
||
$queryStr = "select b.`status` as `key`, count(b.`status`) as total from (select a.`id`, max(c.`statusLogID`) as maxlog from `tblDocuments` a left join `tblDocumentStatus` b on a.id=b.`documentID` left join `tblDocumentStatusLog` c on b.`statusID`=c.`statusID` group by a.`id` order by a.id) a left join `tblDocumentStatusLog` b on a.maxlog=b.`statusLogID` group by b.`status`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
case 'docspermonth':
|
||
$queryStr = "select *, count(`key`) as total from (select ".$this->db->getDateExtract("date", '%Y-%m')." as `key` from `tblDocuments`) a group by `key` order by `key`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
case 'docsaccumulated':
|
||
$queryStr = "select *, count(`key`) as total from (select ".$this->db->getDateExtract("date")." as `key` from `tblDocuments`) a group by `key` order by `key`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
$sum = 0;
|
||
foreach($resArr as &$res) {
|
||
$sum += $res['total'];
|
||
/* auxially variable $key is need because sqlite returns
|
||
* a key '`key`'
|
||
*/
|
||
$res['key'] = mktime(12, 0, 0, substr($res['key'], 5, 2), substr($res['key'], 8, 2), substr($res['key'], 0, 4)) * 1000;
|
||
$res['total'] = $sum;
|
||
}
|
||
return $resArr;
|
||
case 'sizeperuser':
|
||
$queryStr = "select c.`fullName` as `key`, sum(`fileSize`) as total from `tblDocuments` a left join `tblDocumentContent` b on a.id=b.`document` left join `tblUsers` c on a.`owner`=c.`id` group by a.`owner`, c.`fullName`";
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if (!$resArr)
|
||
return false;
|
||
|
||
return $resArr;
|
||
default:
|
||
return array();
|
||
}
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Returns changes with a period of time
|
||
*
|
||
* This method returns a list of all changes happened in the database
|
||
* within a given period of time. It currently just checks for
|
||
* entries in the database tables tblDocumentContent, tblDocumentFiles,
|
||
* and tblDocumentStatusLog
|
||
*
|
||
* @param string $start start date, defaults to start of current day
|
||
* @param string $end end date, defaults to end of start day
|
||
* @return array list of changes
|
||
*/
|
||
function getTimeline($startts='', $endts='') { /* {{{ */
|
||
if(!$startts)
|
||
$startts = mktime(0, 0, 0);
|
||
if(!$endts)
|
||
$endts = $startts+86400;
|
||
$timeline = array();
|
||
|
||
$queryStr = "SELECT DISTINCT document FROM `tblDocumentContent` WHERE `date` > ".$startts." AND `date` < ".$endts." UNION SELECT DISTINCT document FROM `tblDocumentFiles` WHERE `date` > ".$startts." AND `date` < ".$endts;
|
||
$resArr = $this->db->getResultArray($queryStr);
|
||
if ($resArr === false)
|
||
return false;
|
||
foreach($resArr as $rec) {
|
||
$document = $this->getDocument($rec['document']);
|
||
$timeline = array_merge($timeline, $document->getTimeline());
|
||
}
|
||
return $timeline;
|
||
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Set a callback function
|
||
*
|
||
* @param string $name internal name of callback
|
||
* @param mixed $func function name as expected by {call_user_method}
|
||
* @param mixed $params parameter passed as the first argument to the
|
||
* callback
|
||
*/
|
||
function setCallback($name, $func, $params=null) { /* {{{ */
|
||
if($name && $func)
|
||
$this->callbacks[$name] = array(array($func, $params));
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Add a callback function
|
||
*
|
||
* @param string $name internal name of callback
|
||
* @param mixed $func function name as expected by {call_user_method}
|
||
* @param mixed $params parameter passed as the first argument to the
|
||
* callback
|
||
*/
|
||
function addCallback($name, $func, $params=null) { /* {{{ */
|
||
if($name && $func)
|
||
$this->callbacks[$name][] = array($func, $params);
|
||
} /* }}} */
|
||
|
||
/**
|
||
* Create an sql dump of the complete database
|
||
*
|
||
* @param string $filename name of dump file
|
||
*/
|
||
function createDump($filename) { /* {{{ */
|
||
$h = fopen($filename, "w");
|
||
if(!$h)
|
||
return false;
|
||
|
||
$tables = $this->db->TableList('TABLES');
|
||
foreach($tables as $table) {
|
||
$query = "SELECT * FROM `".$table."`";
|
||
$records = $this->db->getResultArray($query);
|
||
fwrite($h,"\n-- TABLE: ".$table."--\n\n");
|
||
foreach($records as $record) {
|
||
$values="";
|
||
$i = 1;
|
||
foreach ($record as $column) {
|
||
if (is_numeric($column)) $values .= $column;
|
||
else $values .= $this->db->qstr($column);
|
||
|
||
if ($i<(count($record))) $values .= ",";
|
||
$i++;
|
||
}
|
||
|
||
fwrite($h, "INSERT INTO `".$table."` VALUES (".$values.");\n");
|
||
}
|
||
}
|
||
|
||
fclose($h);
|
||
return true;
|
||
} /* }}} */
|
||
|
||
}
|
||
?>
|