| Code Coverage
| Lines | Functions and Methods | Classes and Traits
Total | 22.99% covered (danger) | 22.99% | 60 / 261 | 26.92% covered (danger) | 26.92% | 7 / 26 | CRAP | 0.00% covered (danger) | 0.00% | 0 / 1
User | 22.99% covered (danger) | 22.99% | 60 / 261 | 26.92% covered (danger) | 26.92% | 7 / 26 | 1335.98 | 0.00% covered (danger) | 0.00% | 0 / 1
__construct | 63.64% covered (warning) | 63.64% | 21 / 33 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.43 |
getDeptName | 0.00% covered (danger) | 0.00% | 0 / 10 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 |
getDeptId | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getPublishedData | 0.00% covered (danger) | 0.00% | 0 / 16 | 0.00% covered (danger) | 0.00% | 0 / 1 | 6 |
isAdmin | 92.31% covered (success) | 92.31% | 12 / 13 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.00 |
isRoot | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
canAdd | 80.00% covered (warning) | 80.00% | 4 / 5 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.07 |
canCheckIn | 80.00% covered (warning) | 80.00% | 4 / 5 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.07 |
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 | 16.67% covered (danger) | 16.67% | 2 / 12 | 0.00% covered (danger) | 0.00% | 0 / 1 | 8.21 |
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 | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getPhoneNumber | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getFullName | 100.00% covered (success) | 100.00% | 4 / 4 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getUserName | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getCheckedOutFiles | 0.00% covered (danger) | 0.00% | 0 / 11 | 0.00% covered (danger) | 0.00% | 0 / 1 | 12 |
getAllUsers | 100.00% covered (success) | 100.00% | 8 / 8 | 100.00% covered (success) | 100.00% | 1 / 1 | 2 |

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 |
23 | if (!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 | }