Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.96% covered (warning)
75.96%
616 / 811
65.85% covered (warning)
65.85%
54 / 82
CRAP
0.00% covered (danger)
0.00%
0 / 1
SeedDMS_Core_User
75.96% covered (warning)
75.96%
616 / 811
65.85% covered (warning)
65.85%
54 / 82
1833.64
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
1
 getInstance
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
8
 getAllInstances
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
7
 __toString
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 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
 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
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 isAdmin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAdmin
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 isGuest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setGuest
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 isUser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 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
18.52% covered (danger)
18.52%
10 / 54
0.00% covered (danger)
0.00%
0 / 1
861.82
 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
 setImageBlob
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 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
 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
81.25% covered (warning)
81.25%
39 / 48
0.00% covered (danger)
0.00%
0 / 1
20.14
 getApprovalStatus
82.00% covered (warning)
82.00%
41 / 50
0.00% covered (danger)
0.00%
0 / 1
19.89
 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
 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-2024 Uwe Steinmann
14 * @version    Release: @package_version@
15 */
16
17/**
18 * Class to represent a user in the document management system
19 *
20 * @category   DMS
21 * @package    SeedDMS_Core
22 * @author     Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
23 * @copyright  Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
24 *             2010-2024 Uwe Steinmann
25 * @version    Release: @package_version@
26 */
27class SeedDMS_Core_User { /* {{{ */
28    /**
29     * @var integer id of user
30     *
31     * @access protected
32     */
33    protected $_id;
34
35    /**
36     * @var string login name of user
37     *
38     * @access protected
39     */
40    protected $_login;
41
42    /**
43     * @var string password of user as saved in database (md5)
44     *
45     * @access protected
46     */
47    protected $_pwd;
48
49    /**
50     * @var string date when password expires
51     *
52     * @access protected
53     */
54    protected $_pwdExpiration;
55
56    /**
57     * @var string full human readable name of user
58     *
59     * @access protected
60     */
61    protected $_fullName;
62
63    /**
64     * @var string email address of user
65     *
66     * @access protected
67     */
68    protected $_email;
69
70    /**
71     * @var string prefered language of user
72     *      possible values are subdirectories within the language directory
73     *
74     * @access protected
75     */
76    protected $_language;
77
78    /**
79     * @var string preselected theme of user
80     *
81     * @access protected
82     */
83    protected $_theme;
84
85    /**
86     * @var string comment of user
87     *
88     * @access protected
89     */
90    protected $_comment;
91
92    /**
93     * @var string role of user. Can be one of SeedDMS_Core_User::role_user,
94     *      SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest
95     *
96     * @access protected
97     */
98    protected $_role;
99
100    /**
101     * @var boolean true if user shall be hidden
102     *
103     * @access protected
104     */
105    protected $_isHidden;
106
107    /**
108     * @var boolean true if user is disabled
109     *
110     * @access protected
111     */
112    protected $_isDisabled;
113
114    /**
115     * @var int number of login failures
116     *
117     * @access protected
118     */
119    protected $_loginFailures;
120
121    /**
122     * @var SeedDMS_Core_Folder home folder
123     *
124     * @access protected
125     */
126    protected $_homeFolder;
127
128    /**
129     * @var array list of groups
130     *
131     * @access protected
132     */
133    protected $_groups;
134
135    /**
136     * @var SeedDMS_Core_DMS reference to the dms instance this user belongs to
137     *
138     * @access protected
139     */
140    protected $_dms;
141
142    /**
143     * @var int
144     *
145     * @access protected
146     */
147    protected $_quota;
148
149    /**
150     * @var bool
151     *
152     * @access protected
153     */
154    protected $_hasImage;
155
156    const role_user = '0';
157    const role_admin = '1';
158    const role_guest = '2';
159
160    /**
161     * SeedDMS_Core_User constructor.
162     * @param $id
163     * @param $login
164     * @param $pwd
165     * @param $fullName
166     * @param $email
167     * @param $language
168     * @param $theme
169     * @param $comment
170     * @param $role
171     * @param int $isHidden
172     * @param int $isDisabled
173     * @param string $pwdExpiration
174     * @param int $loginFailures
175     * @param int $quota
176     * @param null $homeFolder
177     */
178    public function __construct($id, $login, $pwd, $fullName, $email, $language, $theme, $comment, $role, $isHidden = 0, $isDisabled = 0, $pwdExpiration = '', $loginFailures = 0, $quota = 0, $homeFolder = null) {
179        $this->_id = $id;
180        $this->_login = $login;
181        $this->_pwd = $pwd;
182        $this->_fullName = $fullName;
183        $this->_email = $email;
184        $this->_language = $language;
185        $this->_theme = $theme;
186        $this->_comment = $comment;
187        $this->_role = $role;
188        $this->_isHidden = (bool) $isHidden;
189        $this->_isDisabled = (bool) $isDisabled;
190        $this->_pwdExpiration = $pwdExpiration;
191        $this->_loginFailures = $loginFailures;
192        $this->_quota = $quota;
193        $this->_homeFolder = $homeFolder;
194        $this->_dms = null;
195    }
196
197    /**
198     * Create an instance of a user object
199     *
200     * @param string|integer $id Id, login name, or email of user, depending
201     * on the 3rd parameter.
202     * @param SeedDMS_Core_DMS $dms instance of dms
203     * @param string $by search by [name|email]. If 'name' is passed, the method
204     * will check for the 4th paramater and also filter by email. If this
205     * parameter is left empty, the user will be search by its Id.
206     * @param string $email optional email address if searching for name
207     * @return SeedDMS_Core_User|bool instance of class SeedDMS_Core_User if user was
208     * found, null if user was not found, false in case of error
209     */
210    public static function getInstance($id, $dms, $by = '', $email = '') { /* {{{ */
211        $db = $dms->getDB();
212
213        switch ($by) {
214            case 'name':
215                $queryStr = "SELECT * FROM `tblUsers` WHERE `login` = ".$db->qstr((string) $id);
216                if ($email)
217                    $queryStr .= " AND `email`=".$db->qstr($email);
218                break;
219            case 'email':
220                $queryStr = "SELECT * FROM `tblUsers` WHERE `email` = ".$db->qstr((string) $id);
221                break;
222            default:
223                $queryStr = "SELECT * FROM `tblUsers` WHERE `id` = " . (int) $id;
224        }
225        $resArr = $db->getResultArray($queryStr);
226
227        if (is_bool($resArr) && $resArr == false) return false;
228        if (count($resArr) != 1) return null;
229
230        $resArr = $resArr[0];
231
232        $user = new self((int) $resArr["id"], $resArr["login"], $resArr["pwd"], $resArr["fullName"], $resArr["email"], $resArr["language"], $resArr["theme"], $resArr["comment"], $resArr["role"], $resArr["hidden"], $resArr["disabled"], $resArr["pwdExpiration"], $resArr["loginfailures"], (int) $resArr["quota"], $resArr["homefolder"]);
233        $user->setDMS($dms);
234        return $user;
235    } /* }}} */
236
237    /**
238     * Return all users
239     *
240     * @param $orderby can be `fullname`
241     * @param SeedDMS_Core_DMS $dms
242     * @return SeedDMS_Core_User[]|bool
243     */
244    public static function getAllInstances($orderby, $dms) { /* {{{ */
245        $db = $dms->getDB();
246
247        if ($orderby == 'fullname') {
248            $queryStr = "SELECT * FROM `tblUsers` ORDER BY `fullName`";
249        } else {
250            $queryStr = "SELECT * FROM `tblUsers` ORDER BY `login`";
251        }
252        $resArr = $db->getResultArray($queryStr);
253
254        if (is_bool($resArr) && $resArr == false) {
255            return false;
256        }
257
258        $users = array();
259
260        for ($i = 0; $i < count($resArr); $i++) {
261            /** @var SeedDMS_Core_User $user */
262            $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"], $resArr[$i]["role"], $resArr[$i]["hidden"], $resArr[$i]["disabled"], $resArr[$i]["pwdExpiration"], $resArr[$i]["loginfailures"], (int) $resArr[$i]["quota"], $resArr[$i]["homefolder"]);
263            $user->setDMS($dms);
264            $users[$i] = $user;
265        }
266
267        return $users;
268    } /* }}} */
269
270    /**
271     * Cast to string
272     *
273     * @return string
274     */
275    public function __toString() { /* {{{ */
276        return $this->_fullName." (".$this->_login.")";
277    } /* }}} */
278
279    /**
280     * Check if this object is of type 'user'.
281     *
282     * @param string $type type of object
283     */
284    public function isType($type) { /* {{{ */
285        return $type == 'user';
286    } /* }}} */
287
288    /**
289     * @param SeedDMS_Core_DMS $dms
290     */
291    public function setDMS($dms) {
292        $this->_dms = $dms;
293    }
294
295    /**
296     * @return SeedDMS_Core_DMS $dms
297     */
298    public function getDMS() {
299        return $this->_dms;
300    }
301
302    /**
303     * Return internal id of user
304     *
305     * @return int
306     */
307    public function getID() { return $this->_id; }
308
309    /**
310     * Return login of user
311     *
312     * @return string
313     */
314    public function getLogin() { return $this->_login; }
315
316    /**
317     * Change login of user
318     *
319     * @param $newLogin new login
320     * @return bool
321     */
322    public function setLogin($newLogin) { /* {{{ */
323        $newLogin = trim($newLogin);
324        if (!$newLogin)
325            return false;
326
327        $db = $this->_dms->getDB();
328
329        $queryStr = "UPDATE `tblUsers` SET `login` =".$db->qstr($newLogin)." WHERE `id` = " . $this->_id;
330        $res = $db->getResult($queryStr);
331        if (!$res)
332            return false;
333
334        $this->_login = $newLogin;
335        return true;
336    } /* }}} */
337
338    /**
339     * Return full name of user
340     *
341     * @return string
342     */
343    public function getFullName() { return $this->_fullName; }
344
345    /**
346     * Set full name of user
347     *
348     * @param $newFullName
349     * @return bool
350     */
351    public function setFullName($newFullName) { /* {{{ */
352        $db = $this->_dms->getDB();
353
354        $queryStr = "UPDATE `tblUsers` SET `fullName` = ".$db->qstr($newFullName)." WHERE `id` = " . $this->_id;
355        $res = $db->getResult($queryStr);
356        if (!$res)
357            return false;
358
359        $this->_fullName = $newFullName;
360        return true;
361    } /* }}} */
362
363    /**
364     * Get encrypted password of user
365     *
366     * @return string
367     */
368    public function getPwd() { return $this->_pwd; }
369
370    /**
371     * Set password of user
372     *
373     * The password must be encrypted before calling this method.
374     *
375     * @param $newPwd new encrypted password
376     * @return bool
377     */
378    public function setPwd($newPwd) { /* {{{ */
379        $db = $this->_dms->getDB();
380
381        $queryStr = "UPDATE `tblUsers` SET `pwd` =".$db->qstr($newPwd)." WHERE `id` = " . $this->_id;
382        $res = $db->getResult($queryStr);
383        if (!$res)
384            return false;
385
386        $this->_pwd = $newPwd;
387        return true;
388    } /* }}} */
389
390    /**
391     * @return string
392     */
393    public function getPwdExpiration() { return $this->_pwdExpiration; }
394
395    /**
396     * @param $newPwdExpiration
397     * @return bool
398     */
399    public function setPwdExpiration($newPwdExpiration) { /* {{{ */
400        $db = $this->_dms->getDB();
401
402        if (trim($newPwdExpiration) == '' || trim($newPwdExpiration) == 'never') {
403            $newPwdExpiration = null;
404            $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` = NULL WHERE `id` = " . $this->_id;
405        } else {
406            if (trim($newPwdExpiration) == 'now')
407                $newPwdExpiration = date('Y-m-d H:i:s');
408            $queryStr = "UPDATE `tblUsers` SET `pwdExpiration` =".$db->qstr($newPwdExpiration)." WHERE `id` = " . $this->_id;
409        }
410        $res = $db->getResult($queryStr);
411        if (!$res)
412            return false;
413
414        $this->_pwdExpiration = $newPwdExpiration;
415        return true;
416    } /* }}} */
417
418    /**
419     * Get email address of user
420     *
421     * @return string
422     */
423    public function getEmail() { return $this->_email; }
424
425    /**
426     * Change email address of user
427     *
428     * @param $newEmail new email address
429     * @return bool
430     */
431    public function setEmail($newEmail) { /* {{{ */
432        $db = $this->_dms->getDB();
433
434        $queryStr = "UPDATE `tblUsers` SET `email` =".$db->qstr(trim($newEmail))." WHERE `id` = " . $this->_id;
435        $res = $db->getResult($queryStr);
436        if (!$res)
437            return false;
438
439        $this->_email = $newEmail;
440        return true;
441    } /* }}} */
442
443    /**
444     * @return string
445     */
446    public function getLanguage() { return $this->_language; }
447
448    /**
449     * @param $newLanguage
450     * @return bool
451     */
452    public function setLanguage($newLanguage) { /* {{{ */
453        $db = $this->_dms->getDB();
454
455        $queryStr = "UPDATE `tblUsers` SET `language` =".$db->qstr(trim($newLanguage))." WHERE `id` = " . $this->_id;
456        $res = $db->getResult($queryStr);
457        if (!$res)
458            return false;
459
460        $this->_language = $newLanguage;
461        return true;
462    } /* }}} */
463
464    /**
465     * @return string
466     */
467    public function getTheme() { return $this->_theme; }
468
469    /**
470     * @param string $newTheme
471     * @return bool
472     */
473    public function setTheme($newTheme) { /* {{{ */
474        $db = $this->_dms->getDB();
475
476        $queryStr = "UPDATE `tblUsers` SET `theme` =".$db->qstr(trim($newTheme))." WHERE `id` = " . $this->_id;
477        $res = $db->getResult($queryStr);
478        if (!$res)
479            return false;
480
481        $this->_theme = $newTheme;
482        return true;
483    } /* }}} */
484
485    /**
486     * Return comment of user
487     *
488     * @return string
489     */
490    public function getComment() { return $this->_comment; }
491
492    /**
493     * Change comment of user
494     *
495     * @param $newComment new comment
496     * @return bool
497     */
498    public function setComment($newComment) { /* {{{ */
499        $db = $this->_dms->getDB();
500
501        $queryStr = "UPDATE `tblUsers` SET `comment` =".$db->qstr(trim($newComment))." WHERE `id` = " . $this->_id;
502        $res = $db->getResult($queryStr);
503        if (!$res)
504            return false;
505
506        $this->_comment = $newComment;
507        return true;
508    } /* }}} */
509
510    /**
511     * @return string
512     */
513    public function getRole() { return $this->_role; }
514
515    /**
516     * @param integer $newrole
517     * @return bool
518     */
519    public function setRole($newrole) { /* {{{ */
520        $db = $this->_dms->getDB();
521        if (!in_array($newrole, array(SeedDMS_Core_User::role_admin, SeedDMS_Core_User::role_guest, SeedDMS_Core_User::role_user), true))
522            return false;
523
524        $queryStr = "UPDATE `tblUsers` SET `role` = " . $newrole . " WHERE `id` = " . $this->_id;
525        if (!$db->getResult($queryStr))
526            return false;
527
528        $this->_role = $newrole;
529        return true;
530    } /* }}} */
531
532    /**
533     * Check, if user is an administrator
534     *
535     * @return bool
536     */
537    public function isAdmin() { return ($this->_role == SeedDMS_Core_User::role_admin); }
538
539    /**
540     * Turn user into a admin
541     *
542     * @return bool
543     */
544    public function setAdmin() { /* {{{ */
545        $db = $this->_dms->getDB();
546
547        $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_admin . " WHERE `id` = " . $this->_id;
548        if (!$db->getResult($queryStr))
549            return false;
550
551        $this->_role = SeedDMS_Core_User::role_admin;
552        return true;
553    } /* }}} */
554
555    /**
556     * Check, if user is a guest
557     *
558     * @return bool
559     */
560    public function isGuest() { return ($this->_role == SeedDMS_Core_User::role_guest); }
561
562    /**
563     * Turn user into a guest
564     *
565     * @return bool
566     */
567    public function setGuest() { /* {{{ */
568        $db = $this->_dms->getDB();
569
570        $queryStr = "UPDATE `tblUsers` SET `role` = " . SeedDMS_Core_User::role_guest . " WHERE `id` = " . $this->_id;
571        if (!$db->getResult($queryStr))
572            return false;
573
574        $this->_role = SeedDMS_Core_User::role_guest;
575        return true;
576    } /* }}} */
577
578    /**
579     * Check, if user is a regular user
580     *
581     * @return bool
582     */
583    public function isUser() { return ($this->_role == SeedDMS_Core_User::role_user); }
584
585    /**
586     * Check, if user is hidden
587     *
588     * @return bool
589     */
590    public function isHidden() { return $this->_isHidden; }
591
592    /**
593     * Set user hidden
594     *
595     * @param $isHidden
596     * @return bool
597     */
598    public function setHidden($isHidden) { /* {{{ */
599        $db = $this->_dms->getDB();
600
601        $isHidden = ($isHidden) ? "1" : "0";
602        $queryStr = "UPDATE `tblUsers` SET `hidden` = " . intval($isHidden) . " WHERE `id` = " . $this->_id;
603        if (!$db->getResult($queryStr))
604            return false;
605
606        $this->_isHidden = (bool) $isHidden;
607        return true;
608    }     /* }}} */
609
610    /**
611     * Check, if user is disabled
612     *
613     * @return bool|int
614     */
615    public function isDisabled() { return $this->_isDisabled; }
616
617    /**
618     * Disable user
619     *
620     * @param $isDisabled
621     * @return bool
622     */
623    public function setDisabled($isDisabled) { /* {{{ */
624        $db = $this->_dms->getDB();
625
626        $isDisabled = ($isDisabled) ? "1" : "0";
627        $queryStr = "UPDATE `tblUsers` SET `disabled` = " . intval($isDisabled) . " WHERE `id` = " . $this->_id;
628        if (!$db->getResult($queryStr))
629            return false;
630
631        $this->_isDisabled = (bool) $isDisabled;
632        return true;
633    }     /* }}} */
634
635    /**
636     * @return bool|int
637     */
638    public function addLoginFailure() { /* {{{ */
639        $db = $this->_dms->getDB();
640
641        $this->_loginFailures++;
642        $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id;
643        if (!$db->getResult($queryStr))
644            return false;
645
646        return $this->_loginFailures;
647    } /* }}} */
648
649    /**
650     * @return bool
651     */
652    public function clearLoginFailures() { /* {{{ */
653        $db = $this->_dms->getDB();
654
655        $this->_loginFailures = 0;
656        $queryStr = "UPDATE `tblUsers` SET `loginfailures` = " . $this->_loginFailures . " WHERE `id` = " . $this->_id;
657        if (!$db->getResult($queryStr))
658            return false;
659
660        return true;
661    } /* }}} */
662
663    /**
664     * Calculate the disk space for all documents owned by the user
665     *
666     * This is done by using the internal database field storing the
667     * filesize of a document version.
668     *
669     * @return integer total disk space in Bytes
670     */
671    public function getUsedDiskSpace() { /* {{{ */
672        $db = $this->_dms->getDB();
673
674        $queryStr = "SELECT SUM(`fileSize`) sum FROM `tblDocumentContent` a LEFT JOIN `tblDocuments` b ON a.`document`=b.`id` WHERE b.`owner` = " . $this->_id;
675        $resArr = $db->getResultArray($queryStr);
676        if (is_bool($resArr) && $resArr == false)
677            return false;
678
679        return (int) $resArr[0]['sum'];
680    } /* }}} */
681
682    /**
683     * @return int
684     */
685    public function getQuota() { return $this->_quota; }
686
687    /**
688     * @param integer $quota
689     * @return bool
690     */
691    public function setQuota($quota) { /* {{{ */
692        if (!is_numeric($quota))
693            return false;
694        if ($quota < 0)
695            return false;
696
697        $db = $this->_dms->getDB();
698
699        $quota = intval($quota);
700        $queryStr = "UPDATE `tblUsers` SET `quota` = " . $quota . " WHERE `id` = " . $this->_id;
701        if (!$db->getResult($queryStr))
702            return false;
703
704        $this->_quota = (int) $quota;
705        return true;
706    }     /* }}} */
707
708    /**
709     * @return null|SeedDMS_Core_Folder
710     */
711    public function getHomeFolder() { return $this->_homeFolder; }
712
713    /**
714     * @param integer $homefolder
715     * @return bool
716     */
717    public function setHomeFolder($homefolder) { /* {{{ */
718        $db = $this->_dms->getDB();
719        $homefolder = intval($homefolder);
720
721        $queryStr = "UPDATE `tblUsers` SET `homefolder` = " . ($homefolder ? $homefolder : 'NULL') . " WHERE `id` = " . $this->_id;
722        if (!$db->getResult($queryStr))
723            return false;
724
725        $this->_homeFolder = $homefolder;
726        return true;
727    }     /* }}} */
728
729    /**
730     * Remove user from all processes
731     *
732     * This method adds another log entry to the reviews and approvals
733     * which indicates the user has been deleted from the process. By default it will
734     * do so for each review/approval regardless of its current state unles
735     * the user has been removed already (status=-2). So even
736     * reviews/approvals already processed by the user will be added the log
737     * entry. Only, if the last log entry was a removal already, it will not be
738     * added a second time.
739     *
740     * This removal from processes will also take place for older versions of a document.
741     *
742     * This methode was initialy added to remove a user (which is going to be deleted
743     * afterwards) from all processes he or she is still involved in.
744     *
745     * If a new user is passed, then this user will be added as a new reviewer, approver, etc.
746     * Hence, this method does not replace the old user but actually deletes the old user and
747     * adds a new one. Adding the new reviewer, approver, etc. will also be done for old versions
748     * of a document. The same operation could be archieved by first calling
749     * SeedDMS_Core_DocumentVersion::delIndReviewer() followed by SeedDMS_Core_DocumentVersion::addIndReviewer()
750     * but this would require to do for each version of a document and the operation would not
751     * be in a single transaction.
752     *
753     * A new user is only added if the process (review, approval, etc.) is still in its initial
754     * state (have not been reviewed/approved or rejected). Unlike the removal of the user (see above).
755     *
756     * If a new user is given but has no read access on the document the transfer for that
757     * particular document will be skipped. Not even the removal of the user will take place.
758     *
759     * @param object $user the user doing the removal (needed for entry in
760     *        review and approve log).
761     * @param array $states remove user only from reviews/approvals in one of the states
762     *        e.g. if passing array('review'=>array(0)), the method will operate on
763     *        reviews which has not been touched yet.
764     * @param object $newuser user who takes over the processes
765     * @param array $docs remove only processes from docs with the given document ids
766     * @return boolean true on success or false in case of an error
767     */
768    private function __removeFromProcesses($user, $states = array(), $newuser = null, $docs = null) { /* {{{ */
769        $db = $this->_dms->getDB();
770
771        /* Get a list of all reviews, even those of older document versions */
772        $reviewStatus = $this->getReviewStatus();
773        $db->startTransaction();
774        foreach ($reviewStatus["indstatus"] as $ri) {
775            if (!($doc = $this->_dms->getDocument($ri['documentID'])))
776                continue;
777            if ($docs) {
778                if (!in_array($doc->getID(), $docs))
779                    continue;
780                if (!$doc->isLatestContent($ri['version']))
781                    continue;
782            }
783            if ($newuser && $doc->getAccessMode($newuser) < M_READ)
784                continue;
785            if ($ri['status'] != -2 && (!isset($states['review']) || in_array($ri['status'], $states['review']))) {
786                $queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
787                    "VALUES ('". $ri["reviewID"] ."', '-2', '".(($newuser && $ri['status'] == 0) ? 'Reviewer replaced by '.$newuser->getLogin() : 'Reviewer removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
788                $res = $db->getResult($queryStr);
789                if (!$res) {
790                    $db->rollbackTransaction();
791                    return false;
792                }
793                /* Only reviews not done already can be transferred to a new user */
794                if ($newuser && $ri['status'] == 0) {
795                    if ($version = $doc->getContentByVersion($ri['version'])) {
796                        $ret = $version->addIndReviewer($newuser, $user);
797                        /* returns -3 if the user is already a reviewer */
798                        if ($ret === false || ($ret < 0 && $ret != -3)) {
799                            $db->rollbackTransaction();
800                            return false;
801                        }
802                    }
803                }
804            }
805        }
806        $db->commitTransaction();
807
808        /* Get a list of all approvals, even those of older document versions */
809        $approvalStatus = $this->getApprovalStatus();
810        $db->startTransaction();
811        foreach ($approvalStatus["indstatus"] as $ai) {
812            if (!($doc = $this->_dms->getDocument($ai['documentID'])))
813                continue;
814            if ($docs) {
815                if (!in_array($doc->getID(), $docs))
816                    continue;
817                if (!$doc->isLatestContent($ai['version']))
818                    continue;
819            }
820            if ($newuser && $doc->getAccessMode($newuser) < M_READ)
821                continue;
822            if ($ai['status'] != -2 && (!isset($states['approval']) || in_array($ai['status'], $states['approval']))) {
823                $queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
824                    "VALUES ('". $ai["approveID"] ."', '-2', '".(($newuser && $ai['status'] == 0)? 'Approver replaced by '.$newuser->getLogin() : 'Approver removed from process')."', ".$db->getCurrentDatetime().", '". $user->getID() ."')";
825                $res = $db->getResult($queryStr);
826                if (!$res) {
827                    $db->rollbackTransaction();
828                    return false;
829                }
830                /* Only approvals not done already can be transferred to a new user */
831                if ($newuser && $ai['status'] == 0) {
832                    if ($version = $doc->getContentByVersion($ai['version'])) {
833                        $ret = $version->addIndReviewer($newuser, $user);
834                        /* returns -3 if the user is already a reviewer */
835                        if ($ret === false || ($ret < 0 && $ret != -3)) {
836                            $db->rollbackTransaction();
837                            return false;
838                        }
839                    }
840                }
841            }
842        }
843        $db->commitTransaction();
844
845        return true;
846    } /* }}} */
847
848    /**
849     * Remove user from all processes
850     *
851     * This includes review, approval and workflow
852     *
853     * @param object $user the user doing the removal (needed for entry in
854     *        review and approve log).
855     * @param array $states remove user only from reviews/approvals in one of the states
856     * @param object $newuser user who takes over the processes
857     * @return boolean true on success or false in case of an error
858     */
859    public function removeFromProcesses($user, $states = array(), $newuser = null, $docs = null) { /* {{{ */
860        $db = $this->_dms->getDB();
861
862        $db->startTransaction();
863        if (!$this->__removeFromProcesses($user, $states, $newuser, $docs)) {
864            $db->rollbackTransaction();
865            return false;
866        }
867        $db->commitTransaction();
868        return true;
869    } /* }}} */
870
871    /**
872     * Transfer documents and folders to another user
873     *
874     * @param object $assignToUser the user who is new owner of folders and
875     *        documents which previously were owned by the delete user.
876     * @return boolean true on success or false in case of an error
877     */
878    private function __transferDocumentsFolders($assignToUser) { /* {{{ */
879        $db = $this->_dms->getDB();
880
881        if (!$assignToUser)
882            return false;
883
884        /* Assign documents of the removed user to the given user */
885        $queryStr = "UPDATE `tblFolders` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id;
886        if (!$db->getResult($queryStr)) {
887            return false;
888        }
889
890        $queryStr = "UPDATE `tblDocuments` SET `owner` = " . $assignToUser->getID() . " WHERE `owner` = " . $this->_id;
891        if (!$db->getResult($queryStr)) {
892            return false;
893        }
894
895        $queryStr = "UPDATE `tblDocumentContent` SET `createdBy` = " . $assignToUser->getID() . " WHERE `createdBy` = " . $this->_id;
896        if (!$db->getResult($queryStr)) {
897            return false;
898        }
899
900        // ... but keep public links
901        $queryStr = "UPDATE `tblDocumentLinks` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
902        if (!$db->getResult($queryStr)) {
903            return false;
904        }
905
906        // set administrator for deleted user's attachments
907        $queryStr = "UPDATE `tblDocumentFiles` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
908        if (!$db->getResult($queryStr)) {
909            return false;
910        }
911
912        return true;
913    } /* }}} */
914
915    /**
916     * Transfer documents and folders to another user
917     *
918     * @param object $assignToUser the user who is new owner of folders and
919     *        documents which previously were owned by the delete user.
920     * @return boolean true on success or false in case of an error
921     */
922    public function transferDocumentsFolders($assignToUser) { /* {{{ */
923        $db = $this->_dms->getDB();
924
925        if ($assignToUser->getID() == $this->_id)
926            return true;
927
928        $db->startTransaction();
929        if (!$this->__transferDocumentsFolders($assignToUser)) {
930            $db->rollbackTransaction();
931            return false;
932        }
933        $db->commitTransaction();
934        return true;
935    } /* }}} */
936
937    /**
938     * Transfer events to another user
939     *
940     * @param object $assignToUser the user who is new owner of events
941     * @return boolean true on success or false in case of an error
942     */
943    private function __transferEvents($assignToUser) { /* {{{ */
944        $db = $this->_dms->getDB();
945
946        if (!$assignToUser)
947            return false;
948
949        // set new owner of events
950        $queryStr = "UPDATE `tblEvents` SET `userID` = " . $assignToUser->getID() . " WHERE `userID` = " . $this->_id;
951        if (!$db->getResult($queryStr)) {
952            return false;
953        }
954
955        return true;
956    } /* }}} */
957
958    /**
959     * Transfer events to another user
960     *
961     * @param object $assignToUser the user who is new owner of events
962     * @return boolean true on success or false in case of an error
963     */
964    public function transferEvents($assignToUser) { /* {{{ */
965        $db = $this->_dms->getDB();
966
967        if ($assignToUser->getID() == $this->_id)
968            return true;
969
970        $db->startTransaction();
971        if (!$this->__transferEvents($assignToUser)) {
972            $db->rollbackTransaction();
973            return false;
974        }
975        $db->commitTransaction();
976        return true;
977    } /* }}} */
978
979    /**
980     * Remove the user and also remove all its keywords, notifications, etc.
981     * Do not remove folders and documents of the user, but assign them
982     * to a different user.
983     *
984     * @param SeedDMS_Core_User $user the user doing the removal (needed for entry in
985     *        review and approve log).
986     * @param SeedDMS_Core_User $assignToUser the user who is new owner of folders and
987     *        documents which previously were owned by the delete user.
988     * @return boolean true on success or false in case of an error
989     */
990    public function remove($user, $assignToUser = null) { /* {{{ */
991        $db = $this->_dms->getDB();
992
993        /* Records like folders and documents that formely have belonged to
994         * the user will assign to another user. If no such user is set,
995         * the function now returns false and will not use the admin user
996         * anymore.
997         */
998        if (!$assignToUser)
999            return false;
1000            /** @noinspection PhpUnusedLocalVariableInspection */
1001            $assignTo = $assignToUser->getID();
1002
1003        $db->startTransaction();
1004
1005        // delete private keyword lists
1006        $queryStr = "SELECT `tblKeywords`.`id` FROM `tblKeywords`, `tblKeywordCategories` WHERE `tblKeywords`.`category` = `tblKeywordCategories`.`id` AND `tblKeywordCategories`.`owner` = " . $this->_id;
1007        $resultArr = $db->getResultArray($queryStr);
1008        if (count($resultArr) > 0) {
1009            $queryStr = "DELETE FROM `tblKeywords` WHERE ";
1010            for ($i = 0; $i < count($resultArr); $i++) {
1011                $queryStr .= "id = " . $resultArr[$i]["id"];
1012                if ($i + 1 < count($resultArr))
1013                    $queryStr .= " OR ";
1014            }
1015            if (!$db->getResult($queryStr)) {
1016                $db->rollbackTransaction();
1017                return false;
1018            }
1019        }
1020
1021        $queryStr = "DELETE FROM `tblKeywordCategories` WHERE `owner` = " . $this->_id;
1022        if (!$db->getResult($queryStr)) {
1023            $db->rollbackTransaction();
1024            return false;
1025        }
1026
1027        //Benachrichtigungen entfernen
1028        $queryStr = "DELETE FROM `tblNotify` WHERE `userID` = " . $this->_id;
1029        if (!$db->getResult($queryStr)) {
1030            $db->rollbackTransaction();
1031            return false;
1032        }
1033
1034        // Remove private links on documents ...
1035        $queryStr = "DELETE FROM `tblDocumentLinks` WHERE `userID` = " . $this->_id . " AND `public` = 0";
1036        if (!$db->getResult($queryStr)) {
1037            $db->rollbackTransaction();
1038            return false;
1039        }
1040
1041        /* Assign documents, folders, files, public document links of the removed user to the given user */
1042        if (!$this->__transferDocumentsFolders($assignToUser)) {
1043                $db->rollbackTransaction();
1044                return false;
1045        }
1046
1047        // unlock documents locked by the user
1048        $queryStr = "DELETE FROM `tblDocumentLocks` WHERE `userID` = " . $this->_id;
1049        if (!$db->getResult($queryStr)) {
1050            $db->rollbackTransaction();
1051            return false;
1052        }
1053
1054        // Delete user from all groups
1055        $queryStr = "DELETE FROM `tblGroupMembers` WHERE `userID` = " . $this->_id;
1056        if (!$db->getResult($queryStr)) {
1057            $db->rollbackTransaction();
1058            return false;
1059        }
1060
1061        // User aus allen ACLs streichen
1062        $queryStr = "DELETE FROM `tblACLs` WHERE `userID` = " . $this->_id;
1063        if (!$db->getResult($queryStr)) {
1064            $db->rollbackTransaction();
1065            return false;
1066        }
1067
1068        // Delete image of user
1069        $queryStr = "DELETE FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1070        if (!$db->getResult($queryStr)) {
1071            $db->rollbackTransaction();
1072            return false;
1073        }
1074
1075        // Delete entries in password history
1076        $queryStr = "DELETE FROM `tblUserPasswordHistory` WHERE `userID` = " . $this->_id;
1077        if (!$db->getResult($queryStr)) {
1078            $db->rollbackTransaction();
1079            return false;
1080        }
1081
1082        // Delete entries in password request
1083        $queryStr = "DELETE FROM `tblUserPasswordRequest` WHERE `userID` = " . $this->_id;
1084        if (!$db->getResult($queryStr)) {
1085            $db->rollbackTransaction();
1086            return false;
1087        }
1088
1089        // mandatory review/approve
1090        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id;
1091        if (!$db->getResult($queryStr)) {
1092            $db->rollbackTransaction();
1093            return false;
1094        }
1095
1096        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id;
1097        if (!$db->getResult($queryStr)) {
1098            $db->rollbackTransaction();
1099            return false;
1100        }
1101
1102        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
1103        if (!$db->getResult($queryStr)) {
1104            $db->rollbackTransaction();
1105            return false;
1106        }
1107
1108        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
1109        if (!$db->getResult($queryStr)) {
1110            $db->rollbackTransaction();
1111            return false;
1112        }
1113
1114        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1115        if (!$db->getResult($queryStr)) {
1116            $db->rollbackTransaction();
1117            return false;
1118        }
1119
1120        $queryStr = "DELETE FROM `tblWorkflowTransitionUsers` WHERE `userid` = " . $this->_id;
1121        if (!$db->getResult($queryStr)) {
1122            $db->rollbackTransaction();
1123            return false;
1124        }
1125
1126        /* Assign events of the removed user to the given user */
1127        if (!$this->__transferEvents($assignToUser)) {
1128                $db->rollbackTransaction();
1129                return false;
1130        }
1131
1132        // Delete user itself
1133        $queryStr = "DELETE FROM `tblUsers` WHERE `id` = " . $this->_id;
1134        if (!$db->getResult($queryStr)) {
1135            $db->rollbackTransaction();
1136            return false;
1137        }
1138
1139        // TODO : update document status if reviewer/approver has been deleted
1140        // "DELETE FROM `tblDocumentApproveLog` WHERE `userID` = " . $this->_id;
1141        // "DELETE FROM `tblDocumentReviewLog` WHERE `userID` = " . $this->_id;
1142
1143        if (!$this->__removeFromProcesses($user)) {
1144                $db->rollbackTransaction();
1145                return false;
1146        }
1147
1148        $db->commitTransaction();
1149        return true;
1150    } /* }}} */
1151
1152    /**
1153     * Make the user a member of a group
1154     * This function uses {@link SeedDMS_Group::addUser} but checks before if
1155     * the user is already a member of the group.
1156     *
1157     * @param SeedDMS_Core_Group $group group to be the member of
1158     * @return boolean true on success or false in case of an error or the user
1159     *        is already a member of the group
1160     */
1161    public function joinGroup($group) { /* {{{ */
1162        if ($group->isMember($this))
1163            return false;
1164
1165        if (!$group->addUser($this))
1166            return false;
1167
1168        unset($this->_groups);
1169        return true;
1170    } /* }}} */
1171
1172    /**
1173     * Removes the user from a group
1174     * This function uses {@link SeedDMS_Group::removeUser} but checks before if
1175     * the user is a member of the group at all.
1176     *
1177     * @param SeedDMS_Core_Group $group group to leave
1178     * @return boolean true on success or false in case of an error or the user
1179     *        is not a member of the group
1180     */
1181    public function leaveGroup($group) { /* {{{ */
1182        if (!$group->isMember($this))
1183            return false;
1184
1185        if (!$group->removeUser($this))
1186            return false;
1187
1188        unset($this->_groups);
1189        return true;
1190    } /* }}} */
1191
1192    /**
1193     * Get all groups the user is a member of
1194     *
1195     * @return SeedDMS_Core_Group[]|bool list of groups
1196     */
1197    public function getGroups() { /* {{{ */
1198        $db = $this->_dms->getDB();
1199
1200        if (!isset($this->_groups)) {
1201            $queryStr = "SELECT `tblGroups`.*, `tblGroupMembers`.`userID` FROM `tblGroups` ".
1202                "LEFT JOIN `tblGroupMembers` ON `tblGroups`.`id` = `tblGroupMembers`.`groupID` ".
1203                "WHERE `tblGroupMembers`.`userID`='". $this->_id ."'";
1204            $resArr = $db->getResultArray($queryStr);
1205            if (is_bool($resArr) && $resArr == false)
1206                return false;
1207
1208            $this->_groups = array();
1209            $classname = $this->_dms->getClassname('group');
1210            foreach ($resArr as $row) {
1211                /** @var SeedDMS_Core_Group $group */
1212                $group = new $classname((int) $row["id"], $row["name"], $row["comment"]);
1213                $group->setDMS($this->_dms);
1214                array_push($this->_groups, $group);
1215            }
1216        }
1217        return $this->_groups;
1218    } /* }}} */
1219
1220    /**
1221     * Checks if user is member of a given group
1222     *
1223     * @param SeedDMS_Core_Group $group
1224     * @return boolean true if user is member of the given group otherwise false
1225     */
1226    public function isMemberOfGroup($group) { /* {{{ */
1227        return $group->isMember($this);
1228    } /* }}} */
1229
1230    /**
1231     * Check if user has an image in its profile
1232     *
1233     * @return boolean true if user has a picture of itself
1234     */
1235    public function hasImage() { /* {{{ */
1236        if (!isset($this->_hasImage)) {
1237            $db = $this->_dms->getDB();
1238
1239            $queryStr = "SELECT COUNT(*) AS num FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1240            $resArr = $db->getResultArray($queryStr);
1241            if ($resArr === false)
1242                return false;
1243
1244            if ($resArr[0]["num"] == 0)    $this->_hasImage = false;
1245            else $this->_hasImage = true;
1246        }
1247
1248        return $this->_hasImage;
1249    } /* }}} */
1250
1251    /**
1252     * Get the image from the users profile
1253     *
1254     * @return string|null|bool image data as a string or null if no image is set or
1255     * false in case of an error
1256     */
1257    public function getImage() { /* {{{ */
1258        $db = $this->_dms->getDB();
1259
1260        $queryStr = "SELECT * FROM `tblUserImages` WHERE `userID` = " . $this->_id;
1261        $resArr = $db->getResultArray($queryStr);
1262        if ($resArr === false)
1263            return false;
1264
1265        if ($resArr)
1266            return $resArr[0];
1267        else
1268            return null;
1269    } /* }}} */
1270
1271    /**
1272     * @param string $tmpfile
1273     * @param string $mimeType
1274     * @return bool
1275     */
1276    public function setImage($tmpfile, $mimeType) { /* {{{ */
1277        $db = $this->_dms->getDB();
1278
1279        $fp = fopen($tmpfile, "rb");
1280        if (!$fp) return false;
1281        $content = fread($fp, filesize($tmpfile));
1282        fclose($fp);
1283
1284        if ($this->hasImage()) {
1285            $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($content)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id;
1286        } else {
1287            $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($content)."', ".$db->qstr($mimeType).")";
1288        }
1289        if (!$db->getResult($queryStr)) {
1290            return false;
1291        }
1292
1293        $this->_hasImage = true;
1294        return true;
1295    } /* }}} */
1296
1297    /**
1298     * @param string $imagedata
1299     * @param string $mimeType
1300     * @return bool
1301     */
1302    public function setImageBlob($imagedata, $mimeType) { /* {{{ */
1303        $db = $this->_dms->getDB();
1304
1305        if ($this->hasImage()) {
1306            $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($imagedata)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id;
1307        } else {
1308            $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($imagedata)."', ".$db->qstr($mimeType).")";
1309        }
1310        if (!$db->getResult($queryStr)) {
1311            return false;
1312        }
1313
1314        $this->_hasImage = true;
1315        return true;
1316    } /* }}} */
1317
1318    /**
1319     * Returns all documents of a given user
1320     * @return SeedDMS_Core_Document[]|bool list of documents
1321     */
1322    public function getDocuments() { /* {{{ */
1323        $db = $this->_dms->getDB();
1324
1325        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1326            "FROM `tblDocuments` ".
1327            "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ".
1328            "WHERE `tblDocuments`.`owner` = " . $this->_id . " ORDER BY `sequence`";
1329
1330        $resArr = $db->getResultArray($queryStr);
1331        if (is_bool($resArr) && !$resArr)
1332            return false;
1333
1334        $documents = array();
1335        $classname = $this->_dms->getClassname('document');
1336        foreach ($resArr as $row) {
1337            /** @var SeedDMS_Core_Document $document */
1338            $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"]);
1339            $document->setDMS($this->_dms);
1340            $documents[] = $document;
1341        }
1342        return $documents;
1343    } /* }}} */
1344
1345    /**
1346     * Returns all documents locked by a given user
1347     *
1348     * @return bool|SeedDMS_Core_Document[] list of documents
1349     */
1350    public function getDocumentsLocked() { /* {{{ */
1351        $db = $this->_dms->getDB();
1352
1353        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1354            "FROM `tblDocumentLocks` LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` ".
1355            "WHERE `tblDocumentLocks`.`userID` = '".$this->_id."' ".
1356            "ORDER BY `id` DESC";
1357
1358        $resArr = $db->getResultArray($queryStr);
1359        if (is_bool($resArr) && !$resArr)
1360            return false;
1361
1362        $documents = array();
1363        $classname = $this->_dms->getClassname('document');
1364        foreach ($resArr as $row) {
1365            /** @var SeedDMS_Core_Document $document */
1366            $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"]);
1367            $document->setDMS($this->_dms);
1368            $documents[] = $document;
1369        }
1370        return $documents;
1371    } /* }}} */
1372
1373    /**
1374     * Returns all document links of a given user
1375     * @return SeedDMS_Core_DocumentLink[]|bool list of document links
1376     */
1377    public function getDocumentLinks() { /* {{{ */
1378        $db = $this->_dms->getDB();
1379
1380        $queryStr = "SELECT * FROM `tblDocumentLinks` ".
1381            "WHERE `userID` = " . $this->_id;
1382
1383        $resArr = $db->getResultArray($queryStr);
1384        if (is_bool($resArr) && !$resArr)
1385            return false;
1386
1387        $links = array();
1388        $classname = 'SeedDMS_Core_DocumentLink';
1389        foreach ($resArr as $row) {
1390            $document = $this->_dms->getDocument($row["document"]);
1391            $target = $this->_dms->getDocument($row["target"]);
1392            /** @var SeedDMS_Core_Document $document */
1393            $link = new $classname((int) $row["id"], $document, $target, $row["userID"], $row["public"]);
1394            $links[] = $link;
1395        }
1396        return $links;
1397    } /* }}} */
1398
1399    /**
1400     * Returns all document files of a given user
1401     * @return SeedDMS_Core_DocumentFile[]|bool list of document files
1402     */
1403    public function getDocumentFiles() { /* {{{ */
1404        $db = $this->_dms->getDB();
1405
1406        $queryStr = "SELECT * FROM `tblDocumentFiles` ".
1407            "WHERE `userID` = " . $this->_id;
1408
1409        $resArr = $db->getResultArray($queryStr);
1410        if (is_bool($resArr) && !$resArr)
1411            return false;
1412
1413        $files = array();
1414        $classname = 'SeedDMS_Core_DocumentFile';
1415        foreach ($resArr as $row) {
1416            $document = $this->_dms->getDocument($row["document"]);
1417            /** @var SeedDMS_Core_DocumentFile $file */
1418            $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"]);
1419            $files[] = $file;
1420        }
1421        return $files;
1422    } /* }}} */
1423
1424    /**
1425     * Returns all document contents of a given user
1426     * @return SeedDMS_Core_DocumentContent[]|bool list of document contents
1427     */
1428    public function getDocumentContents() { /* {{{ */
1429        $db = $this->_dms->getDB();
1430
1431        $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `createdBy` = " . $this->_id;
1432
1433        $resArr = $db->getResultArray($queryStr);
1434        if (is_bool($resArr) && !$resArr)
1435            return false;
1436
1437        $contents = array();
1438        $classname = $this->_dms->getClassname('documentcontent');
1439        foreach ($resArr as $row) {
1440            $document = $this->_dms->getDocument($row["document"]);
1441            /** @var SeedDMS_Core_DocumentContent $content */
1442            $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']);
1443            $contents[] = $content;
1444        }
1445        return $contents;
1446    } /* }}} */
1447
1448    /**
1449     * Returns all folders of a given user
1450     * @return SeedDMS_Core_Folder[]|bool list of folders
1451     */
1452    public function getFolders() { /* {{{ */
1453        $db = $this->_dms->getDB();
1454
1455        $queryStr = "SELECT * FROM `tblFolders` ".
1456            "WHERE `owner` = " . $this->_id . " ORDER BY `sequence`";
1457
1458        $resArr = $db->getResultArray($queryStr);
1459        if (is_bool($resArr) && !$resArr)
1460            return false;
1461
1462        $folders = array();
1463        $classname = $this->_dms->getClassname('folder');
1464        foreach ($resArr as $row) {
1465            /** @var SeedDMS_Core_Folder $folder */
1466            $folder = new $classname((int) $row["id"], $row["name"], $row['parent'], $row["comment"], $row["date"], $row["owner"], $row["inheritAccess"], $row["defaultAccess"], $row["sequence"]);
1467            $folder->setDMS($this->_dms);
1468            $folders[] = $folder;
1469        }
1470        return $folders;
1471    } /* }}} */
1472
1473    /**
1474     * Get a list of reviews
1475     *
1476     * This function returns a list of all reviews and their latest log entry
1477     * seperated by individuals and groups. If the document id
1478     * is passed, then only this document will be checked for reviews. The
1479     * same is true for the version of a document which limits the list
1480     * further. If you do not limit on a version it will retrieve the status
1481     * for each version, that includes even older versions which has been superseded
1482     * by a new version.
1483     *
1484     * For a detailed description of the result array see
1485     * {link SeedDMS_Core_User::getApprovalStatus} which does the same for
1486     * approvals.
1487     *
1488     * @param int $documentID optional document id for which to retrieve the
1489     *        reviews
1490     * @param int $version optional version of the document
1491     * @return array|bool list of all reviews
1492     */
1493    public function getReviewStatus($documentID = null, $version = null) { /* {{{ */
1494        $db = $this->_dms->getDB();
1495
1496        if (!$db->createTemporaryTable("ttreviewid", true)) {
1497            return false;
1498        }
1499
1500        $status = array("indstatus" => array(), "grpstatus" => array());
1501
1502        // See if the user is assigned as an individual reviewer.
1503        // Attention: this method didn't use ttreviewid to filter out the latest
1504        // log entry. This was added 2021-09-29 because $group->getReviewStatus()
1505        // does it as well. The check below if the date is larger than the date
1506        // of a previos entry is still required to just take the latest version
1507        // of a document into account.
1508        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1509            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1510            "`tblDocumentReviewLog`.`userID` ".
1511            "FROM `tblDocumentReviewers` ".
1512            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1513            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1514            // Does it makes sense to check in the where clause for the fields used by the left join? That would remove all rows where the left join didn't match. Without the where, the record would be still there but without the data from tblDocumentReviewLog. This makes only a difference if the ReviewLog misses entries for the review, but if it does, this methods returns no record at all and the document is not in the list of reviewed documents.
1515//            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1516            "WHERE 1=1 ".
1517            ($documentID == null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1518            ($version == null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1519            "AND `tblDocumentReviewers`.`type`='0' ".
1520            "AND `tblDocumentReviewers`.`required`='". $this->_id ."' ".
1521            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1522        $resArr = $db->getResultArray($queryStr);
1523        if (is_bool($resArr) && $resArr === false)
1524            return false;
1525        if (count($resArr)>0) {
1526            foreach ($resArr as $res) {
1527                if (isset($status["indstatus"][$res['documentID']])) {
1528                    if ($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1529                        $status["indstatus"][$res['documentID']] = $res;
1530                    }
1531                } else {
1532                    $status["indstatus"][$res['documentID']] = $res;
1533                }
1534            }
1535        }
1536
1537        // See if the user is the member of a group that has been assigned to
1538        // review the document version.
1539        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1540            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1541            "`tblDocumentReviewLog`.`userID` ".
1542            "FROM `tblDocumentReviewers` ".
1543            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1544            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1545            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentReviewers`.`required` ".
1546// See comment above
1547//            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1548            "WHERE 1=1 ".
1549            ($documentID == null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1550            ($version == null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1551            "AND `tblDocumentReviewers`.`type`='1' ".
1552            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1553            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1554        $resArr = $db->getResultArray($queryStr);
1555        if (is_bool($resArr) && $resArr === false)
1556            return false;
1557        if (count($resArr)>0) {
1558            foreach ($resArr as $res) {
1559                if (isset($status["grpstatus"][$res['documentID']])) {
1560                    if ($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1561                        $status["grpstatus"][$res['documentID']] = $res;
1562                    }
1563                } else {
1564                    $status["grpstatus"][$res['documentID']] = $res;
1565                }
1566            }
1567        }
1568        return $status;
1569    } /* }}} */
1570
1571    /**
1572     * Get a list of approvals
1573     *
1574     * This function returns a list of all approvals and their latest log entry
1575     * seperated by individuals and groups. If the document id
1576     * is passed, then only this document will be checked for approvals. The
1577     * same is true for the version of a document which limits the list
1578     * further. If you do not limit on a version it will retrieve the status
1579     * for each version, that includes even older versions which has been superseded
1580     * by a new version.
1581     *
1582     * The result array has two elements:
1583     * - indstatus: which contains the approvals by individuals (users)
1584     * - grpstatus: which contains the approvals by groups
1585     *
1586     * Each element is itself an array of approvals with the following elements
1587     * (it is a combination of fields from tblDocumentApprovers and tblDocumentApproveLog):
1588     * - approveID: unique id of approval
1589     * - documentID: id of document, that needs to be approved
1590     * - version: version of document, that needs to be approved
1591     * - type: 0 for individual approval, 1 for group approval
1592     * - required: id of user who is required to do the approval
1593     * - status: 0 not approved, ....
1594     * - comment: comment given during approval
1595     * - date: date of approval
1596     * - userID: id of user who has done the approval
1597     *
1598     * @param int $documentID optional document id for which to retrieve the
1599     *        approvals
1600     * @param int $version optional version of the document
1601     * @return array|bool list of all approvals
1602     */
1603    public function getApprovalStatus($documentID = null, $version = null) { /* {{{ */
1604        $db = $this->_dms->getDB();
1605
1606        if (!$db->createTemporaryTable("ttapproveid")) {
1607            return false;
1608        }
1609
1610        $status = array("indstatus" => array(), "grpstatus" => array());
1611
1612        // See if the user is assigned as an individual approver.
1613        // Attention: this method didn't use ttapproveid to filter out the latest
1614        // log entry. This was added 2021-09-29 because $group->getApprovalStatus()
1615        // does it as well. The check below if the date is larger than the date
1616        // of a previos entry is still required to just take the latest version
1617        // of a document into account.
1618        $queryStr =
1619            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1620            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1621            "`tblDocumentApproveLog`.`userID` ".
1622            "FROM `tblDocumentApprovers` ".
1623            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1624            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1625// See comment at getReviewStatus()
1626//            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1627            "WHERE 1=1 ".
1628            ($documentID == null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1629            ($version == null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1630            "AND `tblDocumentApprovers`.`type`='0' ".
1631            "AND `tblDocumentApprovers`.`required`='". $this->_id ."' ".
1632            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1633
1634        $resArr = $db->getResultArray($queryStr);
1635        if (is_bool($resArr) && $resArr == false)
1636            return false;
1637        if (count($resArr)>0) {
1638            foreach ($resArr as $res) {
1639                if (isset($status["indstatus"][$res['documentID']])) {
1640                    if ($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1641                        $status["indstatus"][$res['documentID']] = $res;
1642                    }
1643                } else {
1644                    $status["indstatus"][$res['documentID']] = $res;
1645                }
1646            }
1647        }
1648
1649        // See if the user is the member of a group that has been assigned to
1650        // approve the document version.
1651        $queryStr =
1652            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1653            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1654            "`tblDocumentApproveLog`.`userID` ".
1655            "FROM `tblDocumentApprovers` ".
1656            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1657            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1658            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ".
1659// See comment at getReviewStatus()
1660//            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1661            "WHERE 1=1 ".
1662            ($documentID == null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1663            ($version == null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1664            "AND `tblDocumentApprovers`.`type`='1' ".
1665            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1666            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1667        $resArr = $db->getResultArray($queryStr);
1668        if (is_bool($resArr) && $resArr == false)
1669            return false;
1670        if (count($resArr)>0) {
1671            foreach ($resArr as $res) {
1672                if (isset($status["grpstatus"][$res['documentID']])) {
1673                    if ($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1674                        $status["grpstatus"][$res['documentID']] = $res;
1675                    }
1676                } else {
1677                    $status["grpstatus"][$res['documentID']] = $res;
1678                }
1679            }
1680        }
1681        return $status;
1682    } /* }}} */
1683
1684    /**
1685     * Get a list of documents with a workflow
1686     *
1687     * @param int $documentID optional document id for which to retrieve the
1688     *        reviews
1689     * @param int $version optional version of the document
1690     * @return array|bool list of all workflows
1691     */
1692    public function getWorkflowStatus($documentID = null, $version = null) { /* {{{ */
1693        $db = $this->_dms->getDB();
1694
1695        $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;
1696        if ($documentID) {
1697            $queryStr .= ' AND d.`document`='.(int) $documentID;
1698            if ($version)
1699                $queryStr .= ' AND d.`version`='.(int) $version;
1700        }
1701        $resArr = $db->getResultArray($queryStr);
1702        if (is_bool($resArr) && $resArr == false)
1703            return false;
1704        $result['u'] = array();
1705        if (count($resArr)>0) {
1706            foreach ($resArr as $res) {
1707                $result['u'][] = $res;
1708            }
1709        }
1710
1711        $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;
1712        if ($documentID) {
1713            $queryStr .= ' AND d.`document`='.(int) $documentID;
1714            if ($version)
1715                $queryStr .= ' AND d.`version`='.(int) $version;
1716        }
1717        $resArr = $db->getResultArray($queryStr);
1718        if (is_bool($resArr) && $resArr == false)
1719            return false;
1720        $result['g'] = array();
1721        if (count($resArr)>0) {
1722            foreach ($resArr as $res) {
1723                $result['g'][] = $res;
1724            }
1725        }
1726        return $result;
1727    } /* }}} */
1728
1729    /**
1730     * Get a list of workflows this user is involved as in individual
1731     *
1732     * @return array|bool list of all workflows
1733     */
1734    public function getWorkflowsInvolved() { /* {{{ */
1735        $db = $this->_dms->getDB();
1736
1737        $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;
1738        $resArr = $db->getResultArray($queryStr);
1739        if (is_bool($resArr) && $resArr == false)
1740            return false;
1741        $result = array();
1742        if (count($resArr)>0) {
1743            foreach ($resArr as $res) {
1744                $result[] = $this->_dms->getWorkflow((int) $res['id']);
1745            }
1746        }
1747
1748        return $result;
1749    } /* }}} */
1750
1751    /**
1752     * Get a list of mandatory reviewers
1753     * A user which isn't trusted completely may have assigned mandatory
1754     * reviewers (both users and groups).
1755     * Whenever the user inserts a new document the mandatory reviewers are
1756     * filled in as reviewers.
1757     *
1758     * @return array list of arrays with two elements containing the user id
1759     *         (reviewerUserID) and group id (reviewerGroupID) of the reviewer.
1760     */
1761    public function getMandatoryReviewers() { /* {{{ */
1762        $db = $this->_dms->getDB();
1763
1764        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
1765        $resArr = $db->getResultArray($queryStr);
1766
1767        return $resArr;
1768    } /* }}} */
1769
1770    /**
1771     * Get a list of mandatory approvers
1772     * See {link SeedDMS_Core_User::getMandatoryReviewers}
1773     *
1774     * @return array list of arrays with two elements containing the user id
1775     *         (approverUserID) and group id (approverGroupID) of the approver.
1776     */
1777    public function getMandatoryApprovers() { /* {{{ */
1778        $db = $this->_dms->getDB();
1779
1780        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
1781        $resArr = $db->getResultArray($queryStr);
1782
1783        return $resArr;
1784    } /* }}} */
1785
1786    /**
1787     * Get a list of users this user is a mandatory reviewer of
1788     *
1789     * This method is the reverse function of getMandatoryReviewers(). It returns
1790     * those user where the current user is a mandatory reviewer.
1791     *
1792     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory reviewer.
1793     */
1794    public function isMandatoryReviewerOf() { /* {{{ */
1795        $db = $this->_dms->getDB();
1796
1797        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id;
1798        $resArr = $db->getResultArray($queryStr);
1799        if (is_bool($resArr) && !$resArr) return false;
1800
1801        $users = array();
1802        foreach ($resArr as $res) {
1803            $users[] = self::getInstance($res['userID'], $this->_dms);
1804        }
1805
1806        return $users;
1807    } /* }}} */
1808
1809    /**
1810     * Get a list of users this user is a mandatory approver of
1811     *
1812     * This method is the reverse function of getMandatoryApprovers(). It returns
1813     * those user where the current user is a mandatory approver.
1814     *
1815     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory approver.
1816     */
1817    public function isMandatoryApproverOf() { /* {{{ */
1818        $db = $this->_dms->getDB();
1819
1820        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id;
1821        $resArr = $db->getResultArray($queryStr);
1822        if (is_bool($resArr) && !$resArr) return false;
1823
1824        $users = array();
1825        foreach ($resArr as $res) {
1826            $users[] = self::getInstance($res['userID'], $this->_dms);
1827        }
1828
1829        return $users;
1830    } /* }}} */
1831
1832    /**
1833     * Get the mandatory workflow
1834     * A user which isn't trusted completely may have assigned mandatory
1835     * workflow
1836     * Whenever the user inserts a new document the mandatory workflow is
1837     * filled in as the workflow.
1838     *
1839     * @return SeedDMS_Core_Workflow|bool workflow
1840     */
1841    public function getMandatoryWorkflow() { /* {{{ */
1842        $db = $this->_dms->getDB();
1843
1844        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1845        $resArr = $db->getResultArray($queryStr);
1846        if (is_bool($resArr) && !$resArr) return false;
1847
1848        if (!$resArr)
1849            return null;
1850
1851        $workflow = $this->_dms->getWorkflow($resArr[0]['workflow']);
1852        return $workflow;
1853    } /* }}} */
1854
1855    /**
1856     * Get the mandatory workflows
1857     * A user which isn't trusted completely may have assigned mandatory
1858     * workflow
1859     * Whenever the user inserts a new document the mandatory workflow is
1860     * filled in as the workflow.
1861     *
1862     * @return SeedDMS_Core_Workflow[]|bool workflow
1863     */
1864    public function getMandatoryWorkflows() { /* {{{ */
1865        $db = $this->_dms->getDB();
1866
1867        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1868        $resArr = $db->getResultArray($queryStr);
1869        if (is_bool($resArr) && !$resArr) return false;
1870
1871        if (!$resArr)
1872            return null;
1873
1874        $workflows = array();
1875        foreach ($resArr as $res) {
1876            $workflows[] = $this->_dms->getWorkflow($res['workflow']);
1877        }
1878        return $workflows;
1879    } /* }}} */
1880
1881    /**
1882     * Set a mandatory reviewer
1883     * This function sets a mandatory reviewer if it isn't already set.
1884     *
1885     * @param integer $id id of reviewer
1886     * @param boolean $isgroup true if $id is a group
1887     * @return boolean true on success, otherwise false
1888     */
1889    public function setMandatoryReviewer($id, $isgroup = false) { /* {{{ */
1890        $db = $this->_dms->getDB();
1891        $id = (int) $id;
1892
1893        if ($isgroup) {
1894            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerGroupID` = " . $id;
1895            $resArr = $db->getResultArray($queryStr);
1896            if (count($resArr) != 0) return true;
1897
1898            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerGroupID`) VALUES (" . $this->_id . ", " . $id .")";
1899            $resArr = $db->getResult($queryStr);
1900            if (is_bool($resArr) && !$resArr) return false;
1901        } else {
1902            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerUserID` = " . $id;
1903            $resArr = $db->getResultArray($queryStr);
1904            if (count($resArr) != 0) return true;
1905
1906            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerUserID`) VALUES (" . $this->_id . ", " . $id .")";
1907            $resArr = $db->getResult($queryStr);
1908            if (is_bool($resArr) && !$resArr) return false;
1909        }
1910
1911        return true;
1912    } /* }}} */
1913
1914    /**
1915     * Set a mandatory approver
1916     * This function sets a mandatory approver if it isn't already set.
1917     *
1918     * @param integer $id id of approver
1919     * @param boolean $isgroup true if $id is a group
1920     * @return boolean true on success, otherwise false
1921     */
1922    public function setMandatoryApprover($id, $isgroup = false) { /* {{{ */
1923        $db = $this->_dms->getDB();
1924        $id = (int) $id;
1925
1926        if ($isgroup) {
1927            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverGroupID` = " . $id;
1928            $resArr = $db->getResultArray($queryStr);
1929            if (count($resArr) != 0) return true;
1930
1931            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverGroupID`) VALUES (" . $this->_id . ", " . $id .")";
1932            $resArr = $db->getResult($queryStr);
1933            if (is_bool($resArr) && !$resArr) return false;
1934        } else {
1935            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverUserID` = " . $id;
1936            $resArr = $db->getResultArray($queryStr);
1937            if (count($resArr) != 0) return true;
1938
1939            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverUserID`) VALUES (" . $this->_id . ", " . $id .")";
1940            $resArr = $db->getResult($queryStr);
1941            if (is_bool($resArr) && !$resArr) return false;
1942        }
1943
1944        return true;
1945    } /* }}} */
1946
1947    /**
1948     * Set a mandatory workflow
1949     * This function sets a mandatory workflow if it isn't already set.
1950     *
1951     * @param object $workflow workflow
1952     * @return boolean true on success, otherwise false
1953     */
1954    public function setMandatoryWorkflow($workflow) { /* {{{ */
1955        $db = $this->_dms->getDB();
1956
1957        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id . " AND `workflow` = " . (int) $workflow->getID();
1958        $resArr = $db->getResultArray($queryStr);
1959        if (count($resArr) != 0) return true;
1960
1961        $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
1962        $resArr = $db->getResult($queryStr);
1963        if (is_bool($resArr) && !$resArr) return false;
1964
1965        return true;
1966    } /* }}} */
1967
1968    /**
1969     * Set a mandatory workflows
1970     * This function sets a list of mandatory workflows.
1971     *
1972     * @param SeedDMS_Core_Workflow[] $workflows list of workflow objects
1973     * @return boolean true on success, otherwise false
1974     */
1975    public function setMandatoryWorkflows($workflows) { /* {{{ */
1976        $db = $this->_dms->getDB();
1977
1978        $db->startTransaction();
1979        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1980        if (!$db->getResult($queryStr)) {
1981            $db->rollbackTransaction();
1982            return false;
1983        }
1984
1985        foreach ($workflows as $workflow) {
1986            $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
1987            $resArr = $db->getResult($queryStr);
1988            if (is_bool($resArr) && !$resArr) {
1989                $db->rollbackTransaction();
1990                return false;
1991            }
1992        }
1993
1994        $db->commitTransaction();
1995        return true;
1996    } /* }}} */
1997
1998    /**
1999     * Deletes all mandatory reviewers
2000     *
2001     * @return boolean true on success, otherwise false
2002     */
2003    public function delMandatoryReviewers() { /* {{{ */
2004        $db = $this->_dms->getDB();
2005        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
2006        if (!$db->getResult($queryStr)) return false;
2007        return true;
2008    } /* }}} */
2009
2010    /**
2011     * Deletes all mandatory approvers
2012     *
2013     * @return boolean true on success, otherwise false
2014     */
2015    public function delMandatoryApprovers() { /* {{{ */
2016        $db = $this->_dms->getDB();
2017
2018        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
2019        if (!$db->getResult($queryStr)) return false;
2020        return true;
2021    } /* }}} */
2022
2023    /**
2024     * Deletes the  mandatory workflow
2025     *
2026     * @return boolean true on success, otherwise false
2027     */
2028    public function delMandatoryWorkflow() { /* {{{ */
2029        $db = $this->_dms->getDB();
2030        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2031        if (!$db->getResult($queryStr)) return false;
2032        return true;
2033    } /* }}} */
2034
2035    /**
2036     * Get all notifications of user
2037     *
2038     * @param integer $type type of item (T_DOCUMENT or T_FOLDER)
2039     * @return SeedDMS_Core_Notification[]|bool array of notifications
2040     */
2041    public function getNotifications($type = 0) { /* {{{ */
2042        $db = $this->_dms->getDB();
2043        $queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ".
2044         "WHERE `tblNotify`.`userID` = ". $this->_id;
2045        if ($type) {
2046            $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type;
2047        }
2048
2049        $resArr = $db->getResultArray($queryStr);
2050        if (is_bool($resArr) && !$resArr)
2051            return false;
2052
2053        $notifications = array();
2054        foreach ($resArr as $row) {
2055            $not = new SeedDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]);
2056            $not->setDMS($this);
2057            array_push($notifications, $not);
2058        }
2059
2060        return $notifications;
2061    } /* }}} */
2062
2063    /**
2064     * Return list of personal keyword categories
2065     *
2066     * @return SeedDMS_Core_KeywordCategory[]|bool list of categories or false in case of an error
2067     */
2068    public function getKeywordCategories() { /* {{{ */
2069        $db = $this->_dms->getDB();
2070
2071        $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `owner` = ".$this->_id;
2072
2073        $resArr = $db->getResultArray($queryStr);
2074        if (is_bool($resArr) && !$resArr)
2075            return false;
2076
2077        $categories = array();
2078        foreach ($resArr as $row) {
2079            $cat = new SeedDMS_Core_KeywordCategory((int) $row["id"], $row["owner"], $row["name"]);
2080            $cat->setDMS($this->_dms);
2081            array_push($categories, $cat);
2082        }
2083
2084        return $categories;
2085    } /* }}} */
2086
2087} /* }}} */