Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.29% covered (warning)
63.29%
724 / 1144
55.66% covered (warning)
55.66%
59 / 106
CRAP
0.00% covered (danger)
0.00%
0 / 2
SeedDMS_Core_Role
25.61% covered (danger)
25.61%
21 / 82
43.75% covered (danger)
43.75%
7 / 16
600.57
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getInstance
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
7.23
 getAllInstances
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
30
 setDMS
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getID
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setName
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 isAdmin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isGuest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRole
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRole
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getNoAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNoAccess
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 remove
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 isUsed
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 getUsers
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
SeedDMS_Core_User
66.20% covered (warning)
66.20%
703 / 1062
57.78% covered (warning)
57.78%
52 / 90
8415.99
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 getInstance
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
8
 getAllInstances
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
 isType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDMS
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDMS
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getID
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLogin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setLogin
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 getFullName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFullName
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getPwd
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPwd
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getSecret
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setSecret
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getPwdExpiration
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPwdExpiration
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 getEmail
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setEmail
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getLanguage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setLanguage
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getTheme
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTheme
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getComment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setComment
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getRole
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRole
80.00% covered (warning)
80.00%
8 / 10
0.00% covered (danger)
0.00%
0 / 1
5.20
 isAdmin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 _setAdmin
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 isGuest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 _setGuest
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 isHidden
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setHidden
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 isDisabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDisabled
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 addLoginFailure
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 clearLoginFailures
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getUsedDiskSpace
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getQuota
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setQuota
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 getHomeFolder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setHomeFolder
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 __removeFromProcesses
16.67% covered (danger)
16.67%
18 / 108
0.00% covered (danger)
0.00%
0 / 1
3690.69
 removeFromProcesses
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
2.09
 __transferDocumentsFolders
68.42% covered (warning)
68.42%
13 / 19
0.00% covered (danger)
0.00%
0 / 1
8.54
 transferDocumentsFolders
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
3.10
 __transferEvents
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
3.21
 transferEvents
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 remove
49.45% covered (danger)
49.45%
45 / 91
0.00% covered (danger)
0.00%
0 / 1
105.73
 joinGroup
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 leaveGroup
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 getGroups
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
5.01
 isMemberOfGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasImage
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
4.02
 getImage
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 setImage
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
4.07
 getDocuments
73.33% covered (warning)
73.33%
11 / 15
0.00% covered (danger)
0.00%
0 / 1
4.30
 getDocumentsLocked
73.33% covered (warning)
73.33%
11 / 15
0.00% covered (danger)
0.00%
0 / 1
4.30
 getDocumentsCheckOut
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 getDocumentLinks
64.29% covered (warning)
64.29%
9 / 14
0.00% covered (danger)
0.00%
0 / 1
4.73
 getDocumentFiles
69.23% covered (warning)
69.23%
9 / 13
0.00% covered (danger)
0.00%
0 / 1
4.47
 getDocumentContents
66.67% covered (warning)
66.67%
8 / 12
0.00% covered (danger)
0.00%
0 / 1
4.59
 getFolders
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
4.01
 getReviewStatus
79.17% covered (warning)
79.17%
38 / 48
0.00% covered (danger)
0.00%
0 / 1
20.93
 getApprovalStatus
80.00% covered (warning)
80.00%
40 / 50
0.00% covered (danger)
0.00%
0 / 1
20.59
 getReceiptStatus
79.17% covered (warning)
79.17%
38 / 48
0.00% covered (danger)
0.00%
0 / 1
26.38
 getRevisionStatus
82.00% covered (warning)
82.00%
41 / 50
0.00% covered (danger)
0.00%
0 / 1
24.82
 getWorkflowStatus
53.85% covered (warning)
53.85%
14 / 26
0.00% covered (danger)
0.00%
0 / 1
29.62
 getWorkflowsInvolved
70.00% covered (warning)
70.00%
7 / 10
0.00% covered (danger)
0.00%
0 / 1
5.68
 getMandatoryReviewers
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getMandatoryApprovers
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 isMandatoryReviewerOf
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 isMandatoryApproverOf
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 getMandatoryWorkflow
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
4.25
 getMandatoryWorkflows
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 setMandatoryReviewer
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
8
 setMandatoryApprover
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
8
 setMandatoryWorkflow
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 setMandatoryWorkflows
71.43% covered (warning)
71.43%
10 / 14
0.00% covered (danger)
0.00%
0 / 1
5.58
 delMandatoryReviewers
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 delMandatoryApprovers
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 delMandatoryWorkflow
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getSubstitutes
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 getReverseSubstitutes
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
42
 addSubstitute
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 removeSubstitute
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 isSubstitute
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 maySwitchToUser
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
56
 getNotifications
71.43% covered (warning)
71.43%
10 / 14
0.00% covered (danger)
0.00%
0 / 1
5.58
 getKeywordCategories
