Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
6.51% covered (danger)
6.51%
17 / 261
0.00% covered (danger)
0.00%
0 / 26
CRAP
0.00% covered (danger)
0.00%
0 / 1
User
6.51% covered (danger)
6.51%
17 / 261
0.00% covered (danger)
0.00%
0 / 26
2348.09
0.00% covered (danger)
0.00%
0 / 1
 __construct
51.52% covered (warning)
51.52%
17 / 33
0.00% covered (danger)
0.00%
0 / 1
4.03
 getDeptName
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 getDeptId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPublishedData
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 isAdmin
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 isRoot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 canAdd
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 canCheckIn
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getPassword
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 changePassword
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 validatePassword
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
12
 changeName
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 isReviewer
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 isReviewerForFile
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 getAllRevieweeIds
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 getRevieweeIds
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 getAllRejectedFileIds
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 getRejectedFileIds
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getExpiredFileIds
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getNumExpiredFiles
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getEmailAddress
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPhoneNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFullName
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getUserName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCheckedOutFiles
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 getAllUsers
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/*
3 * Copyright (C) 2000-2021. Stephen Lawrence
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20// (C) 2002-2004 Stephen Lawrence Jr., Khoa Nguyen
21// Container for user related info
22
23if (!defined('User_class')) {
24    define('User_class', 'true', false);
25
26    class User extends databaseData
27    {
28        public $root_id;
29        public $id;
30        public $username;
31        public $first_name;
32        public $last_name;
33        public $email;
34        public $phone;
35        public $department;
36        public $pw_reset_code;
37        public $can_add;
38        public $can_checkin;
39
40        /**
41         * @param int $id
42         * @param PDO $connection
43         */
44        public function __construct($id, PDO $connection)
45        {
46            $this->root_id = $GLOBALS['CONFIG']['root_id'];
47            $this->field_name = 'username';
48            $this->field_id = 'id';
49            $this->tablename = $this->TABLE_USER;
50            $this->result_limit = 1; //there is only 1 user with a certain user_name or user_id
51
52            // Set connection and initialize without calling setId yet
53            $this->connection = $connection;
54            
55            // Add error handling for setId call
56            try {
57                // Now we can safely call setId since tablename is set
58                $this->setId($id);
59            } catch (Exception $e) {
60                error_log("User constructor error: " . $e->getMessage());
61                $this->error = "Failed to initialize user with ID: " . $id;
62                return;
63            }
64
65            $query = "
66                    SELECT 
67                        id, 
68                        username, 
69                        department, 
70                        phone, 
71                        email, 
72                        last_name, 
73                        first_name, 
74                        pw_reset_code,
75                        can_add,
76                        can_checkin
77                    FROM 
78                        {$GLOBALS['CONFIG']['db_prefix']}user 
79                    WHERE 
80                        id = :id";
81            $stmt = $this->connection->prepare($query);
82            $stmt->execute(array(':id' => $this->id));
83            $result = $stmt->fetch();
84
85            // Check if user was found in database
86            if ($result === false) {
87                $this->error = "User not found in database for ID: " . $this->id;
88                error_log("User constructor - User not found for ID: " . $this->id);
89                return;
90            }
91
92            list(
93                    $this->id,
94                    $this->username,
95                    $this->department,
96                    $this->phone,
97                    $this->email,
98                    $this->last_name,
99                    $this->first_name,
100                    $this->pw_reset_code,
101                    $this->can_add,
102                    $this->can_checkin
103            ) = $result;
104        }
105
106        /**
107         * Return department name for current user
108         * @return string
109         */
110        public function getDeptName()
111        {
112            $query = "
113              SELECT
114                d.name
115              FROM
116                {$GLOBALS['CONFIG']['db_prefix']}department d,
117                {$GLOBALS['CONFIG']['db_prefix']}user u
118              WHERE
119                u.id = :id
120              AND
121                u.department = d.id";
122            $stmt = $this->connection->prepare($query);
123            $stmt->execute(array(
124                ':id' => $this->id
125            ));
126            $result = $stmt->fetchColumn();
127
128            return $result;
129        }
130
131        /**
132         * Return department ID for current user
133         * @return string
134         */
135        public function getDeptId()
136        {
137            return $this->department;
138        }
139
140        /**
141         * Return an array of publishable documents
142         * @return array
143         * @param object $publishable
144         */
145        public function getPublishedData($publishable)
146        {
147            $data_published = array();
148            $index = 0;
149            $query = "
150              SELECT
151                d.id
152              FROM
153                {$GLOBALS['CONFIG']['db_prefix']}data d,
154                {$GLOBALS['CONFIG']['db_prefix']}user u
155              WHERE
156                d.owner = :id
157              AND
158                u.id = d.owner
159              AND
160                d.publishable = :publishable ";
161            $stmt = $this->connection->prepare($query);
162            $stmt->execute(array(
163                ':publishable' => $publishable,
164                ':id' => $this->id
165            ));
166            $result = $stmt->fetchAll();
167
168            foreach ($result as $row) {
169                $data_published[$index] = $row;
170                $index++;
171            }
172            return $data_published;
173        }
174
175        /**
176         * Check whether user from object has Admin rights
177         * @return Boolean
178         */
179        public function isAdmin()
180        {
181            if ($this->isRoot()) {
182                return true;
183            }
184            $query = "
185              SELECT
186                admin
187              FROM
188                {$GLOBALS['CONFIG']['db_prefix']}admin
189              WHERE
190                id = :id
191            ";
192            $stmt = $this->connection->prepare($query);
193            $stmt->execute(array(
194                ':id' => $this->id
195            ));
196            $result = $stmt->fetchColumn();
197
198            if ($stmt->rowCount() !=1) {
199                return false;
200            }
201
202            return $result;
203        }
204
205        /**
206         * Check whether user from object is root
207         * @return bool
208         */
209        public function isRoot()
210        {
211            return ($this->root_id == $this->getId());
212        }
213
214        /**
215        * @return boolean
216        */
217        public function canAdd()
218        {
219            if ($this->isAdmin()) {
220                return true;
221            }
222            if ($this->can_add) {
223                return true;
224            }
225            return false;
226        }
227        
228        /**
229        * @return boolean
230        */
231        public function canCheckIn()
232        {
233            if ($this->isAdmin()) {
234                return true;
235            }
236            if ($this->can_checkin) {
237                return true;
238            }
239            return false;
240        }
241
242        /**
243         * @return string
244         */
245        public function getPassword()
246        {
247            $query = "
248              SELECT
249                password
250              FROM
251                $this->tablename
252              WHERE
253                id = :id
254            ";
255            $stmt = $this->connection->prepare($query);
256            $stmt->execute(array(':id' => $this->id));
257            $result = $stmt->fetchColumn();
258
259            if ($stmt->rowCount() !=1) {
260                header('Location:' . $GLOBALS['CONFIG']['base_url'] . 'error?ec=14');
261                exit;
262            }
263
264            return $result;
265        }
266
267        /**
268         * @param string $non_encrypted_password
269         * @return bool
270         */
271        public function changePassword($non_encrypted_password)
272        {
273            $query = "
274              UPDATE
275                $this->tablename
276              SET
277                password = md5(:non_encrypted_password)
278              WHERE
279                id = :id
280            ";
281            $stmt = $this->connection->prepare($query);
282            $stmt->execute(array(
283                ':non_encrypted_password' => $non_encrypted_password,
284                ':id' => $this->id
285            ));
286            return true;
287        }
288
289        /**
290         * @param string $non_encrypted_password
291         * @return bool
292         */
293        public function validatePassword($non_encrypted_password)
294        {
295            $query = "
296              SELECT
297                username
298              FROM
299                $this->tablename
300              WHERE
301                id = :id
302              AND
303                password = md5(:non_encrypted_password)
304            ";
305            $stmt = $this->connection->prepare($query);
306            $stmt->execute(array(
307                ':non_encrypted_password' => $non_encrypted_password,
308                ':id' => $this->id
309            ));
310            if ($stmt->rowCount() == 1) {
311                return true;
312            } else {
313                // Check the old password() style user password
314                $query = "
315                  SELECT
316                    username
317                  FROM
318                    $this->tablename
319                  WHERE
320                    id = :id
321                  AND
322                    password = password(:non_encrypted_password)
323                ";
324                $stmt = $this->connection->prepare($query);
325                $stmt->execute(array(
326                    ':non_encrypted_password' => $non_encrypted_password,
327                    ':id' => $this->id
328                ));
329                if ($stmt->rowCount() == 1) {
330                    return true;
331                }
332            }
333            return false;
334        }
335
336        /**
337         * @param string $new_name
338         * @return bool
339         */
340        public function changeName($new_name)
341        {
342            $query = "
343              UPDATE
344                $this->tablename
345              SET
346                username = :new_name
347              WHERE
348                id = :id
349            ";
350            $stmt = $this->connection->prepare($query);
351            $stmt->execute(array(
352                ':new_name' => $new_name,
353                ':id' => $this->id
354            ));
355            return true;
356        }
357
358       /**
359        *   Determine if the current user is a reviewer or not
360        *   @return boolean
361        */
362        public function isReviewer()
363        {
364            // If they are an admin, they can review
365            if ($this->isAdmin()) {
366                return true;
367            }
368            
369            // Lets see if this non-admin user has a department they can review for, if so, they are a reviewer
370            $query = "
371            SELECT
372              dept_id
373            FROM
374              {$GLOBALS['CONFIG']['db_prefix']}dept_reviewer
375            WHERE
376              user_id = :id
377            ";
378            $stmt = $this->connection->prepare($query);
379            $stmt->execute(array(
380                ':id' => $this->id
381            ));
382            if ($stmt->rowCount() > 0) {
383                return true;
384            } else {
385                return false;
386            }
387        }
388
389       /**
390        * Determine if the current user is a reviewer for a specific ID
391        * @param int $file_id
392        * @return boolean
393        */
394        public function isReviewerForFile($file_id)
395        {
396            $query = "SELECT
397                            d.id
398                      FROM
399                            {$GLOBALS['CONFIG']['db_prefix']}data as d,
400                            {$GLOBALS['CONFIG']['db_prefix']}dept_reviewer as dr
401                      WHERE
402                            
403                            dr.dept_id = d.department AND
404                            dr.user_id = :user_id AND
405                            d.department = dr.dept_id AND
406                            d.id = :file_id
407                            ";
408            $stmt = $this->connection->prepare($query);
409            $stmt->execute(array(
410                ':user_id' => $this->id,
411                ':file_id' => $file_id
412            ));
413
414            $num_rows = $stmt->rowCount();
415            if ($num_rows < 1) {
416                return false;
417            }
418            return true;
419        }
420
421        /**
422         * this functions assume that you are an admin thus allowing you to review all departments
423         * @return array
424         */
425        public function getAllRevieweeIds()
426        {
427            if ($this->isAdmin()) {
428                $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}$this->TABLE_DATA WHERE publishable = 0";
429                $stmt = $this->connection->prepare($query);
430                $stmt->execute(array());
431                $result = $stmt->fetchAll();
432
433                $file_data = array();
434                $index = 0;
435                foreach ($result as $row) {
436                    $file_data[$index] = $row[0];
437                    $index++;
438                }
439
440                return $file_data;
441            }
442        }
443        
444        /**
445         * getRevieweeIds - Return an array of files that need reviewing under this person
446         * @return array
447         */
448        public function getRevieweeIds()
449        {
450            if ($this->isReviewer()) {
451                // Which departments can this user review?
452                $query = "SELECT dept_id FROM {$GLOBALS['CONFIG']['db_prefix']}$this->TABLE_DEPT_REVIEWER WHERE user_id = :id";
453                $stmt = $this->connection->prepare($query);
454                $stmt->execute(array(
455                    ':id' => $this->id
456                ));
457                $result = $stmt->fetchAll();
458
459                $num_depts = $stmt->rowCount();
460                $index = 0;
461                // Build the query
462                $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}data WHERE (";
463                foreach ($result as $row) {
464                    $dept = $row['dept_id'];
465                    if ($index != $num_depts -1) {
466                        $query = $query . " department = :dept OR ";
467                    } else {
468                        $query = $query . " department = :dept )";
469                    }
470                    $index++;
471                }
472                $query = $query . " AND publishable = 0";
473
474                $stmt = $this->connection->prepare($query);
475                $stmt->execute(array(':dept' => $dept));
476                $result = $stmt->fetchAll();
477
478                $file_data = array();
479                $num_files = $stmt->rowCount();
480
481                for ($index = 0; $index< $num_files; $index++) {
482                    $fid = $result[$index]['id'];
483                    $file_data[$index] = $fid;
484                }
485                return $file_data;
486            }
487        }
488
489        /**
490         * @return array
491         */
492        public function getAllRejectedFileIds()
493        {
494            $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}$this->TABLE_DATA WHERE publishable = '-1'";
495            $stmt = $this->connection->prepare($query);
496            $stmt->execute();
497            $result = $stmt->fetchAll();
498
499            $file_data = array();
500            $num_files = $stmt->rowCount();
501
502            for ($index = 0; $index< $num_files; $index++) {
503                list($fid) = $result[$index];
504                $file_data[$index] = $fid;
505            }
506            return $file_data;
507        }
508
509        /**
510         * @return array
511         */
512        public function getRejectedFileIds()
513        {
514            $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}data WHERE publishable = '-1' and owner = :id";
515            $stmt = $this->connection->prepare($query);
516            $stmt->execute(array(
517                ':id' => $this->id
518            ));
519            $result = $stmt->fetchAll();
520
521            $file_data = array();
522            $num_files = $stmt->rowCount();
523
524            for ($index = 0; $index< $num_files; $index++) {
525                list($fid) = $result[$index];
526                $file_data[$index] = $fid;
527            }
528            return $file_data;
529        }
530
531        /**
532         * @return array
533         */
534        public function getExpiredFileIds()
535        {
536            $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}data WHERE status = -1 AND owner = :id";
537            $stmt = $this->connection->prepare($query);
538            $stmt->execute(array(
539                ':id' => $this->id
540            ));
541            $result = $stmt->fetchAll();
542
543            $len = $stmt->rowCount();
544            $file_data = array();
545
546            for ($index = 0; $index< $len; $index++) {
547                list($fid) = $result[$index];
548                $file_data[$index] = $fid;
549            }
550            return $file_data;
551        }
552
553        /**
554         * @return int
555         */
556        public function getNumExpiredFiles()
557        {
558            $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}data WHERE status =- 1 AND owner = :id";
559            $stmt = $this->connection->prepare($query);
560            $stmt->execute(array(
561                ':id' => $this->id
562            ));
563            return $stmt->rowCount();
564        }
565
566        /**
567         * @return mixed
568         */
569        public function getEmailAddress()
570        {
571            return $this->email;
572        }
573
574        /**
575         * @return mixed
576         */
577        public function getPhoneNumber()
578        {
579            return $this->phone;
580        }
581
582        /**
583         * /Return full name array where array[0]=firstname and array[1]=lastname
584         * @return mixed
585         */
586        public function getFullName()
587        {
588            $full_name = array();
589            $full_name[0] = $this->first_name;
590            $full_name[1] = $this->last_name;
591
592            return $full_name;
593        }
594
595        /**
596         * Return username of current user
597         * @return mixed
598         */
599        public function getUserName()
600        {
601            return $this->username;
602        }
603
604        /**
605         * Return list of checked out files to root
606         * @return array
607         */
608        public function getCheckedOutFiles()
609        {
610            if ($this->isRoot()) {
611                $query = "SELECT id FROM {$GLOBALS['CONFIG']['db_prefix']}data WHERE status > 0";
612                $stmt = $this->connection->prepare($query);
613                $stmt->execute();
614                $result = $stmt->fetchAll();
615
616                $len = $stmt->rowCount();
617                $file_data = array();
618                for ($index = 0; $index < $len; $index++) {
619                    list($fid) = $result[$index];
620                    $file_data[$index] = $fid;
621                }
622                return $file_data;
623            }
624        }
625
626        /**
627         * getAllUsers - Returns an array of all the active users
628         * @param $pdo
629         * @return array
630         */
631        public static function getAllUsers(PDO $pdo)
632        {
633            $userListArray = array();
634            // query to get a list of available users
635            $query = "SELECT id, username, first_name, last_name FROM {$GLOBALS['CONFIG']['db_prefix']}user ORDER BY username";
636            $stmt = $pdo->prepare($query);
637            $stmt->execute();
638            $result = $stmt->fetchAll();
639            foreach ($result as $row) {
640                $userListArray[] = $row;
641            }
642            return $userListArray;
643        }
644    }
645}