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    /**
1273     * @param string $tmpfile
1274     * @param string $mimeType
1275     * @return bool
1276     */
1277    public function setImage($tmpfile, $mimeType) { /* {{{ */
1278        $db = $this->_dms->getDB();
1279
1280        $fp = fopen($tmpfile, "rb");
1281        if (!$fp) return false;
1282        $content = fread($fp, filesize($tmpfile));
1283        fclose($fp);
1284
1285        if ($this->hasImage()) {
1286            $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($content)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id;
1287        } else {
1288            $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($content)."', ".$db->qstr($mimeType).")";
1289        }
1290        if (!$db->getResult($queryStr)) {
1291            return false;
1292        }
1293
1294        $this->_hasImage = true;
1295        return true;
1296    } /* }}} */
1297
1298    /**
1299     * @param string $imagedata
1300     * @param string $mimeType
1301     * @return bool
1302     */
1303    public function setImageBlob($imagedata, $mimeType) { /* {{{ */
1304        $db = $this->_dms->getDB();
1305
1306        if ($this->hasImage()) {
1307            $queryStr = "UPDATE `tblUserImages` SET `image` = '".base64_encode($imagedata)."', `mimeType` = ".$db->qstr($mimeType)." WHERE `userID` = " . $this->_id;
1308        } else {
1309            $queryStr = "INSERT INTO `tblUserImages` (`userID`, `image`, `mimeType`) VALUES (" . $this->_id . ", '".base64_encode($imagedata)."', ".$db->qstr($mimeType).")";
1310        }
1311        if (!$db->getResult($queryStr)) {
1312            return false;
1313        }
1314
1315        $this->_hasImage = true;
1316        return true;
1317    } /* }}} */
1318
1319    /**
1320     * Returns all documents of a given user
1321     * @return SeedDMS_Core_Document[]|bool list of documents
1322     */
1323    public function getDocuments() { /* {{{ */
1324        $db = $this->_dms->getDB();
1325
1326        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1327            "FROM `tblDocuments` ".
1328            "LEFT JOIN `tblDocumentLocks` ON `tblDocuments`.`id`=`tblDocumentLocks`.`document` ".
1329            "WHERE `tblDocuments`.`owner` = " . $this->_id . " ORDER BY `sequence`";
1330
1331        $resArr = $db->getResultArray($queryStr);
1332        if (is_bool($resArr) && !$resArr)
1333            return false;
1334
1335        $documents = array();
1336        $classname = $this->_dms->getClassname('document');
1337        foreach ($resArr as $row) {
1338            /** @var SeedDMS_Core_Document $document */
1339            $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"]);
1340            $document->setDMS($this->_dms);
1341            $documents[] = $document;
1342        }
1343        return $documents;
1344    } /* }}} */
1345
1346    /**
1347     * Returns all documents locked by a given user
1348     *
1349     * @return bool|SeedDMS_Core_Document[] list of documents
1350     */
1351    public function getDocumentsLocked() { /* {{{ */
1352        $db = $this->_dms->getDB();
1353
1354        $queryStr = "SELECT `tblDocuments`.*, `tblDocumentLocks`.`userID` as `lockUser` ".
1355            "FROM `tblDocumentLocks` LEFT JOIN `tblDocuments` ON `tblDocuments`.`id` = `tblDocumentLocks`.`document` ".
1356            "WHERE `tblDocumentLocks`.`userID` = '".$this->_id."' ".
1357            "ORDER BY `id` DESC";
1358
1359        $resArr = $db->getResultArray($queryStr);
1360        if (is_bool($resArr) && !$resArr)
1361            return false;
1362
1363        $documents = array();
1364        $classname = $this->_dms->getClassname('document');
1365        foreach ($resArr as $row) {
1366            /** @var SeedDMS_Core_Document $document */
1367            $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"]);
1368            $document->setDMS($this->_dms);
1369            $documents[] = $document;
1370        }
1371        return $documents;
1372    } /* }}} */
1373
1374    /**
1375     * Returns all document links of a given user
1376     * @return SeedDMS_Core_DocumentLink[]|bool list of document links
1377     */
1378    public function getDocumentLinks() { /* {{{ */
1379        $db = $this->_dms->getDB();
1380
1381        $queryStr = "SELECT * FROM `tblDocumentLinks` ".
1382            "WHERE `userID` = " . $this->_id;
1383
1384        $resArr = $db->getResultArray($queryStr);
1385        if (is_bool($resArr) && !$resArr)
1386            return false;
1387
1388        $links = array();
1389        $classname = 'SeedDMS_Core_DocumentLink';
1390        foreach ($resArr as $row) {
1391            $document = $this->_dms->getDocument($row["document"]);
1392            $target = $this->_dms->getDocument($row["target"]);
1393            /** @var SeedDMS_Core_Document $document */
1394            $link = new $classname((int) $row["id"], $document, $target, $row["userID"], $row["public"]);
1395            $links[] = $link;
1396        }
1397        return $links;
1398    } /* }}} */
1399
1400    /**
1401     * Returns all document files of a given user
1402     * @return SeedDMS_Core_DocumentFile[]|bool list of document files
1403     */
1404    public function getDocumentFiles() { /* {{{ */
1405        $db = $this->_dms->getDB();
1406
1407        $queryStr = "SELECT * FROM `tblDocumentFiles` ".
1408            "WHERE `userID` = " . $this->_id;
1409
1410        $resArr = $db->getResultArray($queryStr);
1411        if (is_bool($resArr) && !$resArr)
1412            return false;
1413
1414        $files = array();
1415        $classname = 'SeedDMS_Core_DocumentFile';
1416        foreach ($resArr as $row) {
1417            $document = $this->_dms->getDocument($row["document"]);
1418            /** @var SeedDMS_Core_DocumentFile $file */
1419            $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"]);
1420            $files[] = $file;
1421        }
1422        return $files;
1423    } /* }}} */
1424
1425    /**
1426     * Returns all document contents of a given user
1427     * @return SeedDMS_Core_DocumentContent[]|bool list of document contents
1428     */
1429    public function getDocumentContents() { /* {{{ */
1430        $db = $this->_dms->getDB();
1431
1432        $queryStr = "SELECT * FROM `tblDocumentContent` WHERE `createdBy` = " . $this->_id;
1433
1434        $resArr = $db->getResultArray($queryStr);
1435        if (is_bool($resArr) && !$resArr)
1436            return false;
1437
1438        $contents = array();
1439        $classname = $this->_dms->getClassname('documentcontent');
1440        foreach ($resArr as $row) {
1441            $document = $this->_dms->getDocument($row["document"]);
1442            /** @var SeedDMS_Core_DocumentContent $content */
1443            $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']);
1444            $contents[] = $content;
1445        }
1446        return $contents;
1447    } /* }}} */
1448
1449    /**
1450     * Returns all folders of a given user
1451     * @return SeedDMS_Core_Folder[]|bool list of folders
1452     */
1453    public function getFolders() { /* {{{ */
1454        $db = $this->_dms->getDB();
1455
1456        $queryStr = "SELECT * FROM `tblFolders` ".
1457            "WHERE `owner` = " . $this->_id . " ORDER BY `sequence`";
1458
1459        $resArr = $db->getResultArray($queryStr);
1460        if (is_bool($resArr) && !$resArr)
1461            return false;
1462
1463        $folders = array();
1464        $classname = $this->_dms->getClassname('folder');
1465        foreach ($resArr as $row) {
1466            /** @var SeedDMS_Core_Folder $folder */
1467            $folder = new $classname((int) $row["id"], $row["name"], $row['parent'], $row["comment"], $row["date"], $row["owner"], $row["inheritAccess"], $row["defaultAccess"], $row["sequence"]);
1468            $folder->setDMS($this->_dms);
1469            $folders[] = $folder;
1470        }
1471        return $folders;
1472    } /* }}} */
1473
1474    /**
1475     * Get a list of reviews
1476     *
1477     * This function returns a list of all reviews and their latest log entry
1478     * seperated by individuals and groups. If the document id
1479     * is passed, then only this document will be checked for reviews. The
1480     * same is true for the version of a document which limits the list
1481     * further. If you do not limit on a version it will retrieve the status
1482     * for each version, that includes even older versions which has been superseded
1483     * by a new version.
1484     *
1485     * For a detailed description of the result array see
1486     * {link SeedDMS_Core_User::getApprovalStatus} which does the same for
1487     * approvals.
1488     *
1489     * @param int $documentID optional document id for which to retrieve the
1490     *        reviews
1491     * @param int $version optional version of the document
1492     * @return array|bool list of all reviews
1493     */
1494    public function getReviewStatus($documentID = null, $version = null) { /* {{{ */
1495        $db = $this->_dms->getDB();
1496
1497        if (!$db->createTemporaryTable("ttreviewid", true)) {
1498            return false;
1499        }
1500
1501        $status = array("indstatus" => array(), "grpstatus" => array());
1502
1503        // See if the user is assigned as an individual reviewer.
1504        // Attention: this method didn't use ttreviewid to filter out the latest
1505        // log entry. This was added 2021-09-29 because $group->getReviewStatus()
1506        // does it as well. The check below if the date is larger than the date
1507        // of a previos entry is still required to just take the latest version
1508        // of a document into account.
1509        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1510            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1511            "`tblDocumentReviewLog`.`userID` ".
1512            "FROM `tblDocumentReviewers` ".
1513            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1514            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1515            // 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.
1516//            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1517            "WHERE 1=1 ".
1518            ($documentID == null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1519            ($version == null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1520            "AND `tblDocumentReviewers`.`type`='0' ".
1521            "AND `tblDocumentReviewers`.`required`='". $this->_id ."' ".
1522            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1523        $resArr = $db->getResultArray($queryStr);
1524        if (is_bool($resArr) && $resArr === false)
1525            return false;
1526        if (count($resArr)>0) {
1527            foreach ($resArr as $res) {
1528                if (isset($status["indstatus"][$res['documentID']])) {
1529                    if ($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1530                        $status["indstatus"][$res['documentID']] = $res;
1531                    }
1532                } else {
1533                    $status["indstatus"][$res['documentID']] = $res;
1534                }
1535            }
1536        }
1537
1538        // See if the user is the member of a group that has been assigned to
1539        // review the document version.
1540        $queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
1541            "`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
1542            "`tblDocumentReviewLog`.`userID` ".
1543            "FROM `tblDocumentReviewers` ".
1544            "LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
1545            "LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
1546            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentReviewers`.`required` ".
1547// See comment above
1548//            "WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
1549            "WHERE 1=1 ".
1550            ($documentID == null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
1551            ($version == null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
1552            "AND `tblDocumentReviewers`.`type`='1' ".
1553            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1554            "ORDER BY `tblDocumentReviewLog`.`reviewLogID` DESC";
1555        $resArr = $db->getResultArray($queryStr);
1556        if (is_bool($resArr) && $resArr === false)
1557            return false;
1558        if (count($resArr)>0) {
1559            foreach ($resArr as $res) {
1560                if (isset($status["grpstatus"][$res['documentID']])) {
1561                    if ($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1562                        $status["grpstatus"][$res['documentID']] = $res;
1563                    }
1564                } else {
1565                    $status["grpstatus"][$res['documentID']] = $res;
1566                }
1567            }
1568        }
1569        return $status;
1570    } /* }}} */
1571
1572    /**
1573     * Get a list of approvals
1574     *
1575     * This function returns a list of all approvals and their latest log entry
1576     * seperated by individuals and groups. If the document id
1577     * is passed, then only this document will be checked for approvals. The
1578     * same is true for the version of a document which limits the list
1579     * further. If you do not limit on a version it will retrieve the status
1580     * for each version, that includes even older versions which has been superseded
1581     * by a new version.
1582     *
1583     * The result array has two elements:
1584     * - indstatus: which contains the approvals by individuals (users)
1585     * - grpstatus: which contains the approvals by groups
1586     *
1587     * Each element is itself an array of approvals with the following elements
1588     * (it is a combination of fields from tblDocumentApprovers and tblDocumentApproveLog):
1589     * - approveID: unique id of approval
1590     * - documentID: id of document, that needs to be approved
1591     * - version: version of document, that needs to be approved
1592     * - type: 0 for individual approval, 1 for group approval
1593     * - required: id of user who is required to do the approval
1594     * - status: 0 not approved, ....
1595     * - comment: comment given during approval
1596     * - date: date of approval
1597     * - userID: id of user who has done the approval
1598     *
1599     * @param int $documentID optional document id for which to retrieve the
1600     *        approvals
1601     * @param int $version optional version of the document
1602     * @return array|bool list of all approvals
1603     */
1604    public function getApprovalStatus($documentID = null, $version = null) { /* {{{ */
1605        $db = $this->_dms->getDB();
1606
1607        if (!$db->createTemporaryTable("ttapproveid")) {
1608            return false;
1609        }
1610
1611        $status = array("indstatus" => array(), "grpstatus" => array());
1612
1613        // See if the user is assigned as an individual approver.
1614        // Attention: this method didn't use ttapproveid to filter out the latest
1615        // log entry. This was added 2021-09-29 because $group->getApprovalStatus()
1616        // does it as well. The check below if the date is larger than the date
1617        // of a previos entry is still required to just take the latest version
1618        // of a document into account.
1619        $queryStr =
1620            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1621            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1622            "`tblDocumentApproveLog`.`userID` ".
1623            "FROM `tblDocumentApprovers` ".
1624            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1625            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1626// See comment at getReviewStatus()
1627//            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1628            "WHERE 1=1 ".
1629            ($documentID == null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1630            ($version == null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1631            "AND `tblDocumentApprovers`.`type`='0' ".
1632            "AND `tblDocumentApprovers`.`required`='". $this->_id ."' ".
1633            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1634
1635        $resArr = $db->getResultArray($queryStr);
1636        if (is_bool($resArr) && $resArr == false)
1637            return false;
1638        if (count($resArr)>0) {
1639            foreach ($resArr as $res) {
1640                if (isset($status["indstatus"][$res['documentID']])) {
1641                    if ($status["indstatus"][$res['documentID']]['date'] < $res['date']) {
1642                        $status["indstatus"][$res['documentID']] = $res;
1643                    }
1644                } else {
1645                    $status["indstatus"][$res['documentID']] = $res;
1646                }
1647            }
1648        }
1649
1650        // See if the user is the member of a group that has been assigned to
1651        // approve the document version.
1652        $queryStr =
1653            "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
1654            "`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
1655            "`tblDocumentApproveLog`.`userID` ".
1656            "FROM `tblDocumentApprovers` ".
1657            "LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
1658            "LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
1659            "LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`groupID` = `tblDocumentApprovers`.`required` ".
1660// See comment at getReviewStatus()
1661//            "WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
1662            "WHERE 1=1 ".
1663            ($documentID == null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
1664            ($version == null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
1665            "AND `tblDocumentApprovers`.`type`='1' ".
1666            "AND `tblGroupMembers`.`userID`='". $this->_id ."' ".
1667            "ORDER BY `tblDocumentApproveLog`.`approveLogID` DESC";
1668        $resArr = $db->getResultArray($queryStr);
1669        if (is_bool($resArr) && $resArr == false)
1670            return false;
1671        if (count($resArr)>0) {
1672            foreach ($resArr as $res) {
1673                if (isset($status["grpstatus"][$res['documentID']])) {
1674                    if ($status["grpstatus"][$res['documentID']]['date'] < $res['date']) {
1675                        $status["grpstatus"][$res['documentID']] = $res;
1676                    }
1677                } else {
1678                    $status["grpstatus"][$res['documentID']] = $res;
1679                }
1680            }
1681        }
1682        return $status;
1683    } /* }}} */
1684
1685    /**
1686     * Get a list of documents with a workflow
1687     *
1688     * @param int $documentID optional document id for which to retrieve the
1689     *        reviews
1690     * @param int $version optional version of the document
1691     * @return array|bool list of all workflows
1692     */
1693    public function getWorkflowStatus($documentID = null, $version = null) { /* {{{ */
1694        $db = $this->_dms->getDB();
1695
1696        $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;
1697        if ($documentID) {
1698            $queryStr .= ' AND d.`document`='.(int) $documentID;
1699            if ($version)
1700                $queryStr .= ' AND d.`version`='.(int) $version;
1701        }
1702        $resArr = $db->getResultArray($queryStr);
1703        if (is_bool($resArr) && $resArr == false)
1704            return false;
1705        $result['u'] = array();
1706        if (count($resArr)>0) {
1707            foreach ($resArr as $res) {
1708                $result['u'][] = $res;
1709            }
1710        }
1711
1712        $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;
1713        if ($documentID) {
1714            $queryStr .= ' AND d.`document`='.(int) $documentID;
1715            if ($version)
1716                $queryStr .= ' AND d.`version`='.(int) $version;
1717        }
1718        $resArr = $db->getResultArray($queryStr);
1719        if (is_bool($resArr) && $resArr == false)
1720            return false;
1721        $result['g'] = array();
1722        if (count($resArr)>0) {
1723            foreach ($resArr as $res) {
1724                $result['g'][] = $res;
1725            }
1726        }
1727        return $result;
1728    } /* }}} */
1729
1730    /**
1731     * Get a list of workflows this user is involved as in individual
1732     *
1733     * @return array|bool list of all workflows
1734     */
1735    public function getWorkflowsInvolved() { /* {{{ */
1736        $db = $this->_dms->getDB();
1737
1738        $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;
1739        $resArr = $db->getResultArray($queryStr);
1740        if (is_bool($resArr) && $resArr == false)
1741            return false;
1742        $result = array();
1743        if (count($resArr)>0) {
1744            foreach ($resArr as $res) {
1745                $result[] = $this->_dms->getWorkflow((int) $res['id']);
1746            }
1747        }
1748
1749        return $result;
1750    } /* }}} */
1751
1752    /**
1753     * Get a list of mandatory reviewers
1754     * A user which isn't trusted completely may have assigned mandatory
1755     * reviewers (both users and groups).
1756     * Whenever the user inserts a new document the mandatory reviewers are
1757     * filled in as reviewers.
1758     *
1759     * @return array list of arrays with two elements containing the user id
1760     *         (reviewerUserID) and group id (reviewerGroupID) of the reviewer.
1761     */
1762    public function getMandatoryReviewers() { /* {{{ */
1763        $db = $this->_dms->getDB();
1764
1765        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
1766        $resArr = $db->getResultArray($queryStr);
1767
1768        return $resArr;
1769    } /* }}} */
1770
1771    /**
1772     * Get a list of mandatory approvers
1773     * See {link SeedDMS_Core_User::getMandatoryReviewers}
1774     *
1775     * @return array list of arrays with two elements containing the user id
1776     *         (approverUserID) and group id (approverGroupID) of the approver.
1777     */
1778    public function getMandatoryApprovers() { /* {{{ */
1779        $db = $this->_dms->getDB();
1780
1781        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
1782        $resArr = $db->getResultArray($queryStr);
1783
1784        return $resArr;
1785    } /* }}} */
1786
1787    /**
1788     * Get a list of users this user is a mandatory reviewer of
1789     *
1790     * This method is the reverse function of getMandatoryReviewers(). It returns
1791     * those user where the current user is a mandatory reviewer.
1792     *
1793     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory reviewer.
1794     */
1795    public function isMandatoryReviewerOf() { /* {{{ */
1796        $db = $this->_dms->getDB();
1797
1798        $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `reviewerUserID` = " . $this->_id;
1799        $resArr = $db->getResultArray($queryStr);
1800        if (is_bool($resArr) && !$resArr) return false;
1801
1802        $users = array();
1803        foreach ($resArr as $res) {
1804            $users[] = self::getInstance($res['userID'], $this->_dms);
1805        }
1806
1807        return $users;
1808    } /* }}} */
1809
1810    /**
1811     * Get a list of users this user is a mandatory approver of
1812     *
1813     * This method is the reverse function of getMandatoryApprovers(). It returns
1814     * those user where the current user is a mandatory approver.
1815     *
1816     * @return SeedDMS_Core_User[]|bool list of users where this user is a mandatory approver.
1817     */
1818    public function isMandatoryApproverOf() { /* {{{ */
1819        $db = $this->_dms->getDB();
1820
1821        $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `approverUserID` = " . $this->_id;
1822        $resArr = $db->getResultArray($queryStr);
1823        if (is_bool($resArr) && !$resArr) return false;
1824
1825        $users = array();
1826        foreach ($resArr as $res) {
1827            $users[] = self::getInstance($res['userID'], $this->_dms);
1828        }
1829
1830        return $users;
1831    } /* }}} */
1832
1833    /**
1834     * Get the mandatory workflow
1835     * A user which isn't trusted completely may have assigned mandatory
1836     * workflow
1837     * Whenever the user inserts a new document the mandatory workflow is
1838     * filled in as the workflow.
1839     *
1840     * @return SeedDMS_Core_Workflow|bool workflow
1841     */
1842    public function getMandatoryWorkflow() { /* {{{ */
1843        $db = $this->_dms->getDB();
1844
1845        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1846        $resArr = $db->getResultArray($queryStr);
1847        if (is_bool($resArr) && !$resArr) return false;
1848
1849        if (!$resArr)
1850            return null;
1851
1852        $workflow = $this->_dms->getWorkflow($resArr[0]['workflow']);
1853        return $workflow;
1854    } /* }}} */
1855
1856    /**
1857     * Get the mandatory workflows
1858     * A user which isn't trusted completely may have assigned mandatory
1859     * workflow
1860     * Whenever the user inserts a new document the mandatory workflow is
1861     * filled in as the workflow.
1862     *
1863     * @return SeedDMS_Core_Workflow[]|bool workflow
1864     */
1865    public function getMandatoryWorkflows() { /* {{{ */
1866        $db = $this->_dms->getDB();
1867
1868        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1869        $resArr = $db->getResultArray($queryStr);
1870        if (is_bool($resArr) && !$resArr) return false;
1871
1872        if (!$resArr)
1873            return null;
1874
1875        $workflows = array();
1876        foreach ($resArr as $res) {
1877            $workflows[] = $this->_dms->getWorkflow($res['workflow']);
1878        }
1879        return $workflows;
1880    } /* }}} */
1881
1882    /**
1883     * Set a mandatory reviewer
1884     * This function sets a mandatory reviewer if it isn't already set.
1885     *
1886     * @param integer $id id of reviewer
1887     * @param boolean $isgroup true if $id is a group
1888     * @return boolean true on success, otherwise false
1889     */
1890    public function setMandatoryReviewer($id, $isgroup = false) { /* {{{ */
1891        $db = $this->_dms->getDB();
1892        $id = (int) $id;
1893
1894        if ($isgroup) {
1895            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerGroupID` = " . $id;
1896            $resArr = $db->getResultArray($queryStr);
1897            if (count($resArr) != 0) return true;
1898
1899            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerGroupID`) VALUES (" . $this->_id . ", " . $id .")";
1900            $resArr = $db->getResult($queryStr);
1901            if (is_bool($resArr) && !$resArr) return false;
1902        } else {
1903            $queryStr = "SELECT * FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id . " AND `reviewerUserID` = " . $id;
1904            $resArr = $db->getResultArray($queryStr);
1905            if (count($resArr) != 0) return true;
1906
1907            $queryStr = "INSERT INTO `tblMandatoryReviewers` (`userID`, `reviewerUserID`) VALUES (" . $this->_id . ", " . $id .")";
1908            $resArr = $db->getResult($queryStr);
1909            if (is_bool($resArr) && !$resArr) return false;
1910        }
1911
1912        return true;
1913    } /* }}} */
1914
1915    /**
1916     * Set a mandatory approver
1917     * This function sets a mandatory approver if it isn't already set.
1918     *
1919     * @param integer $id id of approver
1920     * @param boolean $isgroup true if $id is a group
1921     * @return boolean true on success, otherwise false
1922     */
1923    public function setMandatoryApprover($id, $isgroup = false) { /* {{{ */
1924        $db = $this->_dms->getDB();
1925        $id = (int) $id;
1926
1927        if ($isgroup) {
1928            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverGroupID` = " . $id;
1929            $resArr = $db->getResultArray($queryStr);
1930            if (count($resArr) != 0) return true;
1931
1932            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverGroupID`) VALUES (" . $this->_id . ", " . $id .")";
1933            $resArr = $db->getResult($queryStr);
1934            if (is_bool($resArr) && !$resArr) return false;
1935        } else {
1936            $queryStr = "SELECT * FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id . " AND `approverUserID` = " . $id;
1937            $resArr = $db->getResultArray($queryStr);
1938            if (count($resArr) != 0) return true;
1939
1940            $queryStr = "INSERT INTO `tblMandatoryApprovers` (`userID`, `approverUserID`) VALUES (" . $this->_id . ", " . $id .")";
1941            $resArr = $db->getResult($queryStr);
1942            if (is_bool($resArr) && !$resArr) return false;
1943        }
1944
1945        return true;
1946    } /* }}} */
1947
1948    /**
1949     * Set a mandatory workflow
1950     * This function sets a mandatory workflow if it isn't already set.
1951     *
1952     * @param object $workflow workflow
1953     * @return boolean true on success, otherwise false
1954     */
1955    public function setMandatoryWorkflow($workflow) { /* {{{ */
1956        $db = $this->_dms->getDB();
1957
1958        $queryStr = "SELECT * FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id . " AND `workflow` = " . (int) $workflow->getID();
1959        $resArr = $db->getResultArray($queryStr);
1960        if (count($resArr) != 0) return true;
1961
1962        $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
1963        $resArr = $db->getResult($queryStr);
1964        if (is_bool($resArr) && !$resArr) return false;
1965
1966        return true;
1967    } /* }}} */
1968
1969    /**
1970     * Set a mandatory workflows
1971     * This function sets a list of mandatory workflows.
1972     *
1973     * @param SeedDMS_Core_Workflow[] $workflows list of workflow objects
1974     * @return boolean true on success, otherwise false
1975     */
1976    public function setMandatoryWorkflows($workflows) { /* {{{ */
1977        $db = $this->_dms->getDB();
1978
1979        $db->startTransaction();
1980        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
1981        if (!$db->getResult($queryStr)) {
1982            $db->rollbackTransaction();
1983            return false;
1984        }
1985
1986        foreach ($workflows as $workflow) {
1987            $queryStr = "INSERT INTO `tblWorkflowMandatoryWorkflow` (`userid`, `workflow`) VALUES (" . $this->_id . ", " . $workflow->getID() .")";
1988            $resArr = $db->getResult($queryStr);
1989            if (is_bool($resArr) && !$resArr) {
1990                $db->rollbackTransaction();
1991                return false;
1992            }
1993        }
1994
1995        $db->commitTransaction();
1996        return true;
1997    } /* }}} */
1998
1999    /**
2000     * Deletes all mandatory reviewers
2001     *
2002     * @return boolean true on success, otherwise false
2003     */
2004    public function delMandatoryReviewers() { /* {{{ */
2005        $db = $this->_dms->getDB();
2006        $queryStr = "DELETE FROM `tblMandatoryReviewers` WHERE `userID` = " . $this->_id;
2007        if (!$db->getResult($queryStr)) return false;
2008        return true;
2009    } /* }}} */
2010
2011    /**
2012     * Deletes all mandatory approvers
2013     *
2014     * @return boolean true on success, otherwise false
2015     */
2016    public function delMandatoryApprovers() { /* {{{ */
2017        $db = $this->_dms->getDB();
2018
2019        $queryStr = "DELETE FROM `tblMandatoryApprovers` WHERE `userID` = " . $this->_id;
2020        if (!$db->getResult($queryStr)) return false;
2021        return true;
2022    } /* }}} */
2023
2024    /**
2025     * Deletes the  mandatory workflow
2026     *
2027     * @return boolean true on success, otherwise false
2028     */
2029    public function delMandatoryWorkflow() { /* {{{ */
2030        $db = $this->_dms->getDB();
2031        $queryStr = "DELETE FROM `tblWorkflowMandatoryWorkflow` WHERE `userid` = " . $this->_id;
2032        if (!$db->getResult($queryStr)) return false;
2033        return true;
2034    } /* }}} */
2035
2036    /**
2037     * Get all notifications of user
2038     *
2039     * @param integer $type type of item (T_DOCUMENT or T_FOLDER)
2040     * @return SeedDMS_Core_Notification[]|bool array of notifications
2041     */
2042    public function getNotifications($type = 0) { /* {{{ */
2043        $db = $this->_dms->getDB();
2044        $queryStr = "SELECT `tblNotify`.* FROM `tblNotify` ".
2045         "WHERE `tblNotify`.`userID` = ". $this->_id;
2046        if ($type) {
2047            $queryStr .= " AND `tblNotify`.`targetType` = ". (int) $type;
2048        }
2049
2050        $resArr = $db->getResultArray($queryStr);
2051        if (is_bool($resArr) && !$resArr)
2052            return false;
2053
2054        $notifications = array();
2055        foreach ($resArr as $row) {
2056            $not = new SeedDMS_Core_Notification($row["target"], $row["targetType"], $row["userID"], $row["groupID"]);
2057            $not->setDMS($this);
2058            array_push($notifications, $not);
2059        }
2060
2061        return $notifications;
2062    } /* }}} */
2063
2064    /**
2065     * Return list of personal keyword categories
2066     *
2067     * @return SeedDMS_Core_KeywordCategory[]|bool list of categories or false in case of an error
2068     */
2069    public function getKeywordCategories() { /* {{{ */
2070        $db = $this->_dms->getDB();
2071
2072        $queryStr = "SELECT * FROM `tblKeywordCategories` WHERE `owner` = ".$this->_id;
2073
2074        $resArr = $db->getResultArray($queryStr);
2075        if (is_bool($resArr) && !$resArr)
2076            return false;
2077
2078        $categories = array();
2079        foreach ($resArr as $row) {
2080            $cat = new SeedDMS_Core_KeywordCategory((int) $row["id"], $row["owner"], $row["name"]);
2081            $cat->setDMS($this->_dms);
2082            array_push($categories, $cat);
2083        }
2084
2085        return $categories;
2086    } /* }}} */
2087
2088} /* }}} */