63.64% covered (warning)
63.64%
7 / 11
0.00% covered (danger)
0.00%
0 / 1
4.77
1<?php
2declare(strict_types=1);
3
4/**
5 * Implementation of the user object in the document management system
6 *
7 * @category   DMS
8 * @package    SeedDMS_Core
9 * @license    GPL 2
10 * @version    @version@
11 * @author     Uwe Steinmann <uwe@steinmann.cx>
12 * @copyright  Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
13 *             2010 Uwe Steinmann
14 * @version    Release: @package_version@
15 */
16
17/**
18 * Class to represent a role in the document management system
19 *
20 * @category   DMS
21 * @package    SeedDMS_Core
22 * @author     Uwe Steinmann <uwe@steinmann.cx>
23 * @copyright  Copyright (C) 2016 Uwe Steinmann
24 * @version    Release: @package_version@
25 */
26class SeedDMS_Core_Role { /* {{{ */
27    /**
28     * @var integer id of role
29     *
30     * @access protected
31     */
32    var $_id;
33
34    /**
35     * @var string name of role
36     *
37     * @access protected
38     */
39    var $_name;
40
41    /**
42     * @var string role of user. Can be one of SeedDMS_Core_User::role_user,
43     *      SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest
44     *
45     * @access protected
46     */
47    var $_role;
48
49    /**
50     * @var array list of status without access
51     *
52     * @access protected
53     */
54    var $_noaccess;
55
56    /**
57     * @var object reference to the dms instance this user belongs to
58     *
59     * @access protected
60     */
61    var $_dms;
62
63    const role_user = '0';
64    const role_admin = '1';
65    const role_guest = '2';
66
67    function __construct($id, $name, $role, $noaccess=array()) { /* {{{ */
68        $this->_id = $id;
69        $this->_name = $name;
70        $this->_role = $role;
71        $this->_noaccess = $noaccess;
72        $this->_dms = null;
73    } /* }}} */
74
75    /**
76     * Create an instance of a role object
77     *
78     * @param string|integer $id Id, login name, or email of user, depending
79     * on the 3rd parameter.
80     * @param object $dms instance of dms
81     * @param string $by search by name. If 'name' is passed, the method
82     * will search by name instead of id. If this
83     * parameter is left empty, the role will be searched by its Id.
84     *
85     * @return object instance of class SeedDMS_Core_User
86     */
87    public static function getInstance($id, $dms, $by='') { /* {{{ */
88        $db = $dms->getDB();
89
90        switch($by) {
91        case 'name':
92            $queryStr = "SELECT * FROM `tblRoles` WHERE `name` = ".$db->qstr($id);
93            break;
94        default:
95            $queryStr = "SELECT * FROM `tblRoles` WHERE `id` = " . (int) $id;
96        }
97
98        $resArr = $db->getResultArray($queryStr);
99        if (is_bool($resArr) && $resArr == false) return false;
100        if (count($resArr) != 1) return false;
101
102        $resArr = $resArr[0];
103
104        $role = new self($resArr["id"], $resArr["name"], $resArr["role"], $resArr['noaccess'] ? explode(',', $resArr['noaccess']) : array());
105        $role->setDMS($dms);
106        return $role;
107    } /* }}} */
108
109    public static function getAllInstances($orderby, $dms) { /* {{{ */
110        $db = $dms->getDB();
111
112        if($orderby == 'name')
113            $queryStr = "SELECT * FROM `tblRoles` ORDER BY `name`";
114        else
115            $queryStr = "SELECT * FROM `tblRoles` ORDER BY `id`";
116        $resArr = $db->getResultArray($queryStr);
117
118        if (is_bool($resArr) && $resArr == false)
119            return false;
120
121        $roles = array();
122
123        for ($i = 0; $i < count($resArr); $i++) {
124            $role = new self($resArr[$i]["id"], $resArr[$i]["name"], $resArr[$i]["role"], explode(',', $resArr[$i]['noaccess']));
125            $role->setDMS($dms);
126            $roles[$i] = $role;
127        }
128
129        return $roles;
130} /* }}} */
131
132    function setDMS($dms) {
133        $this->_dms = $dms;
134    }
135
136    function getID() { return $this->_id; }
137
138    function getName() { return $this->_name; }
139
140    function setName($newName) { /* {{{ */
141        $db = $this->_dms->getDB();
142
143        $queryStr = "UPDATE `tblRoles` SET `name` =".$db->qstr($newName)." WHERE `id` = " . $this->_id;
144        $res = $db->getResult($queryStr);
145        if (!$res)
146            return false;
147
148        $this->_name = $newName;
149        return true;
150    } /* }}} */
151
152    function isAdmin() { return ($this->_role == SeedDMS_Core_Role::role_admin); }
153
154    function isGuest() { return ($this->_role == SeedDMS_Core_Role::role_guest); }
155
156    function getRole() { return $this->_role; }
157
158    function setRole($newrole) { /* {{{ */
159        $db = $this->_dms->getDB();
160
161        $queryStr = "UPDATE `tblRoles` SET `role` = " . $newrole . " WHERE `id` = " . $this->_id;
162        if (!$db->getResult($queryStr))
163            return false;
164
165        $this->_role = $newrole;
166        return true;
167    } /* }}} */
168
169    function getNoAccess() { return $this->_noaccess; }
170
171    function setNoAccess($noaccess) { /* {{{ */
172        $db = $this->_dms->getDB();
173
174        $queryStr = "UPDATE `tblRoles` SET `noaccess` = " . $db->qstr($noaccess ? implode(',',$noaccess) : '') . " WHERE `id` = " . $this->_id;
175        if (!$db->getResult($queryStr))
176            return false;
177
178        $this->_noaccess = $noaccess;
179        return true;
180    } /* }}} */
181
182    /**
183     * Delete role
184     *
185     * @return boolean true on success or false in case of an error
186     */
187    function remove() { /* {{{ */
188        $db = $this->_dms->getDB();
189
190        $queryStr = "DELETE FROM `tblRoles` WHERE `id` = " . $this->_id;
191        if (!$db->getResult($queryStr)) {
192            return false;
193        }
194
195        return true;
196    } /* }}} */
197
198    function isUsed() { /* {{{ */
199        $db = $this->_dms->getDB();
200        
201        $queryStr = "SELECT * FROM `tblUsers` WHERE `role`=".$this->_id;
202        $resArr = $db->getResultArray($queryStr);
203        if (is_array($resArr) && count($resArr) == 0)
204            return false;
205        return true;
206    } /* }}} */
207
208    function getUsers() { /* {{{ */
209        $db = $this->_dms->getDB();
210        
211        if (!isset($this->_users)) {
212            $queryStr = "SELECT * FROM `tblUsers` WHERE `role`=".$this->_id;
213            $resArr = $db->getResultArray($queryStr);
214            if (is_bool($resArr) && $resArr == false)
215                return false;
216
217            $this->_users = array();
218
219            $classnamerole = $this->_dms->getClassname('role');
220
221            $classname = $this->_dms->getClassname('user');
222            foreach ($resArr as $row) {
223                $role = $classnamerole::getInstance($row['role'], $this->_dms);
224                $user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $role, $row['hidden']);
225                $user->setDMS($this->_dms);
226                array_push($this->_users, $user);
227            }
228        }
229        return $this->_users;
230    } /* }}} */
231
232} /* }}} */
233
234/**
235 * Class to represent a user in the document management system
236 *
237 * @category   DMS
238 * @package    SeedDMS_Core
239 * @author     Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
240 * @copyright  Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
241 *             2010 Uwe Steinmann
242 * @version    Release: @package_version@
243 */
244class SeedDMS_Core_User { /* {{{ */
245    /**
246     * @var integer id of user
247     *
248     * @access protected
249     */
250    protected $_id;
251
252    /**
253     * @var string login name of user
254     *
255     * @access protected
256     */
257    protected $_login;
258
259    /**
260     * @var string password of user as saved in database (md5)
261     *
262     * @access protected
263     */
264    protected $_pwd;
265
266    /**
267     * @var string secret of user for 2-factor authentication
268     *
269     * @access protected
270     */
271    var $_secret;
272
273    /**
274     * @var string date when password expires
275     *
276     * @access protected
277     */
278    protected $_pwdExpiration;
279
280    /**
281     * @var string full human readable name of user
282     *
283     * @access protected
284     */
285    protected $_fullName;
286
287    /**
288     * @var string email address of user
289     *
290     * @access protected
291     */
292    protected $_email;
293
294    /**
295     * @var string prefered language of user
296     *      possible values are subdirectories within the language directory
297     *
298     * @access protected
299     */
300    protected $_language;
301
302    /**
303     * @var string preselected theme of user
304     *
305     * @access protected
306     */
307    protected $_theme;
308
309    /**
310     * @var string comment of user
311     *
312     * @access protected
313     */
314    protected $_comment;
315
316    /**
317     * @var string role of user. Can be one of SeedDMS_Core_User::role_user,
318     *      SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest
319     *
320     * @access protected
321     */
322    protected $_role;
323
324    /**
325     * @var boolean true if user shall be hidden
326     *
327     * @access protected
328     */
329    protected $_isHidden;
330
331    /**
332     * @var boolean true if user is disabled
333     *
334     * @access protected
335     */
336    protected $_isDisabled;
337
338    /**
339     * @var int number of login failures
340     *
341     * @access protected
342     */
343    protected $_loginFailures;
344
345    /**
346     * @var SeedDMS_Core_Folder home folder
347     *
348     * @access protected
349     */
350    protected $_homeFolder;
351
352    /**
353     * @var array list of users this user can substitute
354     *
355     * @access protected
356     */
357    var $_substitutes;
358
359    /**
360     * @var array reverse list of users this user can substitute
361     *
362     * @access protected
363     */
364    var $_rev_substitutes;
365
366    /**
367     * @var array list of groups
368     *
369     * @access protected
370     */
371    protected $_groups;
372
373    /**
374     * @var SeedDMS_Core_DMS reference to the dms instance this user belongs to
375     *
376     * @access protected
377     */
378    protected $_dms;
379
380    /**
381     * @var int
382     *
383     * @access protected
384     */
385    protected $_quota;
386
387    /**
388     * @var bool
389     *
390     * @access protected
391     */
392    protected $_hasImage;
393
394    const role_user = '0';
395    const role_admin = '1';
396    const role_guest = '2';
397
398    /**
399     * SeedDMS_Core_User constructor.
400     * @param $id
401     * @param $login
402     * @param $pwd
403     * @param $fullName
404     * @param $email
405     * @param $language
406     * @param $theme
407     * @param $comment
408     * @param $role
409     * @param int $isHidden
410     * @param int $isDisabled
411     * @param string $pwdExpiration
412     * @param int $loginFailures
413     * @param int $quota
414     * @param null $homeFolder
415     * @param string $secret
416     */
417    function __construct($id, $login, $pwd, $fullName, $email, $language, $theme, $comment, $role, $isHidden=0, $isDisabled=0, $pwdExpiration='', $loginFailures=0, $quota=0, $homeFolder=null, $secret='') {
418        $this->_id = $id;
419        $this->_login = $login;
420        $this->_pwd = $pwd;
421        $this->_fullName = $fullName;
422        $this->_email = $email;
423        $this->_language = $language;
424        $this->_theme = $theme;
425        $this->_comment = $comment;
426        $this->_role = $role;
427        $this->_isHidden = (bool) $isHidden;
428        $this->_isDisabled = (bool) $isDisabled;
429        $this->_pwdExpiration = $pwdExpiration;
430        $this->_loginFailures = $loginFailures;
431        $this->_quota = $quota;
432        $this->_homeFolder = $homeFolder;
433        $this->_secret = $secret;
434        $this->_substitutes = null;
435        $this->_rev_substitutes = null;
436        $this->_dms = null;
437    }
438
439    /**
440     * Create an instance of a user object
441     *
442     * @param string|integer $id Id, login name, or email of user, depending
443     * on the 3rd parameter.
444     * @param SeedDMS_Core_DMS $dms instance of dms
445     * @param string $by search by [name|email]. If 'name' is passed, the method
446     * will check for the 4th paramater and also filter by email. If this
447     * parameter is left empty, the user will be search by its Id.
448     * @param string $email optional email address if searching for name
449     * @return SeedDMS_Core_User|bool instance of class SeedDMS_Core_User if user was
450     * found, null if user was not found, false in case of error
451     */
452    public static function getInstance($id, $dms, $by='', $email='') { /* {{{ */
453        $db = $dms->getDB();
454
455        switch($by) {
456        case 'name':
457            $queryStr = "SELECT * FROM `tblUsers` WHERE `login` = ".$db->qstr($id);
458            if($email)
459                $queryStr .= " AND `email`=".$db->qstr($email);
460            break;
461        case 'email':
462            $queryStr = "SELECT * FROM `tblUsers` WHERE `email` = ".$db->qstr($id);
463            break;
464        default:
465            $queryStr = "SELECT * FROM `tblUsers` WHERE `id` = " . (int) $id;
466        }
467        $resArr = $db->getResultArray($queryStr);
468
469        if (is_bool($resArr) && $resArr == false) return false;
470        if (count($resArr) != 1) return null;
471
472        $resArr = $resArr[0];
473
474        $classname = $dms->getClassname('role');
475        $role = $classname::getInstance($resArr['role'], $dms);
476
477        $user = new self((int) $resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $role, $resArr["hidden"], $resArr["disabled"], $resArr["pwdExpiration"], $resArr["loginfailures"], $resArr["quota"], $resArr["homefolder"], $resArr["secret"]);
478        $user->setDMS($dms);
479        return $user;
480    } /* }}} */
481
482    /**
483     * @param $orderby
484     * @param SeedDMS_Core_DMS $dms
485     * @return SeedDMS_Core_User[]|bool
486     */
487    public static function getAllInstances($orderby, $dms) { /* {{{ */
488        $db = $dms->getDB();
489
490        if($orderby == 'fullname')
491            $queryStr = "SELECT * FROM `tblUsers` ORDER BY `fullName`";
492        else
493            $queryStr = "SELECT * FROM `tblUsers` ORDER BY `login`";
494        $resArr = $db->getResultArray($queryStr);
495
496        if (is_bool($resArr) && $resArr == false)
497            return false;
498
499        $users = array();
500
501        $classname = $dms->getClassname('role');
502        for ($i = 0; $i < count($resArr); $i++) {
503            /** @var SeedDMS_Core_User $user */
504            $role = $classname::getInstance($resArr[$i]['role'], $dms);
505            $user = new self($resArr[$i]["id"], $resArr[$i]["login"], $resArr[$i]["pwd"], $resArr[$i]["fullName"], $resArr[$i]["email"], (isset($resArr[$i]["language"])?$resArr[$i]["language"]:NULL), (isset($resArr[$i]["theme"])?$resArr[$i]["theme"]:NULL), $resArr[$i]["comment"], $role, $resArr[$i]["hidden"], $resArr[$i]["disabled"], $resArr[$i]["pwdExpiration"], $resArr[$i]["loginfailures"], $resArr[$i]["quota"], $resArr[$i]["homefolder"]);
506            $user->setDMS($dms);
507            $users[$i] = $user;
508        }
509
510        return $users;
511} /* }}} */
512
513    /**
514     * Check if this object is of type 'user'.
515     *
516     * @param string $type type of object
517     */
518    public function isType($type) { /* {{{ */
519        return $type == 'user';
520    } /* }}} */
521
522    /**
523     * @param SeedDMS_Core_DMS $dms
524     */
525    function setDMS($dms) {
526        $this->_dms = $dms;
527    }
528
529    /**
530     * @return SeedDMS_Core_DMS $dms
531     */
532    function getDMS() {
533        return $this->_dms;
534    }
535
536    /**
537     * @return int
538     */
539    function getID() { return $this->_id; }
540
541    /**
542     * @return string
543     */
544    function getLogin() { return $this->_login; }
545
546    /**
547     * @param $newLogin
548     * @return bool
549     */
550    function setLogin($newLogin) { /* {{{ */
551        $newLogin = trim($newLogin);
552        if(!$newLogin)
553            return false;
554
555        $db = $this->_dms->getDB();
556
557        $queryStr = "UPDATE `tblUsers` SET `login` =".$db->qstr($newLogin)." WHERE `id` = " . $this->_id;
558        $res = $db->getResult($queryStr);
559        if (!$res)
560            return false;
561
562        $this->_login = $newLogin;
563        return true;
564    } /* }}} */
565
566    /**
567     * @return string
568     */
569    function getFullName() { return $this->_fullName; }
570
571    /**
572     * @param $newFullName
573     * @return bool
574     */
575    function setFullName($newFullName) { /* {{{ */
576        $db = $this->_dms->getDB();
577
578        $queryStr = "UPDATE `tblUsers` SET `fullName` = ".$db->qstr($newFullName)." WHERE `id` = " . $this->_id;
579        $res = $db->getResult($queryStr);
580        if (!$res)
581            return false;
582
583        $this->_fullName = $newFullName;
584        return true;
585    } /* }}} */
586
587    /**
588     * @return string
589     */
590    function getPwd() { return $this->_pwd; }
591
592    /**
593     * @param $newPwd
594     * @return bool
595     */
596    function setPwd($newPwd) { /* {{{ */
597        $db = $this->_dms->getDB();
598
599        $queryStr = "UPDATE `tblUsers` SET `pwd` =".$db->qstr($newPwd)." WHERE `id` = " . $this->_id;
600        $res = $db->getResult($queryStr);
601        if (!$res)
602            return false;
603
604        $this->_pwd = $newPwd;
605        return true;
606    } /* }}} */
607
608    /**
609     * @return string
610     */
611    function getSecret() { return $this->_secret; }
612
613    /**
614     * @param string $newSecret
615     */
616    function setSecret($newSecret) { /* {{{ */
617        $db = $this->_dms->getDB();
618
619        $queryStr = "UPDATE `tblUsers` SET `secret` =".$db->qstr($newSecret)." WHERE `id` = " . $this->_id;
620        $res = $db->getResult($queryStr);
621        if (!$res)
622            return false;
623
624        $this->_secret = $newSecret;
625        return true;
626    } /* }}} */
627
628    /**
629     * @return string
630     */
631    function getPwdExpiration() { return $this->_pwdExpiration; }
632
633    /**
634     * @param $newPwdExpiration
635     * @return bool
636     */
637    function setPwdExpiration($newPwdExpiration) { /* {{{ */
638        $db = $this->_dms->getDB();
639
640        if(trim($newPwdExpiration) == '' || trim($newPwdExpiration) == 'never') {
641            $newPwdExpiration = null;
642            $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` = NULL WHERE `id` = " . $this->_id;
643        } else {
644            if(trim($newPwdExpiration) == 'now')
645                $newPwdExpiration = date('Y-m-d H:i:s');
646            $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` =".$db->qstr($newPwdExpiration)." WHERE `id` = " . $this->_id;
647        }
648        $res = $db->getResult($queryStr);
649        if (!$res)
650            return false;
651
652        $this->_pwdExpiration = $newPwdExpiration;
653        return true;
654    } /* }}} */
655
656    /**
657     * @return string
658     */
659    function getEmail() { return $this->_email; }
660
661    /**
662     * @param $newEmail
663     * @return bool
664     */
665    function setEmail($newEmail) { /* {{{ */
666        $db = $this->_dms->getDB();
667
668        $queryStr = "UPDATE `tblUsers` SET `email` =".$db->qstr(trim($newEmail))." WHERE `id` = " . $this->_id;
669        $res = $db->getResult($queryStr);
670        if (!$res)
671            return false;
672
673        $this->_email = $newEmail;
674        return true;
675    } /* }}} */
676
677    /**
678     * @return string
679     */
680    function getLanguage() { return $this->_language; }
681
682    /**
683     * @param $newLanguage
684     * @return bool
685     */
686    function setLanguage($newLanguage) { /* {{{ */
687        $db = $this->_dms->getDB();
688
689        $queryStr = "UPDATE `tblUsers` SET `language` =".$db->qstr(trim($newLanguage))." WHERE `id` = " . $this->_id;
690        $res = $db->getResult($queryStr);
691        if (!$res)
692            return false;
693
694        $this->_language = $newLanguage;
695        return true;
696    } /* }}} */
697
698    /**
699     * @return string
700     */
701    function getTheme() { return $this->_theme; }
702
703    /**
704     * @param string $newTheme
705     * @return bool
706     */
707    function setTheme($newTheme) { /* {{{ */
708        $db = $this->_dms->getDB();
709
710        $queryStr = "UPDATE `tblUsers` SET `theme` =".$db->qstr(trim($newTheme))." WHERE `id` = " . $this->_id;
711        $res = $db->getResult($queryStr);
712        if (!$res)
713            return false;
714
715        $this->_theme = $newTheme;
716        return true;
717    } /* }}} */
718
719    /**
720     * @return string
721     */
722    function getComment() { return $this->_comment; }
723
724    /**
725     * @param $newComment
726     * @return bool
727     */
728    function setComment($newComment) { /* {{{ */
729        $db = $this->_dms->getDB();
730
731        $queryStr = "UPDATE `tblUsers` SET `comment` =".$db->qstr(trim($newComment))." WHERE `id` = " . $this->_id;
732        $res = $db->getResult($queryStr);
733        if (!$res)
734            return false;
735
736        $this->_comment = $newComment;
737        return true;
738    } /* }}} */
739
740    /**
741     * @return string
742     */
743    function getRole() { return $this->_role; }
744
745    /**
746     * @param integer $newrole
747     * @return bool
748     */
749    function setRole($newrole) { /* {{{ */
750        $db = $this->_dms->getDB();
751
752        if(!is_object($newrole) || (get_class($newrole) != $this->_dms->getClassname('role')))
753            return false;
754
755        if(is_object($newrole))
756            $queryStr = "UPDATE `tblUsers` SET `role` = " . $newrole->getID() . " WHERE `id` = " . $this->_id;
757        else
758            $queryStr = "UPDATE `tblUsers` SET `role` = " . $newrole . " WHERE `id` = " . $this->_id;
759        if (!$db->getResult($queryStr))
760            return false;
761
762        $this->_role = $newrole;
763        return true;
764    } /* }}} */
765
766    /**
767     * @return bool
768     */
769    function isAdmin() { return (is_object($this->_role) ? $this->_role->isAdmin() : $this->_role == SeedDMS_Core_User::role_admin); }
770
771    /**
772     * Was never used and is now deprecated
773     */
774    function _setAdmin($isAdmin) { /* {{{ */
775        $db = $this->_dms->getDB();
776
777        $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_admin . " WHERE `id` = " . $this->_id;
778        if (!$db->getResult($queryStr))
779            return false;
780
781        $this->_role = SeedDMS_Core_User::role_admin;
782        return true;
783    } /* }}} */
784
785    /**
786     * @return bool
787     */
788    function isGuest() { return (is_object($this->_role) ? $this->_role->isGuest() : $this->_role == SeedDMS_Core_User::role_guest); }
789
790    /**
791     * Was never used and is now deprecated
792     */
793    function _setGuest($isGuest) { /* {{{ */
794        $db = $this->_dms->getDB();
795
796        $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_guest . " WHERE `id` = " . $this->_id;
797        if (!$db->getResult($queryStr))
798            return false;
799
800        $this->_role = SeedDMS_Core_User::role_guest;
801        return true;
802    } /* }}} */
803
804    /**
805     * @return bool
806     */
807    function isHidden() { return $this->_isHidden; }
808
809    /**
810     * @param $isHidden
811     * @return bool
812     */
813    function setHidden($isHidden) { /* {{{ */
814        $db = $this->_dms->getDB();
815
816        $isHidden = ($isHidden) ? "1" : "0";
817        $queryStr = "UPDATE `tblUsers` SET `hidden` = " . intval($isHidden) . " WHERE `id` = " . $this->_id;
818        if (!$db->getResult($queryStr))
819            return false;
820
821        $this->_isHidden = (bool) $isHidden;
822        return true;
823    }     /* }}} */
824
825    /**
826     * @return bool|int
827     */
828    function isDisabled() { return $this->_isDisabled; }
829
830    /**
831     * @param $isDisabled
832     * @return bool
833     */
834    function setDisabled($isDisabled) { /* {{{ */
835        $db = $this->_dms->getDB();
836
837        $isDisabled = ($isDisabled) ? "1" : "0";
838        $queryStr = "UPDATE `tblUsers` SET `disabled` = " . intval($isDisabled) . " WHERE `id` = " . $this->_id;
839        if (!$db->getResult($queryStr))
840            return false;
841
842        $this->_isDisabled = (bool) $isDisabled;
843        return true;
844    }     /* }}} */
845
846    /**
847     * @return bool|int
848     */
849    function addLoginFailure() { /* {{{ */
850        $db = $this->_dms->getDB();
851
852        $this->_loginFailures++;
853        $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id;
854        if (!$db->getResult($queryStr))
855            return false;
856
857        return $this->_loginFailures;
858    } /* }}} */
859
860    /**
861     * @return bool
862     */
863    function clearLoginFailures() { /* {{{ */
864        $db = $this->_dms->getDB();
865
866        $this->_loginFailures = 0;
867        $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id;
868        if (!$db->getResult($queryStr))
869            return false;
870
871        return true;
872    } /* }}} */
873
874    /**
875     * Calculate the disk space for all documents owned by the user
876     * 
877     * This is done by using the internal database field storing the
878     * filesize of a document version.
879     *
880     * @return integer total disk space in Bytes
881     */
882    function getUsedDiskSpace() { /* {{{ */
883        $db = $this->_dms->getDB();
884
885        $queryStr = "SELECT SUM(`fileSize`) sum FROM `tblDocumentContent` a LEFT JOIN `tblDocuments` b ON a.`document`=b.`id` WHERE b.`owner` = " . $this->_id;
886        $resArr = $db->getResultArray($queryStr);
887        if (is_bool($resArr) && $resArr == false)
888            return false;
889
890        return $resArr[0]['sum'];
891    } /* }}} */
892
893    /**
894     * @return int
895     */
896    function getQuota() { return $this->_quota; }
897
898    /**
899     * @param integer $quota
900     * @return bool
901     */
902    function setQuota($quota) { /* {{{ */
903        if (!is_numeric($quota))
904            return false;
905        if($quota < 0)
906            return false;
907
908        $db = $this->_dms->getDB();
909
910        $quota = intval($quota);
911        $queryStr = "UPDATE `tblUsers` SET `quota` = " . $quota . " WHERE `id` = " . $this->_id;
912        if (!$db->getResult($queryStr))
913            return false;
914
915        $this->_quota = $quota;
916        return true;
917    }     /* }}} */
918
919    /**
920     * @return null|SeedDMS_Core_Folder
921     */
922    function getHomeFolder() { return $this->_homeFolder; }
923
924    /**
925     * @param integer $homefolder
926     * @return bool
927     */
928    function setHomeFolder($homefolder) { /* {{{ */
929        $db = $this->_dms->getDB();
930        $homefolder = intval($homefolder);
931
932        $queryStr = "UPDATE `tblUsers` SET `homefolder` = " . ($homefolder ? $homefolder : 'NULL') . " WHERE `id` = " . $this->_id;
933        if (!$db->getResult($queryStr))
934            return false;
935
936        $this->_homeFolder = $homefolder;
937        return true;
938    }     /* }}} */
939
940    /**
941     * Remove user from all processes
942     *
943     * This method adds another log entry to the reviews, approvals, receptions, revisions,
944     * which indicates that the user has been deleted from the process. By default it will
945     * do so for each review/approval/reception/revision regardless of its current state unless
946     * the user has been removed already (status=-2). So even
947     * reviews/approvals/receptions/revisions already processed by the user will be added the log
948     * entry. Only, if the last log entry was a removal already, it will not be
949     * added a second time.
950     * This behaviour can be changed by passing a list of states in the optional
951     * argument $states. Only reviews, etc. in the given state will be affected.
952     * This allows to remove the user only if the review, etc. has not been done
953     * (state = 0).
954     *
955     * The last optional parameter $newuser is for replacing the user currently in
956     * charge by another user. If this parameter is passed, the old user will
957     * be deleted first (like described above) and afterwards the new user will
958     * be addded. The deletion of the old user and adding the new user will only
959     * happen if the new user has at least read access on the document. If not,
960     * the document will be skipped and remained unchanged.
961     *
962     * This removal from processes will also take place for older versions of a document.
963     *
964     * This methode was initialy added to remove a user (which is going to be deleted
965     * afterwards) from all processes he or she is still involved in.
966     *
967     * If a new user is passed, then this user will be added as a new reviewer, approver, etc.
968     * Hence, this method does not replace the old user but actually deletes the old user and
969     * adds a new one. Adding the new reviewer, approver, etc. will also be done for old versions
970     * of a document. The same operation could be archieved by first calling
971     * SeedDMS_Core_DocumentVersion::delIndReviewer() followed by SeedDMS_Core_DocumentVersion::addIndReviewer()
972     * but this would require to do for each version of a document and the operation would not
973     * be in a single transaction.
974     *
975     * A new user is only added if the process (review, approval, etc.) is still in its initial
976     * state (have not been reviewed/approved or rejected). Unlike the removal of the user (see above).
977     *
978     * If a new user is given but has no read access on the document the transfer for that
979     * particular document will be skipped. Not even the removal of the user will take place.
980     * 
981     * @param object $user the user doing the removal (needed for entry in
982     *        review and approve log).
983     * @param array $states remove user only from reviews/approvals in one of the states
984     *        e.g. if passing array('review'=>array(0)), the method will operate on
985     *        reviews which has not been touched yet.
986     * @param object $newuser user who takes over the processes
987     * @param array $docs remove only processes from docs with the given document ids
988     * @return boolean true on success or false in case of an error
989     */
990    private function __removeFromProcesses($user, $states = array(), $newuser=null, $docs=null) { /* {{{ */
991        $db = $this->_dms->getDB();
992
993        /* Get a list of all reviews, even those of older document versions */
994        $reviewStatus = $this->getReviewStatus();
995        $db->startTransaction();
996        foreach ($reviewStatus["indstatus"] as $ri) {
997            if(!($doc = $this->_dms->getDocument($ri['documentID'])))
998                continue;
999            if($docs) {
1000                if(!in_array($doc->getID(), $docs))
1001                    continue;
1002                if(!$doc->isLatestContent($ri['version']))
1003                    continue;
1004            }
1005            if($newuser && $doc->getAccessMode($newuser) < M_READ)
1006                continue;
1007            if($ri['status'] != -2 && (!isset($states['review']) || in_array($ri['status'], $states['review']))) {
1008                $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
1009                    "VALUES ('". $ri["reviewID"] ."', '-2', '".(($newuser && $ri['status'] == 0) ? 'Reviewer replaced by '.$newuser->getLogin() : 'Reviewer removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
1010                $res=$db->getResult($queryStr);
1011                if(!$res) {
1012                    $db->rollbackTransaction();
1013                    return false;
1014                }
1015                /* Only reviews not done already can be transferred to a new user */
1016                if($newuser && $ri['status'] == 0) {
1017                    if($version = $doc->getContentByVersion($ri['version'])) {
1018                        $ret = $version->addIndReviewer($newuser, $user);
1019                        /* returns -3 if the user is already a reviewer */ 
1020                        if($ret === false || ($ret < 0 && $ret != -3)) {
1021                            $db->rollbackTransaction();
1022                            return false;
1023                        }
1024                    }
1025                }
1026            }
1027        }
1028        $db->commitTransaction();
1029
1030        /* Get a list of all approvals, even those of older document versions */
1031        $approvalStatus = $this->getApprovalStatus();
1032        $db->startTransaction();
1033        foreach ($approvalStatus["indstatus"] as $ai) {
1034            if(!($doc = $this->_dms->getDocument($ai['documentID'])))
1035                continue;
1036            if($docs) {
1037                if(!in_array($doc->getID(), $docs))
1038                    continue;
1039                if(!$doc->isLatestContent($ai['version']))
1040                    continue;
1041            }
1042            if($newuser && $doc->getAccessMode($newuser) < M_READ)
1043                continue;
1044            if($ai['status'] != -2 && (!isset($states['approval']) || in_array($ai['status'], $states['approval']))) {
1045                $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
1046                    "VALUES ('". $ai["approveID"] ."', '-2', '".(($newuser && $ai['status'] == 0)? 'Approver replaced by '.$newuser->getLogin() : 'Approver removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
1047                $res=$db->getResult($queryStr);
1048                if(!$res) {
1049                    $db->rollbackTransaction();
1050                    return false;
1051                }
1052                /* Only approvals not done already can be transferred to a new user */
1053                if($newuser && $ai['status'] == 0) {
1054                    if($version = $doc->getContentByVersion($ai['version'])) {
1055                        $ret = $version->addIndReviewer($newuser, $user);
1056                        /* returns -3 if the user is already a reviewer */ 
1057                        if($ret === false || ($ret < 0 && $ret != -3)) {
1058                            $db->rollbackTransaction();
1059                            return false;
1060                        }
1061                    }
1062                }
1063            }
1064        }
1065        $db->commitTransaction();
1066
1067        /* Get a list of all receptions, even those of older document versions */
1068        $receiptStatus = $this->getReceiptStatus();
1069        $db->startTransaction();
1070        foreach ($receiptStatus["indstatus"] as $ri) {
1071            if(!($doc = $this->_dms->getDocument($ri['documentID'])))
1072                continue;
1073            if($docs) {
1074                if(!in_array($doc->getID(), $docs))
1075                    continue;
1076                if(!$doc->isLatestContent($ri['version']))
1077                    continue;
1078            }
1079            if($newuser && $doc->getAccessMode($newuser) < M_READ)
1080                continue;
1081            if($ri['status'] != -2 && (!isset($states['receipt']) || in_array($ri['status'], $states['receipt']))) {
1082                $queryStr = "INSERT INTO `tblDocumentReceiptLog` (`receiptID`, `status`, `comment`, `date`, `userID`) ".
1083                    "VALUES ('". $ri["receiptID"] ."', '-2', '".(($newuser && $ri['status'] == 0) ? 'Recipient replaced by '.$newuser->getLogin() : 'Recipient removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
1084                $res=$db->getResult($queryStr);
1085                if(!$res) {
1086                    $db->rollbackTransaction();
1087                    return false;
1088                }
1089                /* Only receptions not done already can be transferred to a new user */
1090                if($newuser && $ri['status'] == 0) {
1091                    if($doc = $this->_dms->getDocument($ri['documentID'])) {
1092                        if($version = $doc->getContentByVersion($ri['version'])) {
1093                            $ret = $version->addIndRecipient($newuser, $user);
1094                            /* returns -3 if the user is already a recipient */ 
1095                            if($ret === false || ($ret < 0 && $ret != -3)) {
1096                                $db->rollbackTransaction();
1097                                return false;
1098                            }
1099                        }
1100                    }
1101                }
1102            }
1103        }
1104        $db->commitTransaction();
1105
1106        /* Get a list of all revisions, even those of older document versions */
1107        $revisionStatus = $this->getRevisionStatus();
1108        $db->startTransaction();
1109        foreach ($revisionStatus["indstatus"] as $ri) {
1110            if(!($doc = $this->_dms->getDocument($ri['documentID'])))
1111                continue;
1112            if($docs) {
1113                if(!in_array($doc->getID(), $docs))
1114                    continue;
1115                if(!$doc->isLatestContent($ri['version']))
1116                    continue;
1117            }
1118            if($newuser && $doc->getAccessMode($newuser) < M_READ)
1119                continue;
1120            if($ri['status'] != -2 && (!isset($states['revision']) || in_array($ri['status'], $states['revision']))) {
1121                $queryStr = "INSERT INTO `tblDocumentRevisionLog` (`revisionID`, `status`, `comment`, `date`, `userID`) ".
1122                    "VALUES ('". $ri["revisionID"] ."', '-2', '".(($newuser && in_array($ri['status'], array(S_LOG_WAITING, S_LOG_SLEEPING))) ? 'Revisor replaced by '.$newuser->getLogin() : 'Revisor removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
1123                $res=$db->getResult($queryStr);
1124                if(!$res) {
1125                    $db->rollbackTransaction();
1126                    return false;
1127                }
1128                /* Only revisions not already done or sleeping can be transferred to a new user */
1129                if($newuser && in_array($ri['status'], array(S_LOG_WAITING, S_LOG_SLEEPING))) {
1130                    if($doc = $this->_dms->getDocument($ri['documentID'])) {
1131                        if($version = $doc->getContentByVersion($ri['version'])) {
1132                            $ret = $version->addIndRevisor($newuser, $user);
1133                            /* returns -3 if the user is already a revisor */ 
1134                            if($ret === false || ($ret < 0 && $ret != -3)) {
1135                                $db->rollbackTransaction();
1136                                return false;
1137                            }
1138                        }
1139                    }
1140                }
1141            }
1142        }
1143        $db->commitTransaction();
1144
1145        return true;
1146    } /* }}} */
1147
1148    /**
1149     * Remove user from all processes
1150     *
1151     * This includes review, approval and workflow
1152     *
1153     * @param object $user the user doing the removal (needed for entry in
1154     *        review and approve log).
1155     * @param array $states remove user only from reviews/approvals in one of the states
1156     * @param object $newuser user who takes over the processes
1157     * @return boolean true on success or false in case of an error
1158     */
1159    public function removeFromProcesses($user, $states=array(), $newuser=null, $docs=null) { /* {{{ */
1160        $db = $this->_dms->getDB();
1161
1162        $db->startTransaction();
1163        if(!$this->__removeFromProcesses($user, $states, $newuser, $docs)) {
1164            $db->rollbackTransaction();
1165            return false;
1166        }
1167        $db->commitTransaction();
1168        return true;
1169    } /* }}} */
1170
1171    /**
1172     * Transfer documents and folders to another user
1173     *
1174     * @param object $assignToUser the user who is new owner of folders and
1175     *        documents which previously were owned by the delete user.
1176     * @return boolean true on success or false in case of an error
1177     */
1178    private function __transferDocumentsFolders($assignToUser) { /* {{{ */
1179        $db = $this->_dms->getDB();
1180
1181        if(!$assignToUser)
1182            return false;
1183
1184        /* Assign documents of the removed user to the given user */
1185        $queryStr = "UPDATE `tblFolders` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id;
1186        if (!$db->getResult($queryStr)) {
1187            return false;
1188        }
1189
1190        $queryStr = "UPDATE `tblDocuments` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id;
1191        if (!$db->getResult($queryStr)) {
1192            return false;
1193        }
1194
1195        $queryStr = "UPDATE `tblDocumentContent` SET `createdBy` = " . $assignToUser->getID() . " WHERE `createdBy` = " . $this->_id;
1196        if (!$db->getResult($queryStr)) {
1197            return false;
1198        }
1199
1200        // ... but keep public links
1201        $queryStr = "UPDATE `tblDocumentLinks` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
1202        if (!$db->getResult($queryStr)) {
1203            return false;
1204        }
1205
1206        // set administrator for deleted user's attachments
1207        $queryStr = "UPDATE `tblDocumentFiles` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
1208        if (!$db->getResult($queryStr)) {
1209            return false;
1210        }
1211
1212        return true;
1213    } /* }}} */
1214
1215    /**
1216     * Transfer documents and folders to another user
1217     *
1218     * @param object $assignToUser the user who is new owner of folders and
1219     *        documents which previously were owned by the delete user.
1220     * @return boolean true on success or false in case of an error
1221     */
1222    public function transferDocumentsFolders($assignToUser) { /* {{{ */
1223        $db = $this->_dms->getDB();
1224
1225        if($assignToUser->getID() == $this->_id)
1226            return true;
1227
1228        $db->startTransaction();
1229        if(!$this->__transferDocumentsFolders($assignToUser)) {
1230            $db->rollbackTransaction();
1231            return false;
1232        }
1233        $db->commitTransaction();
1234        return true;
1235    } /* }}} */
1236
1237    /**
1238     * Transfer events to another user
1239     *
1240     * @param object $assignToUser the user who is new owner of events
1241     * @return boolean true on success or false in case of an error
1242     */
1243    private function __transferEvents($assignToUser) { /* {{{ */
1244        $db = $this->_dms->getDB();
1245
1246        if(!$assignToUser)
1247            return false;
1248
1249        // set new owner of events
1250        $queryStr = "UPDATE `tblEvents` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
1251        if (!$db->getResult($queryStr)) {
1252            return false;
1253        }
1254
1255        return true;
1256    } /* }}} */
1257
1258    /**
1259     * Transfer events to another user
1260     *
1261     * @param object $assignToUser the user who is new owner of events
1262     * @return boolean true on success or false in case of an error
1263     */
1264    public function transferEvents($assignToUser) { /* {{{ */
1265        $db = $this->_dms->getDB();
1266
1267        if($assignToUser->getID() == $this->_id)
1268            return true;
1269
1270        $db->startTransaction();
1271        if(!$this->__transferEvents($assignToUser)) {
1272            $db->rollbackTransaction();
1273            return false;
1274        }
1275        $db->commitTransaction();
1276        return true;
1277    } /* }}} */
1278
1279    /**
1280     * Remove the user and also remove all its keywords, notifications, etc.
1281     * Do not remove folders and documents of the user, but assign them
1282     * to a different user.
1283     *
1284     * @param SeedDMS_Core_User $user the user doing the removal (needed for entry in
1285     *        review and approve log).
1286     * @param SeedDMS_Core_User $assignToUser the user who is new owner of folders and
1287     *        documents which previously were owned by the delete user.
1288     * @return boolean true on success or false in case of an error
1289     */
1290    function remove($user, $assignToUser=null) { /* {{{ */
1291        $db = $this->_dms->getDB();
1292
1293        /* Records like folders and documents that formely have belonged to
1294         * the user will assign to another user. If no such user is set,
1295         * the function now returns false and will not use the admin user
1296         * anymore.
1297         */
1298        if(!$assignToUser)
1299            return false;
1300            /** @noinspection PhpUnusedLocalVariableInspection */
1301            $assignTo = $assignToUser->getID();
1302
1303        $db->startTransaction();
1304
1305        // delete private keyword lists
1306        $queryStr = "SELECT `tblKeywords`.`id` FROM `tblKeywords`, `tblKeywordCategories` WHERE `tblKeywords`.`category` = `tblKeywordCategories`.`id` AND `tblKeywordCategories`.`owner` = " . $this->_id;
1307        $resultArr = $db->getResultArray($queryStr);
1308        if (count($resultArr) > 0) {
1309            $queryStr = "DELETE FROM `tblKeywords` WHERE ";
1310            for ($i = 0; $i < count($resultArr); $i++) {
1311                $queryStr .= "id = " . $resultArr[$i]["id"];
1312                if ($i + 1 < count($resultArr))
1313                    $queryStr .= " OR ";
1314            }
1315            if (!$db->getResult($queryStr)) {
1316                $db->rollbackTransaction();
1317                return false;
1318            }
1319        }
1320
1321        $queryStr = "DELETE FROM `tblKeywordCategories` WHERE `owner` = " . $this->_id;
1322        if (!$db->getResult($queryStr)) {
1323            $db->rollbackTransaction();
1324            return false;
1325        }
1326
1327        //Benachrichtigungen entfernen
1328        $queryStr = "DELETE FROM `tblNotify` WHERE `userID` = " . $this->_id;
1329        if (!$db->getResult($queryStr)) {
1330            $db->rollbackTransaction();
1331            return false;
1332        }
1333
1334        // Remove private links on documents ...
1335        $queryStr = "DELETE FROM `tblDocumentLinks` WHERE `userID` = " . $this->_id . " AND `public` = 0";
1336        if (!$db->getResult($queryStr)) {
1337            $db->rollbackTransaction();
1338            return false;
1339        }
1340
1341        /* Assign documents, folders, files, public document links of the removed user to the given user */
1342        if(!$this->__transferDocumentsFolders($assignToUser)) {
1343                $db->rollbackTransaction();
1344                return false;
1345        }
1346
1347        // unlock documents locked by the user
1348        $queryStr = "DELETE FROM `tblDocumentLocks` WHERE `userID` = " . $this->_id;
1349        if (!$db->getResult($queryStr)) {
1350            $db->rollbackTransaction();
1351            return false;
1352        }
1353
1354        // Delete user from all groups
1355        $queryStr = "DELETE FROM `tblGroupMembers` WHERE `userID` = " . $this->_id;
1356        if (!$db->getResult($queryStr)) {
1357            $db->rollbackTransaction();
1358            return false;
1359        }
1360
1361        // User aus allen ACLs streichen
1362        $queryStr = "DELETE FROM `tblACLs` WHERE `userID` = " . $this->_id;
1363        if (!$db->getResult($queryStr)) {
1364            $db->rollbackTransaction();
1365            return false;
1366        }
1367
1368        // Delete image of user
1369        $queryStr = "DELETE FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1370        if (!$db->getResult($queryStr)) {
1371            $db->rollbackTransaction();
1372            return false;
1373        }
1374
1375        // Delete entries in password history
1376        $queryStr = "DELETE FROM `tblUserPasswordHistory` WHERE `userID` = " . $this->_id;
1377        if (!$db->getResult($queryStr)) {
1378            $db->rollbackTransaction();
1379            return false;
1380        }
1381
1382        // Delete entries in password request
1383        $queryStr = "DELETE FROM `tblUserPasswordRequest` WHERE `userID` = " . $this->_id;
1384        if (!$db->getResult($queryStr)) {
1385            $db->rollbackTransaction();
1386            return false;
1387        }
1388
1389        // mandatory review/approve
1390        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id;
1391        if (!$db->getResult($queryStr)) {
1392            $db->rollbackTransaction();
1393            return false;
1394        }
1395
1396        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id;
1397        if (!$db->getResult($queryStr)) {
1398            $db->rollbackTransaction();
1399            return false;
1400        }
1401
1402        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
1403        if (!$db->getResult($queryStr)) {
1404            $db->rollbackTransaction();
1405            return false;
1406        }
1407
1408        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
1409        if (!$db->getResult($queryStr)) {
1410            $db->rollbackTransaction();
1411            return false;
1412        }
1413
1414        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1415        if (!$db->getResult($queryStr)) {
1416            $db->rollbackTransaction();
1417            return false;
1418        }
1419
1420        $queryStr = "DELETE FROM `tblWorkflowTransitionUsers` WHERE `userid` = " . $this->_id;
1421        if (!$db->getResult($queryStr)) {
1422            $db->rollbackTransaction();
1423            return false;
1424        }
1425
1426        /* Assign events of the removed user to the given user */
1427        if(!$this->__transferEvents($assignToUser)) {
1428                $db->rollbackTransaction();
1429                return false;
1430        }
1431
1432        // Delete user itself
1433        $queryStr = "DELETE FROM `tblUsers` WHERE `id` = " . $this->_id;
1434        if (!$db->getResult($queryStr)) {
1435            $db->rollbackTransaction();
1436            return false;
1437        }
1438
1439        // TODO : update document status if reviewer/approver has been deleted
1440        // "DELETE FROM `tblDocumentApproveLog` WHERE `userID` = " . $this->_id;
1441        // "DELETE FROM `tblDocumentReviewLog` WHERE `userID` = " . $this->_id;
1442
1443        if(!$this->__removeFromProcesses($user)) {
1444                $db->rollbackTransaction();
1445                return false;
1446        }
1447
1448        $db->commitTransaction();
1449        return true;
1450    } /* }}} */
1451
1452    /**
1453     * Make the user a member of a group
1454     * This function uses {@link SeedDMS_Group::addUser} but checks before if
1455     * the user is already a member of the group.
1456     *
1457     * @param SeedDMS_Core_Group $group group to be the member of
1458     * @return boolean true on success or false in case of an error or the user
1459     *        is already a member of the group
1460     */
1461    function joinGroup($group) { /* {{{ */
1462        if ($group->isMember($this))
1463            return false;
1464
1465        if (!$group->addUser($this))
1466            return false;
1467
1468        unset($this->_groups);
1469        return true;
1470    } /* }}} */
1471
1472    /**
1473     * Removes the user from a group
1474     * This function uses {@link SeedDMS_Group::removeUser} but checks before if
1475     * the user is a member of the group at all.
1476     *
1477     * @param SeedDMS_Core_Group $group group to leave
1478     * @return boolean true on success or false in case of an error or the user
1479     *        is not a member of the group
1480     */
1481    function leaveGroup($group) { /* {{{ */
1482        if (!$group->isMember($this))
1483            return false;
1484
1485        if (!$group->removeUser($this))
1486            return false;
1487
1488        unset($this->_groups);
1489        return true;
1490    } /* }}} */
1491
1492    /**
1493     * Get all groups the user is a member of
1494     *
1495     * @return SeedDMS_Core_Group[]|bool list of groups
1496     */
1497    function getGroups() { /* {{{ */
1498        $db = $this->_dms->getDB();
1499
1500        if (!isset($this->_groups))
1501        {
1502            $queryStr = "SELECT `tblGroups`.*, `tblGroupMembers`.`userID` FROM `tblGroups` ".
1503                "LEFT JOIN `tblGroupMembers` ON `tblGroups`.`id` = `tblGroupMembers`.`groupID` ".
1504                "WHERE `tblGroupMembers`.`userID`='". $this->_id ."'";
1505            $resArr = $db->getResultArray($queryStr);
1506            if (is_bool($resArr) && $resArr == false)
1507                return false;
1508
1509            $this->_groups = array();
1510            $classname = $this->_dms->getClassname('group');
1511            foreach ($resArr as $row) {
1512                /** @var SeedDMS_Core_Group $group */
1513                $group = new $classname((int) $row["id"], $row["name"], $row["comment"]);
1514                $group->setDMS($this->_dms);
1515                array_push($this->_groups, $group);
1516            }
1517        }
1518        return $this->_groups;
1519    } /* }}} */
1520
1521    /**
1522     * Checks if user is member of a given group
1523     *
1524     * @param SeedDMS_Core_Group $group
1525     * @return boolean true if user is member of the given group otherwise false
1526     */
1527    function isMemberOfGroup($group) { /* {{{ */
1528        return $group->isMember($this);
1529    } /* }}} */
1530
1531    /**
1532     * Check if user has an image in its profile
1533     *
1534     * @return boolean true if user has a picture of itself
1535     */
1536    function hasImage() { /* {{{ */
1537        if (!isset($this->_hasImage)) {
1538            $db = $this->_dms->getDB();
1539
1540            $queryStr = "SELECT COUNT(*) AS num FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1541            $resArr = $db->getResultArray($queryStr);
1542            if ($resArr === false)
1543                return false;
1544
1545            if ($resArr[0]["num"] == 0)    $this->_hasImage = false;
1546            else $this->_hasImage = true;
1547        }
1548
1549        return $this->_hasImage;
1550    } /* }}} */
1551
1552    /**
1553     * Get the image from the users profile
1554     *
1555     * @return string|null|bool image data as a string or null if no image is set or
1556     * false in case of an error
1557     */
1558    function getImage() { /* {{{ */
1559        $db = $this->_dms->getDB();
1560
1561        $queryStr = "SELECT * FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1562        $resArr = $db->getResultArray($queryStr);
1563        if ($resArr === false)
1564            return false;
1565
1566        if($resArr)
1567            return $resArr[0];
1568        else
1569            return null;
1570    } /* }}} */
1571
1572    /**
1573     * @param $tmpfile
1574     * @param $mimeType
1575     * @return bool
1576     */
1577    function setImage($tmpfile, $mimeType) { /* {{{ */
1578        $db = $this->_dms->getDB();
1579
1580        $fp = fopen($tmpfile, "rb");
1581        if (!$fp) return false;
1582        $content = fread($fp, filesize($tmpfile));
1583        fclose($fp);
1584
1585        if ($this->hasImage())
1586            $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($content)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id;
1587        else
1588            $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($content)."', ".$db->qstr($mimeType).")";
1589        if (!$db->getResult($queryStr))
1590            return false;
1591
1592        $this->_hasImage = true;
1593        return true;
1594    } /* }}} */
1595
1596    /**
1597     * Returns all documents of a given user
1598     * @return SeedDMS_Core_Document[]|bool list of documents
1599     */
1600    function getDocuments() { /* {{{ */
1601        $db = $this->_dms->getDB();
1602
1603        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1604            "FROM `tblDocuments` ".
1605            "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ".
1606            "WHERE `tblDocuments`.`owner` = " . $this->_id . " ORDER BY `sequence`";
1607
1608        $resArr = $db->getResultArray($queryStr);
1609        if (is_bool($resArr) && !$resArr)
1610            return false;
1611
1612        $documents = array();
1613        $classname = $this->_dms->getClassname('document');
1614        foreach ($resArr as $row) {
1615            /** @var SeedDMS_Core_Document $document */
1616            $document = new $classname((int) $row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]);
1617            $document->setDMS($this->_dms);
1618            $documents[] = $document;
1619        }
1620        return $documents;
1621    } /* }}} */
1622
1623    /**
1624     * Returns all documents locked by a given user
1625     *
1626     * @return bool|SeedDMS_Core_Document[] list of documents
1627     */
1628    function getDocumentsLocked() { /* {{{ */
1629        $db = $this->_dms->getDB();
1630
1631        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1632            "FROM `tblDocumentLocks` LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` ".
1633            "WHERE `tblDocumentLocks`.`userID` = '".$this->_id."' ".
1634            "ORDER BY `id` DESC";
1635
1636        $resArr = $db->getResultArray($queryStr);
1637        if (is_bool($resArr) && !$resArr)
1638            return false;
1639
1640        $documents = array();
1641        $classname = $this->_dms->getClassname('document');
1642        foreach ($resArr as $row) {
1643            /** @var SeedDMS_Core_Document $document */
1644            $document = new $classname((int) $row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]);
1645            $document->setDMS($this->_dms);
1646            $documents[] = $document;
1647        }
1648        return $documents;
1649    } /* }}} */
1650
1651    /**
1652     * Returns all documents check out by a given user
1653     *
1654     * @param object $user
1655     * @return array list of documents
1656     */
1657    function getDocumentsCheckOut() { /* {{{ */
1658        $db = $this->_dms->getDB();
1659
1660        $queryStr = "SELECT `tblDocuments`.* ".
1661            "FROM `tblDocumentCheckOuts` LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentCheckOuts`.`document` ".
1662            "WHERE `tblDocumentCheckOuts`.`userID` = '".$this->_id."' ".
1663            "ORDER BY `id` ASC";
1664
1665        $resArr = $db->getResultArray($queryStr);
1666        if (is_bool($resArr) && !$resArr)
1667            return false;
1668
1669        $documents = array();
1670        $classname = $this->_dms->getClassname('document');
1671        foreach ($resArr as $row) {
1672            $document = new $classname($row["id"], $row["name"], $row["comment"], $row["date"], $row["expires"], $row["owner"], $row["folder"], $row["inheritAccess"], $row["defaultAccess"], $row["lockUser"], $row["keywords"], $row["sequence"]);
1673            $document->setDMS($this->_dms);
1674            $documents[] = $document;
1675        }
1676        return $documents;
1677    } /* }}} */
1678
1679    /**
1680     * Returns all document links of a given user
1681     * @return SeedDMS_Core_DocumentLink[]|bool list of document links
1682     */
1683    function getDocumentLinks() { /* {{{ */
1684        $db = $this->_dms->getDB();
1685
1686        $queryStr = "SELECT * FROM `tblDocumentLinks` ".
1687            "WHERE `userID` = " . $this->_id;
1688
1689        $resArr = $db->getResultArray($queryStr);
1690        if (is_bool($resArr) && !$resArr)
1691            return false;
1692
1693        $links = array();
1694        $classname = 'SeedDMS_Core_DocumentLink';
1695        foreach ($resArr as $row) {
1696            $document = $this->_dms->getDocument($row["document"]);
1697            $target = $this->_dms->getDocument($row["target"]);
1698            /** @var SeedDMS_Core_Document $document */
1699            $link = new $classname((int) $row["id"], $document, $target, $row["userID"], $row["public"]);
1700            $links[] = $link;
1701        }
1702        return $links;
1703    } /* }}} */
1704
1705    /**
1706     * Returns all document files of a given user
1707     * @return SeedDMS_Core_DocumentFile[]|bool list of document files
1708     */
1709    function getDocumentFiles() { /* {{{ */
1710        $db = $this->_dms->getDB();
1711
1712        $queryStr = "SELECT * FROM `tblDocumentFiles` ".
1713            "WHERE `userID` = " . $this->_id;
1714
1715        $resArr = $db->getResultArray($queryStr);
1716        if (is_bool($resArr) && !$resArr)
1717            return false;
1718
1719        $files = array();
1720        $classname = 'SeedDMS_Core_DocumentFile';
1721        foreach ($resArr as $row) {
1722            $document = $this->_dms->getDocument($row["document"]);
1723            /** @var SeedDMS_Core_DocumentFile $file */
1724            $file = new $classname((int) $row["id"], $document, $row["userID"], $row["comment"], $row["date"], $row["dir"], $row["fileType"], $row["mimeType"], $row["orgFileName"], $row["name"],$row["version"],$row["public"]);
1725            $files[] = $file;
1726        }
1727        return $files;
1728    } /* }}} */
1729
1730    /**
1731     * Returns all document contents of a given user
1732     * @return SeedDMS_Core_DocumentContent[]|bool list of document contents
1733     */
1734    function getDocumentContents() { /* {{{ */
1735        $db = $this->_dms->getDB();
1736
1737        $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `createdBy` = " . $this->_id;
1738
1739        $resArr = $db->getResultArray($queryStr);
1740        if (is_bool($resArr) && !$resArr)
1741            return false;
1742
1743        $contents = array();
1744        $classname = $this->_dms->getClassname('documentcontent');
1745        foreach ($resArr as $row) {
1746            $document = $this->_dms->getDocument($row["document"]);
1747            /** @var SeedDMS_Core_DocumentContent $content */
1748            $content = new $classname((int) $row["id"], $document, $row["version"], $row["comment"], $row["date"], $row["createdBy"], $row["dir"], $row["orgFileName"], $row["fileType"], $row["mimeType"], $row['fileSize'], $row['checksum']);
1749            $contents[] = $content;
1750        }
1751        return $contents;
1752    } /* }}} */
1753
1754    /**
1755     * Returns all folders of a given user
1756     * @return SeedDMS_Core_Folder[]|bool list of folders
1757     */
1758    function getFolders() { /* {{{ */
1759        $db = $this->_dms->getDB();
1760
1761        $queryStr = "SELECT * FROM `tblFolders` ".
1762            "WHERE `owner` = " . $this->_id . " ORDER BY `sequence`";
1763
1764        $resArr = $db->getResultArray($queryStr);
1765        if (is_bool($resArr) && !$resArr)
1766            return false;
1767
1768        $folders = array();
1769        $classname = $this->_dms->getClassname('folder');
1770        foreach ($resArr as $row) {
1771            /** @var SeedDMS_Core_Folder $folder */
1772            $folder = new $classname((int) $row["id"], $row["name"], $row['parent'], $row["comment"], $row["date"], $row["owner"], $row["inheritAccess"], $row["defaultAccess"], $row["sequence"]);
1773            $folder->setDMS($this->_dms);
1774            $folders[] = $folder;
1775        }
1776        return $folders;
1777    } /* }}} */
1778
1779    /**
1780     * Get a list of reviews
1781     *
1782     * This function returns a list of all reviews and their latest log entry
1783     * seperated by individuals and groups. If the document id
1784     * is passed, then only this document will be checked for reviews. The
1785     * same is true for the version of a document which limits the list
1786     * further. If you do not limit on a version it will retrieve the status
1787     * for each version, that includes even older versions which has been superseded
1788     * by a new version.
1789     *
1790     * For a detailed description of the result array see
1791     * {link SeedDMS_Core_User::getApprovalStatus} which does the same for
1792     * approvals.
1793     *
1794     * @param int $documentID optional document id for which to retrieve the
1795     *        reviews
1796     * @param int $version optional version of the document
1797     * @return array|bool list of all reviews
1798     */
1799    function getReviewStatus($documentID=null, $version=null) { /* {{{ */
1800        $db = $this->_dms->getDB();
1801
1802        if (!$db->createTemporaryTable("ttreviewid", true)) {
1803            return false;
1804        }
1805
1806        $status = array("indstatus"=>array(), "grpstatus"=>array());
1807
1808        // See if the user is assigned as an individual reviewer.
1809        // Attention: this method didn't use ttreviewid to filter out the latest
1810        // log entry. This was added 2021-09-29 because $group->getReviewStatus()
1811        // does it as well. The check below if the date is larger than the date
1812        // of a previos entry is still required to just take the latest version
1813        // of a document into account.
1814        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1815            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1816            "`tblDocumentReviewLog`.`userID` ".
1817            "FROM `tblDocumentReviewers` ".
1818            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1819            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1820            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1821            ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1822            ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1823            "AND `tblDocumentReviewers`.`type`='0' ".
1824            "AND `tblDocumentReviewers`.`required`='". $this->_id ."' ".
1825            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1826        $resArr = $db->getResultArray($queryStr);
1827        if (is_bool($resArr) && $resArr === false)
1828            return false;
1829        if (count($resArr)>0) {
1830            foreach ($resArr as $res) {
1831                if(isset($status["indstatus"][$res['documentID']])) {
1832                    if($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1833                        $status["indstatus"][$res['documentID']] = $res;
1834                    }
1835                } else {
1836                    $status["indstatus"][$res['documentID']] = $res;
1837                }
1838            }
1839        }
1840
1841        // See if the user is the member of a group that has been assigned to
1842        // review the document version.
1843        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1844            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1845            "`tblDocumentReviewLog`.`userID` ".
1846            "FROM `tblDocumentReviewers` ".
1847            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1848            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1849            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentReviewers`.`required` ".
1850            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1851            ($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1852            ($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1853            "AND `tblDocumentReviewers`.`type`='1' ".
1854            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1855            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1856        $resArr = $db->getResultArray($queryStr);
1857        if (is_bool($resArr) && $resArr === false)
1858            return false;
1859        if (count($resArr)>0) {
1860            foreach ($resArr as $res) {
1861                if(isset($status["grpstatus"][$res['documentID']])) {
1862                    if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1863                        $status["grpstatus"][$res['documentID']] = $res;
1864                    }
1865                } else {
1866                    $status["grpstatus"][$res['documentID']] = $res;
1867                }
1868            }
1869        }
1870        return $status;
1871    } /* }}} */
1872
1873    /**
1874     * Get a list of approvals
1875     *
1876     * This function returns a list of all approvals and their latest log entry
1877     * seperated by individuals and groups. If the document id
1878     * is passed, then only this document will be checked for approvals. The
1879     * same is true for the version of a document which limits the list
1880     * further. If you do not limit on a version it will retrieve the status
1881     * for each version, that includes even older versions which has been superseded
1882     * by a new version.
1883     *
1884     * The result array has two elements:
1885     * - indstatus: which contains the approvals by individuals (users)
1886     * - grpstatus: which contains the approvals by groups
1887     *
1888     * Each element is itself an array of approvals with the following elements
1889     * (it is a combination of fields from tblDocumentApprovers and tblDocumentApproveLog):
1890     * - approveID: unique id of approval
1891     * - documentID: id of document, that needs to be approved
1892     * - version: version of document, that needs to be approved
1893     * - type: 0 for individual approval, 1 for group approval
1894     * - required: id of user who is required to do the approval
1895     * - status: 0 not approved, ....
1896     * - comment: comment given during approval
1897     * - date: date of approval
1898     * - userID: id of user who has done the approval
1899     *
1900     * @param int $documentID optional document id for which to retrieve the
1901     *        approvals
1902     * @param int $version optional version of the document
1903     * @return array|bool list of all approvals
1904     */
1905    function getApprovalStatus($documentID=null, $version=null) { /* {{{ */
1906        $db = $this->_dms->getDB();
1907
1908        if (!$db->createTemporaryTable("ttapproveid")) {
1909            return false;
1910        }
1911
1912        $status = array("indstatus"=>array(), "grpstatus"=>array());
1913
1914        // See if the user is assigned as an individual approver.
1915        // Attention: this method didn't use ttapproveid to filter out the latest
1916        // log entry. This was added 2021-09-29 because $group->getApprovalStatus()
1917        // does it as well. The check below if the date is larger than the date
1918        // of a previos entry is still required to just take the latest version
1919        // of a document into account.
1920        $queryStr =
1921            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1922            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1923            "`tblDocumentApproveLog`.`userID` ".
1924            "FROM `tblDocumentApprovers` ".
1925            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1926            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1927            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1928            ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1929            ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1930            "AND `tblDocumentApprovers`.`type`='0' ".
1931            "AND `tblDocumentApprovers`.`required`='". $this->_id ."' ".
1932            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1933
1934        $resArr = $db->getResultArray($queryStr);
1935        if (is_bool($resArr) && $resArr == false)
1936            return false;
1937        if (count($resArr)>0) {
1938            foreach ($resArr as $res) {
1939                if(isset($status["indstatus"][$res['documentID']])) {
1940                    if($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1941                        $status["indstatus"][$res['documentID']] = $res;
1942                    }
1943                } else {
1944                    $status["indstatus"][$res['documentID']] = $res;
1945                }
1946            }
1947        }
1948
1949        // See if the user is the member of a group that has been assigned to
1950        // approve the document version.
1951        $queryStr =
1952            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1953            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1954            "`tblDocumentApproveLog`.`userID` ".
1955            "FROM `tblDocumentApprovers` ".
1956            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1957            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1958            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ".
1959            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1960            ($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1961            ($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1962            "AND `tblDocumentApprovers`.`type`='1' ".
1963            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1964            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1965        $resArr = $db->getResultArray($queryStr);
1966        if (is_bool($resArr) && $resArr == false)
1967            return false;
1968        if (count($resArr)>0) {
1969            foreach ($resArr as $res) {
1970                if(isset($status["grpstatus"][$res['documentID']])) {
1971                    if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1972                        $status["grpstatus"][$res['documentID']] = $res;
1973                    }
1974                } else {
1975                    $status["grpstatus"][$res['documentID']] = $res;
1976                }
1977            }
1978        }
1979        return $status;
1980    } /* }}} */
1981
1982    /**
1983     * Get a list of receipts
1984     * This function returns a list of all receipts seperated by individual
1985     * and group receipts. If the document id
1986     * is passed, then only this document will be checked for receipts. The
1987     * same is true for the version of a document which limits the list
1988     * further.
1989     *
1990     * For a detaile description of the result array see
1991     * {link SeedDMS_Core_User::getApprovalStatus} which does the same for
1992     * approvals.
1993     *
1994     * @param int $documentID optional document id for which to retrieve the
1995     *        receipt
1996     * @param int $version optional version of the document
1997     * @return array list of all receipts
1998     */
1999    function getReceiptStatus($documentID=null, $version=null) { /* {{{ */
2000        $db = $this->_dms->getDB();
2001
2002        $status = array("indstatus"=>array(), "grpstatus"=>array());
2003
2004        if (!$db->createTemporaryTable("ttcontentid")) {
2005            return false;
2006        }
2007        // See if the user is assigned as an individual recipient.
2008        // left join with ttcontentid to restrict result on latest version of document
2009        // unless a document and version is given
2010        $queryStr = "SELECT `tblDocumentRecipients`.*, `tblDocumentReceiptLog`.`status`, ".
2011            "`tblDocumentReceiptLog`.`comment`, `tblDocumentReceiptLog`.`date`, ".
2012            "`tblDocumentReceiptLog`.`userID` ".
2013            "FROM `tblDocumentRecipients` ".
2014            "LEFT JOIN `tblDocumentReceiptLog` USING (`receiptID`) ".
2015            "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentRecipients`.`version` AND `ttcontentid`.`document` = `tblDocumentRecipients`.`documentID` ".
2016            "WHERE `tblDocumentRecipients`.`type`='0' ".
2017            ($documentID==null ? "" : "AND `tblDocumentRecipients`.`documentID` = '". (int) $documentID ."' ").
2018            ($version==null ? "" : "AND `tblDocumentRecipients`.`version` = '". (int) $version ."' ").
2019            ($documentID==null && $version==null ? "AND `ttcontentid`.`maxVersion` = `tblDocumentRecipients`.`version` " : "").
2020            "AND `tblDocumentRecipients`.`required`='". $this->_id ."' ".
2021            "ORDER BY `tblDocumentReceiptLog`.`receiptLogID` DESC";
2022        $resArr = $db->getResultArray($queryStr);
2023        if (is_bool($resArr) && $resArr === false)
2024            return false;
2025        if (count($resArr)>0) {
2026            foreach ($resArr as $res) {
2027                if(isset($status["indstatus"][$res['documentID']])) {
2028                    if($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
2029                        $status["indstatus"][$res['documentID']] = $res;
2030                    }
2031                } else {
2032                    $status["indstatus"][$res['documentID']] = $res;
2033                }
2034            }
2035        }
2036
2037        // See if the user is the member of a group that has been assigned to
2038        // receipt the document version.
2039        $queryStr = "SELECT `tblDocumentRecipients`.*, `tblDocumentReceiptLog`.`status`, ".
2040            "`tblDocumentReceiptLog`.`comment`, `tblDocumentReceiptLog`.`date`, ".
2041            "`tblDocumentReceiptLog`.`userID` ".
2042            "FROM `tblDocumentRecipients` ".
2043            "LEFT JOIN `tblDocumentReceiptLog` USING (`receiptID`) ".
2044            "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentRecipients`.`version` AND `ttcontentid`.`document` = `tblDocumentRecipients`.`documentID` ".
2045            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentRecipients`.`required` ".
2046            "WHERE `tblDocumentRecipients`.`type`='1' ".
2047            ($documentID==null ? "" : "AND `tblDocumentRecipients`.`documentID` = '". (int) $documentID ."' ").
2048            ($version==null ? "" : "AND `tblDocumentRecipients`.`version` = '". (int) $version ."' ").
2049            ($documentID==null && $version==null ? "AND `ttcontentid`.`maxVersion` = `tblDocumentRecipients`.`version` " : "").
2050            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
2051            "ORDER BY `tblDocumentReceiptLog`.`receiptLogID` DESC";
2052        $resArr = $db->getResultArray($queryStr);
2053        if (is_bool($resArr) && $resArr === false)
2054            return false;
2055        if (count($resArr)>0) {
2056            foreach ($resArr as $res) {
2057                if(isset($status["grpstatus"][$res['documentID']])) {
2058                    if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
2059                        $status["grpstatus"][$res['documentID']] = $res;
2060                    }
2061                } else {
2062                    $status["grpstatus"][$res['documentID']] = $res;
2063                }
2064            }
2065        }
2066        return $status;
2067    } /* }}} */
2068
2069    /**
2070     * Get a list of revisions
2071     * This function returns a list of all revisions seperated by individual
2072     * and group revisions. If the document id
2073     * is passed, then only this document will be checked for revisions. The
2074     * same is true for the version of a document which limits the list
2075     * further.
2076     *
2077     * For a detaile description of the result array see
2078     * {link SeedDMS_Core_User::getApprovalStatus} which does the same for
2079     * approvals.
2080     *
2081     * @param int $documentID optional document id for which to retrieve the
2082     *        revisions
2083     * @param int $version optional version of the document
2084     * @return array list of all revisions. If the result array has no elements,
2085     * then the user was not a revisor. If there elements for 'indstatus' or
2086     * 'grpstatus' then the revision hasn't been started.
2087     */
2088    function getRevisionStatus($documentID=null, $version=null) { /* {{{ */
2089        $db = $this->_dms->getDB();
2090
2091        $status = array("indstatus"=>array(), "grpstatus"=>array());
2092
2093        if (!$db->createTemporaryTable("ttcontentid")) {
2094            return false;
2095        }
2096        // See if the user is assigned as an individual revisor.
2097        // left join with ttcontentid to restrict result on latest version of document
2098        // unless a document and version is given
2099        $queryStr = "SELECT `tblDocumentRevisors`.*, `tblDocumentRevisionLog`.`status`, ".
2100            "`tblDocumentRevisionLog`.`comment`, `tblDocumentRevisionLog`.`date`, ".
2101            "`tblDocumentRevisionLog`.`userID` ".
2102            "FROM `tblDocumentRevisors` ".
2103            "LEFT JOIN `tblDocumentRevisionLog` USING (`revisionID`) ".
2104            "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` AND `ttcontentid`.`document` = `tblDocumentRevisors`.`documentID` ".
2105            "WHERE `tblDocumentRevisors`.`type`='0' ".
2106            ($documentID==null ? "" : "AND `tblDocumentRevisors`.`documentID` = '". (int) $documentID ."' ").
2107            ($version==null ? "" : "AND `tblDocumentRevisors`.`version` = '". (int) $version ."' ").
2108            ($documentID==null && $version==null ? "AND `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` " : "").
2109            "AND `tblDocumentRevisors`.`required`='". $this->_id ."' ".
2110            "ORDER BY `tblDocumentRevisionLog`.`revisionLogID` DESC";
2111        $resArr = $db->getResultArray($queryStr);
2112        if ($resArr === false)
2113            return false;
2114        if (count($resArr)>0) {
2115            $status['indstatus'] = array();
2116            foreach ($resArr as $res) {
2117                if($res['date']) {
2118                    if(isset($status["indstatus"][$res['documentID']])) {
2119                        if($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
2120                            $status["indstatus"][$res['documentID']] = $res;
2121                        }
2122                    } else {
2123                        $status["indstatus"][$res['documentID']] = $res;
2124                    }
2125                }
2126            }
2127        }
2128
2129        // See if the user is the member of a group that has been assigned to
2130        // revision the document version.
2131        $queryStr = "SELECT `tblDocumentRevisors`.*, `tblDocumentRevisionLog`.`status`, ".
2132            "`tblDocumentRevisionLog`.`comment`, `tblDocumentRevisionLog`.`date`, ".
2133            "`tblDocumentRevisionLog`.`userID` ".
2134            "FROM `tblDocumentRevisors` ".
2135            "LEFT JOIN `tblDocumentRevisionLog` USING (`revisionID`) ".
2136            "LEFT JOIN `ttcontentid` ON `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` AND `ttcontentid`.`document` = `tblDocumentRevisors`.`documentID` ".
2137            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentRevisors`.`required` ".
2138            "WHERE `tblDocumentRevisors`.`type`='1' ".
2139            ($documentID==null ? "" : "AND `tblDocumentRevisors`.`documentID` = '". (int) $documentID ."' ").
2140            ($version==null ? "" : "AND `tblDocumentRevisors`.`version` = '". (int) $version ."' ").
2141            ($documentID==null && $version==null ? "AND `ttcontentid`.`maxVersion` = `tblDocumentRevisors`.`version` " : "").
2142            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
2143            "ORDER BY `tblDocumentRevisionLog`.`revisionLogID` DESC";
2144        $resArr = $db->getResultArray($queryStr);
2145        if (is_bool($resArr) && $resArr === false)
2146            return false;
2147        if (count($resArr)>0) {
2148            foreach ($resArr as $res) {
2149                if(isset($status["grpstatus"][$res['documentID']])) {
2150                    if($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
2151                        $status["grpstatus"][$res['documentID']] = $res;
2152                    }
2153                } else {
2154                    $status["grpstatus"][$res['documentID']] = $res;
2155                }
2156            }
2157        }
2158        return $status;
2159    } /* }}} */
2160
2161    /**
2162     * Get a list of documents with a workflow
2163     *
2164     * @param int $documentID optional document id for which to retrieve the
2165     *        reviews
2166     * @param int $version optional version of the document
2167     * @return array|bool list of all workflows
2168     */
2169    function getWorkflowStatus($documentID=null, $version=null) { /* {{{ */
2170        $db = $this->_dms->getDB();
2171
2172        $queryStr = 'SELECT DISTINCT d.*, c.`userid` FROM `tblWorkflowTransitions` a LEFT JOIN `tblWorkflows` b ON a.`workflow`=b.`id` LEFT JOIN `tblWorkflowTransitionUsers` c ON a.`id`=c.`transition` LEFT JOIN `tblWorkflowDocumentContent` d ON b.`id`=d.`workflow` WHERE d.`document` IS NOT NULL AND a.`state`=d.`state` AND c.`userid`='.$this->_id;
2173        if($documentID) {
2174            $queryStr .= ' AND d.`document`='.(int) $documentID;
2175            if($version)
2176                $queryStr .= ' AND d.`version`='.(int) $version;
2177        }
2178        $resArr = $db->getResultArray($queryStr);
2179        if (is_bool($resArr) && $resArr == false)
2180            return false;
2181        $result['u'] = array();
2182        if (count($resArr)>0) {
2183            foreach ($resArr as $res) {
2184                $result['u'][] = $res;
2185            }
2186        }
2187
2188        $queryStr = 'select distinct d.*, c.`groupid` from `tblWorkflowTransitions` a left join `tblWorkflows` b on a.`workflow`=b.`id` left join `tblWorkflowTransitionGroups` c on a.`id`=c.`transition` left join `tblWorkflowDocumentContent` d on b.`id`=d.`workflow` left join `tblGroupMembers` e on c.`groupid` = e.`groupID` where d.`document` is not null and a.`state`=d.`state` and e.`userID`='.$this->_id;
2189        if($documentID) {
2190            $queryStr .= ' AND d.`document`='.(int) $documentID;
2191            if($version)
2192                $queryStr .= ' AND d.`version`='.(int) $version;
2193        }
2194        $resArr = $db->getResultArray($queryStr);
2195        if (is_bool($resArr) && $resArr == false)
2196            return false;
2197        $result['g'] = array();
2198        if (count($resArr)>0) {
2199            foreach ($resArr as $res) {
2200                $result['g'][] = $res;
2201            }
2202        }
2203        return $result;
2204    } /* }}} */
2205
2206    /**
2207     * Get a list of workflows this user is involved as in individual
2208     *
2209     * @return array|bool list of all workflows
2210     */
2211    function getWorkflowsInvolved() { /* {{{ */
2212        $db = $this->_dms->getDB();
2213
2214        $queryStr = 'SELECT DISTINCT b.*, c.`userid` FROM `tblWorkflowTransitions` a LEFT JOIN `tblWorkflows` b ON a.`workflow`=b.`id` LEFT JOIN `tblWorkflowTransitionUsers` c ON a.`id`=c.`transition` WHERE c.`userid`='.$this->_id;
2215        $resArr = $db->getResultArray($queryStr);
2216        if (is_bool($resArr) && $resArr == false)
2217            return false;
2218        $result = array();
2219        if (count($resArr)>0) {
2220            foreach ($resArr as $res) {
2221                $result[] = $this->_dms->getWorkflow((int) $res['id']);
2222            }
2223        }
2224
2225        return $result;
2226    } /* }}} */
2227
2228    /**
2229     * Get a list of mandatory reviewers
2230     * A user which isn't trusted completely may have assigned mandatory
2231     * reviewers (both users and groups).
2232     * Whenever the user inserts a new document the mandatory reviewers are
2233     * filled in as reviewers.
2234     *
2235     * @return array list of arrays with two elements containing the user id
2236     *         (reviewerUserID) and group id (reviewerGroupID) of the reviewer.
2237     */
2238    function getMandatoryReviewers() { /* {{{ */
2239        $db = $this->_dms->getDB();
2240
2241        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
2242        $resArr = $db->getResultArray($queryStr);
2243
2244        return $resArr;
2245    } /* }}} */
2246
2247    /**
2248     * Get a list of mandatory approvers
2249     * See {link SeedDMS_Core_User::getMandatoryReviewers}
2250     *
2251     * @return array list of arrays with two elements containing the user id
2252     *         (approverUserID) and group id (approverGroupID) of the approver.
2253     */
2254    function getMandatoryApprovers() { /* {{{ */
2255        $db = $this->_dms->getDB();
2256
2257        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
2258        $resArr = $db->getResultArray($queryStr);
2259
2260        return $resArr;
2261    } /* }}} */
2262
2263    /**
2264     * Get a list of users this user is a mandatory reviewer of
2265     *
2266     * This method is the reverse function of getMandatoryReviewers(). It returns
2267     * those user where the current user is a mandatory reviewer.
2268     *
2269     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory reviewer.
2270     */
2271    function isMandatoryReviewerOf() { /* {{{ */
2272        $db = $this->_dms->getDB();
2273
2274        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id;
2275        $resArr = $db->getResultArray($queryStr);
2276        if (is_bool($resArr) && !$resArr) return false;
2277
2278        $users = array();
2279        foreach($resArr as $res) {
2280            $users[] = self::getInstance($res['userID'], $this->_dms);
2281        }
2282
2283        return $users;
2284    } /* }}} */
2285
2286    /**
2287     * Get a list of users this user is a mandatory approver of
2288     *
2289     * This method is the reverse function of getMandatoryApprovers(). It returns
2290     * those user where the current user is a mandatory approver.
2291     *
2292     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory approver.
2293     */
2294    function isMandatoryApproverOf() { /* {{{ */
2295        $db = $this->_dms->getDB();
2296
2297        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id;
2298        $resArr = $db->getResultArray($queryStr);
2299        if (is_bool($resArr) && !$resArr) return false;
2300
2301        $users = array();
2302        foreach($resArr as $res) {
2303            $users[] = self::getInstance($res['userID'], $this->_dms);
2304        }
2305
2306        return $users;
2307    } /* }}} */
2308
2309    /**
2310     * Get the mandatory workflow
2311     * A user which isn't trusted completely may have assigned mandatory
2312     * workflow
2313     * Whenever the user inserts a new document the mandatory workflow is
2314     * filled in as the workflow.
2315     *
2316     * @return SeedDMS_Core_Workflow|bool workflow
2317     */
2318    function getMandatoryWorkflow() { /* {{{ */
2319        $db = $this->_dms->getDB();
2320
2321        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2322        $resArr = $db->getResultArray($queryStr);
2323        if (is_bool($resArr) && !$resArr) return false;
2324
2325        if(!$resArr)
2326            return null;
2327
2328        $workflow = $this->_dms->getWorkflow($resArr[0]['workflow']);
2329        return $workflow;
2330    } /* }}} */
2331
2332    /**
2333     * Get the mandatory workflows
2334     * A user which isn't trusted completely may have assigned mandatory
2335     * workflow
2336     * Whenever the user inserts a new document the mandatory workflow is
2337     * filled in as the workflow.
2338     *
2339     * @return SeedDMS_Core_Workflow[]|bool workflow
2340     */
2341    function getMandatoryWorkflows() { /* {{{ */
2342        $db = $this->_dms->getDB();
2343
2344        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2345        $resArr = $db->getResultArray($queryStr);
2346        if (is_bool($resArr) && !$resArr) return false;
2347
2348        if(!$resArr)
2349            return null;
2350
2351        $workflows = array();
2352        foreach($resArr as $res) {
2353            $workflows[] = $this->_dms->getWorkflow($res['workflow']);
2354        }
2355        return $workflows;
2356    } /* }}} */
2357
2358    /**
2359     * Set a mandatory reviewer
2360     * This function sets a mandatory reviewer if it isn't already set.
2361     *
2362     * @param integer $id id of reviewer
2363     * @param boolean $isgroup true if $id is a group
2364     * @return boolean true on success, otherwise false
2365     */
2366    function setMandatoryReviewer($id, $isgroup=false) { /* {{{ */
2367        $db = $this->_dms->getDB();
2368        $id = (int) $id;
2369
2370        if ($isgroup){
2371
2372            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerGroupID` = " . $id;
2373            $resArr = $db->getResultArray($queryStr);
2374            if (count($resArr)!=0) return true;
2375
2376            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerGroupID`) VALUES (" . $this->_id . ", " . $id .")";
2377            $resArr = $db->getResult($queryStr);
2378            if (is_bool($resArr) && !$resArr) return false;
2379
2380        }else{
2381
2382            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerUserID` = " . $id;
2383            $resArr = $db->getResultArray($queryStr);
2384            if (count($resArr)!=0) return true;
2385
2386            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerUserID`) VALUES (" . $this->_id . ", " . $id .")";
2387            $resArr = $db->getResult($queryStr);
2388            if (is_bool($resArr) && !$resArr) return false;
2389        }
2390
2391        return true;
2392    } /* }}} */
2393
2394    /**
2395     * Set a mandatory approver
2396     * This function sets a mandatory approver if it isn't already set.
2397     *
2398     * @param integer $id id of approver
2399     * @param boolean $isgroup true if $id is a group
2400     * @return boolean true on success, otherwise false
2401     */
2402    function setMandatoryApprover($id, $isgroup=false) { /* {{{ */
2403        $db = $this->_dms->getDB();
2404        $id = (int) $id;
2405
2406        if ($isgroup){
2407
2408            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverGroupID` = " . $id;
2409            $resArr = $db->getResultArray($queryStr);
2410            if (count($resArr)!=0) return true;
2411
2412            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverGroupID`) VALUES (" . $this->_id . ", " . $id .")";
2413            $resArr = $db->getResult($queryStr);
2414            if (is_bool($resArr) && !$resArr) return false;
2415
2416        }else{
2417
2418            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverUserID` = " . $id;
2419            $resArr = $db->getResultArray($queryStr);
2420            if (count($resArr)!=0) return true;
2421
2422            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverUserID`) VALUES (" . $this->_id . ", " . $id .")";
2423            $resArr = $db->getResult($queryStr);
2424            if (is_bool($resArr) && !$resArr) return false;
2425        }
2426
2427        return true;
2428    } /* }}} */
2429
2430    /**
2431     * Set a mandatory workflow
2432     * This function sets a mandatory workflow if it isn't already set.
2433     *
2434     * @param object $workflow workflow
2435     * @return boolean true on success, otherwise false
2436     */
2437    function setMandatoryWorkflow($workflow) { /* {{{ */
2438        $db = $this->_dms->getDB();
2439
2440        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id . " AND `workflow` = " . (int) $workflow->getID();
2441        $resArr = $db->getResultArray($queryStr);
2442        if (count($resArr)!=0) return true;
2443
2444        $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
2445        $resArr = $db->getResult($queryStr);
2446        if (is_bool($resArr) && !$resArr) return false;
2447
2448        return true;
2449    } /* }}} */
2450
2451    /**
2452     * Set a mandatory workflows
2453     * This function sets a list of mandatory workflows.
2454     *
2455     * @param SeedDMS_Core_Workflow[] $workflows list of workflow objects
2456     * @return boolean true on success, otherwise false
2457     */
2458    function setMandatoryWorkflows($workflows) { /* {{{ */
2459        $db = $this->_dms->getDB();
2460
2461        $db->startTransaction();
2462        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2463        if (!$db->getResult($queryStr)) {
2464            $db->rollbackTransaction();
2465            return false;
2466        }
2467
2468        foreach($workflows as $workflow) {
2469            $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
2470            $resArr = $db->getResult($queryStr);
2471            if (is_bool($resArr) && !$resArr) {
2472                $db->rollbackTransaction();
2473                return false;
2474            }
2475        }
2476
2477        $db->commitTransaction();
2478        return true;
2479    } /* }}} */
2480
2481    /**
2482     * Deletes all mandatory reviewers
2483     *
2484     * @return boolean true on success, otherwise false
2485     */
2486    function delMandatoryReviewers() { /* {{{ */
2487        $db = $this->_dms->getDB();
2488        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
2489        if (!$db->getResult($queryStr)) return false;
2490        return true;
2491    } /* }}} */
2492
2493    /**
2494     * Deletes all mandatory approvers
2495     *
2496     * @return boolean true on success, otherwise false
2497     */
2498    function delMandatoryApprovers() { /* {{{ */
2499        $db = $this->_dms->getDB();
2500
2501        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
2502        if (!$db->getResult($queryStr)) return false;
2503        return true;
2504    } /* }}} */
2505
2506    /**
2507     * Deletes the  mandatory workflow
2508     *
2509     * @return boolean true on success, otherwise false
2510     */
2511    function delMandatoryWorkflow() { /* {{{ */
2512        $db = $this->_dms->getDB();
2513        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2514        if (!$db->getResult($queryStr)) return false;
2515        return true;
2516    } /* }}} */
2517
2518    /**
2519     * Get all substitutes of the user
2520     *
2521     * These users are substitutes of the current user
2522     *
2523     * @return array list of users
2524     */
2525    function getSubstitutes() { /* {{{ */
2526        $db = $this->_dms->getDB();
2527
2528        if (!isset($this->_substitutes)) {
2529            $queryStr = "SELECT `tblUsers`.* FROM `tblUserSubstitutes` ".
2530                "LEFT JOIN `tblUsers` ON `tblUserSubstitutes`.`substitute` = `tblUsers`.`id` ".
2531                "WHERE `tblUserSubstitutes`.`user`='". $this->_id ."'";
2532            $resArr = $db->getResultArray($queryStr);
2533            if (is_bool($resArr) && $resArr == false)
2534                return false;
2535
2536            $this->_substitutes = array();
2537            $classname = $this->_dms->getClassname('user');
2538            foreach ($resArr as $row) {
2539                $user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row["hidden"], $row["disabled"], $row["pwdExpiration"], $row["loginfailures"], $row["quota"], $row["homefolder"]);
2540                $user->setDMS($this->_dms);
2541                array_push($this->_substitutes, $user);
2542            }
2543        }
2544        return $this->_substitutes;
2545    } /* }}} */
2546
2547    /**
2548     * Get all users this user is a substitute of
2549     *
2550     * @return array list of users
2551     */
2552    function getReverseSubstitutes() { /* {{{ */
2553        $db = $this->_dms->getDB();
2554
2555        if (!isset($this->_rev_substitutes)) {
2556            $queryStr = "SELECT `tblUsers`.* FROM `tblUserSubstitutes` ".
2557                "LEFT JOIN `tblUsers` ON `tblUserSubstitutes`.`user` = `tblUsers`.`id` ".
2558                "LEFT JOIN `tblRoles` ON `tblRoles`.`id`=`tblUsers`.`role` ".
2559                "WHERE `tblUserSubstitutes`.`substitute`='". $this->_id ."'";
2560            /* None admins can only be substitutes for regular users, otherwise
2561             * regular users can become admin
2562             */
2563            if(!$this->isAdmin())
2564                $queryStr .= " AND `tblRoles`.`role` = ".SeedDMS_Core_User::role_user;
2565            $resArr = $db->getResultArray($queryStr);
2566            if (is_bool($resArr) && $resArr == false)
2567                return false;
2568
2569            $this->_rev_substitutes = array();
2570            $classnamerole = $this->_dms->getClassname('role');
2571            $classname = $this->_dms->getClassname('user');
2572            foreach ($resArr as $row) {
2573                $role = $classnamerole::getInstance($row['role'], $this->_dms);
2574                $user = new $classname($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $role, $row["hidden"], $row["disabled"], $row["pwdExpiration"], $row["loginfailures"], $row["quota"], $row["homefolder"]);
2575                $user->setDMS($this->_dms);
2576                array_push($this->_rev_substitutes, $user);
2577            }
2578        }
2579        return $this->_rev_substitutes;
2580    } /* }}} */
2581
2582    /**
2583     * Add a substitute to the user
2584     *
2585     * @return boolean true if successful otherwise false
2586     */
2587    function addSubstitute($substitute) { /* {{{ */
2588        $db = $this->_dms->getDB();
2589
2590        if(get_class($substitute) != $this->_dms->getClassname('user'))
2591            return false;
2592
2593        $queryStr = "SELECT * FROM `tblUserSubstitutes` WHERE `user`=" . $this->_id . " AND `substitute`=".$substitute->getID();
2594        $resArr = $db->getResultArray($queryStr);
2595        if (is_bool($resArr) && $resArr == false) return false;
2596        if (count($resArr) == 1) return true;
2597
2598        $queryStr = "INSERT INTO `tblUserSubstitutes` (`user`, `substitute`) VALUES (" . $this->_id . ", ".$substitute->getID().")";
2599        if (!$db->getResult($queryStr))
2600            return false;
2601
2602        $this->_substitutes = null;
2603        return true;
2604    } /* }}} */
2605
2606    /**
2607     * Remove a substitute from the user
2608     *
2609     * @return boolean true if successful otherwise false
2610     */
2611    function removeSubstitute($substitute) { /* {{{ */
2612        $db = $this->_dms->getDB();
2613
2614        if(get_class($substitute) != $this->_dms->getClassname('user'))
2615            return false;
2616
2617        $queryStr = "SELECT * FROM `tblUserSubstitutes` WHERE `user`=" . $this->_id . " AND `substitute`=".$substitute->getID();
2618        $resArr = $db->getResultArray($queryStr);
2619        if (is_bool($resArr) && $resArr == false) return false;
2620        if (count($resArr) == 0) return true;
2621
2622        $queryStr = "DELETE FROM `tblUserSubstitutes` WHERE `user`=" . $this->_id . " AND `substitute`=".$substitute->getID();
2623        if (!$db->getResult($queryStr))
2624            return false;
2625
2626        $this->_substitutes = null;
2627        return true;
2628    } /* }}} */
2629
2630    /**
2631     * Check if user is a substitute of the current user
2632     *
2633     * @return boolean true if successful otherwise false
2634     */
2635    function isSubstitute($substitute) { /* {{{ */
2636        $db = $this->_dms->getDB();
2637
2638        if(get_class($substitute) != $this->_dms->getClassname('user'))
2639            return false;
2640
2641        $queryStr = "SELECT * FROM `tblUserSubstitutes` WHERE `user`=" . $this->_id . " AND `substitute`=".$substitute->getID();
2642        $resArr = $db->getResultArray($queryStr);
2643        if (is_bool($resArr) && $resArr == false) return false;
2644        if (count($resArr) == 1) return true;
2645
2646        return false;
2647    } /* }}} */
2648
2649    /**
2650     * Check if user may switch to the given user
2651     *
2652     * Switching to the given user is only allowed if the given user
2653     * is a substitute for the current user.
2654     *
2655     * @return boolean true if successful otherwise false
2656     */
2657    function maySwitchToUser($touser) { /* {{{ */
2658        $db = $this->_dms->getDB();
2659
2660        if(get_class($touser) != $this->_dms->getClassname('user'))
2661            return false;
2662
2663        /* switching to an admin account is always forbitten, unless the
2664         * current user is admin itself
2665         */
2666        if(!$this->isAdmin() && $touser->isAdmin())
2667            return false;
2668
2669        $queryStr = "SELECT * FROM `tblUserSubstitutes` WHERE `substitute`=" . $this->_id . " AND `user`=".$touser->getID();
2670        $resArr = $db->getResultArray($queryStr);
2671        if (is_bool($resArr) && $resArr == false) return false;
2672        if (count($resArr) == 1) return true;
2673
2674        return false;
2675    } /* }}} */
2676
2677    /**
2678     * Get all notifications of user
2679     *
2680     * @param integer $type type of item (T_DOCUMENT or T_FOLDER)
2681     * @return SeedDMS_Core_Notification[]|bool array of notifications
2682     */
2683    function getNotifications($type=0) { /* {{{ */
2684        $db = $this->_dms->getDB();
2685        $queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ".
2686         "WHERE `tblNotify`.`userID` = ". $this->_id;
2687        if($type) {
2688            $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type;
2689        }
2690
2691        $resArr = $db->getResultArray($queryStr);
2692        if (is_bool($resArr) && !$resArr)
2693            return false;
2694
2695        $notifications = array();
2696        foreach ($resArr as $row) {
2697            $not = new SeedDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]);
2698            $not->setDMS($this);
2699            array_push($notifications, $not);
2700        }
2701
2702        return $notifications;
2703    } /* }}} */
2704
2705    /**
2706     * Return list of personal keyword categories
2707     *
2708     * @return SeedDMS_Core_KeywordCategory[]|bool list of categories or false in case of an error
2709     */
2710    function getKeywordCategories() { /* {{{ */
2711        $db = $this->_dms->getDB();
2712
2713        $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `owner` = ".$this->_id;
2714
2715        $resArr = $db->getResultArray($queryStr);
2716        if (is_bool($resArr) && !$resArr)
2717            return false;
2718
2719        $categories = array();
2720        foreach ($resArr as $row) {
2721            $cat = new SeedDMS_Core_KeywordCategory((int) $row["id"], $row["owner"], $row["name"]);
2722            $cat->setDMS($this->_dms);
2723            array_push($categories, $cat);
2724        }
2725
2726        return $categories;
2727    } /* }}} */
2728
2729} /* }}} */