Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
61.90% covered (warning)
61.90%
52 / 84
57.14% covered (warning)
57.14%
8 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
Useraccount
61.90% covered (warning)
61.90%
52 / 84
57.14% covered (warning)
57.14%
8 / 14
55.84
0.00% covered (danger)
0.00%
0 / 1
 getEntityMapping
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
1
 addConditionLoginName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addConditionUserId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addConditionPassword
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addConditionXauthKey
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addConditionRoleLevel
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 addConditionSearch
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 reverseEntityMapping
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
 postProcess
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 addConditionDepartmentIds
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 addConditionDepartmentIdsAndSearch
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 addConditionExcludeSuperusers
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 addOrderByName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addConditionWorkstationAccess
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace BO\Zmsdb\Query;
4
5use BO\Slim\Application as App;
6
7class Useraccount extends Base implements MappingInterface
8{
9    /**
10     * @var String TABLE mysql table reference
11     */
12    const TABLE = 'nutzer';
13    const TABLE_ASSIGNMENT = 'nutzerzuordnung';
14
15    const QUERY_READ_ID_BY_USERNAME = '
16        SELECT user.`NutzerID` AS id
17        FROM ' . self::TABLE . ' user
18        WHERE
19            user.`Name`=?
20    ';
21
22    const QUERY_WRITE_ASSIGNED_DEPARTMENTS = '
23        REPLACE INTO
24            ' . self::TABLE_ASSIGNMENT . '
25        SET
26            nutzerid=?,
27            behoerdenid=?
28    ';
29
30    const QUERY_DELETE_ASSIGNED_DEPARTMENTS = '
31        DELETE FROM
32            ' . self::TABLE_ASSIGNMENT . '
33        WHERE
34            nutzerid=?
35        ORDER BY behoerdenid
36    ';
37
38    const QUERY_READ_SUPERUSER_DEPARTMENTS = '
39        SELECT behoerde.`BehoerdenID` AS id
40        FROM ' . Department::TABLE . '
41        ORDER BY behoerde.Name
42    ';
43
44    const QUERY_READ_ASSIGNED_DEPARTMENTS = '
45        SELECT userAssignment.`behoerdenid` AS id
46        FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment
47        LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.Name = :useraccountName
48        WHERE
49            useraccount.`NutzerID` = userAssignment.`nutzerid`
50        ORDER BY userAssignment.`behoerdenid`
51    ';
52
53    const QUERY_READ_ASSIGNED_DEPARTMENTS_FOR_ALL = '
54        SELECT useraccount.Name as useraccountName,
55            userAssignment.`behoerdenid` AS id
56        FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment
57        LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.NutzerID = userAssignment.nutzerid
58        WHERE
59            useraccount.Name IN (:useraccountNames)
60        ORDER BY useraccount.Name, userAssignment.`behoerdenid`
61    ';
62
63    public function getEntityMapping()
64    {
65        return [
66            'id' => 'useraccount.Name',
67            'password' => 'useraccount.Passworthash',
68            'lastLogin' => 'useraccount.lastUpdate',
69            'rights__superuser' => self::expression('`useraccount`.`Berechtigung` = 90'),
70            'rights__organisation' => self::expression('`useraccount`.`Berechtigung` >= 70'),
71            'rights__department' => self::expression('`useraccount`.`Berechtigung` >= 50'),
72            'rights__cluster' => self::expression('`useraccount`.`Berechtigung` >= 40'),
73            'rights__useraccount' => self::expression('`useraccount`.`Berechtigung` >= 40'),
74            'rights__scope' => self::expression('`useraccount`.`Berechtigung` >= 30'),
75            'rights__departmentStats' => self::expression('`useraccount`.`Berechtigung` >= 25'),
76            'rights__availability' => self::expression('`useraccount`.`Berechtigung` >= 20'),
77            'rights__ticketprinter' => self::expression('`useraccount`.`Berechtigung` >= 15'),
78            'rights__audit' => self::expression('`useraccount`.`Berechtigung` = 5 OR `useraccount`.`Berechtigung` = 90'),
79            'rights__basic' => self::expression('`useraccount`.`Berechtigung` >= 0'),
80        ];
81    }
82
83    public function addConditionLoginName($loginName)
84    {
85        $this->query->where('useraccount.Name', '=', $loginName);
86        return $this;
87    }
88
89    public function addConditionUserId($userId)
90    {
91        $this->query->where('useraccount.NutzerID', '=', $userId);
92        return $this;
93    }
94
95    public function addConditionPassword($password)
96    {
97        $this->query->where('useraccount.Passworthash', '=', $password);
98        return $this;
99    }
100
101    public function addConditionXauthKey($xAuthKey)
102    {
103        $this->query->where('useraccount.SessionID', '=', $xAuthKey);
104        $this->query->where('useraccount.SessionExpiry', '>', date('Y-m-d H:i:s', time() - App::SESSION_DURATION));
105        return $this;
106    }
107
108    public function addConditionRoleLevel($roleLevel)
109    {
110        $this->query->where('useraccount.Berechtigung', '=', $roleLevel);
111        return $this;
112    }
113
114    public function addConditionSearch($queryString, $orWhere = false)
115    {
116        $condition = function (\BO\Zmsdb\Query\Builder\ConditionBuilder $query) use ($queryString) {
117            $queryString = trim($queryString);
118            $query->orWith('useraccount.NutzerID', 'LIKE', "%$queryString%");
119            $query->orWith('useraccount.Name', 'LIKE', "%$queryString%");
120        };
121        if ($orWhere) {
122            $this->query->orWhere($condition);
123        } else {
124            $this->query->where($condition);
125        }
126        return $this;
127    }
128
129    public function reverseEntityMapping(\BO\Zmsentities\Useraccount $entity)
130    {
131        $data = array();
132        $data['Name'] = $entity->id;
133        $data['Passworthash'] = (isset($entity->password)) ? $entity->password : null;
134        $data['Berechtigung'] = $entity->getRightsLevel();
135        $data['BehoerdenID'] = 0;
136        if (!$entity->isSuperUser() && isset($entity->departments) && 0 < $entity->departments->count()) {
137            $data['BehoerdenID'] = $entity->departments->getFirst()->id;
138        }
139        //default values because of strict mode
140        $data['notrufinitiierung'] = 0;
141        $data['notrufantwort'] = 0;
142
143        $data = array_filter($data, function ($value) {
144            return ($value !== null && $value !== false);
145        });
146        return $data;
147    }
148
149    public function postProcess($data)
150    {
151        $data[$this->getPrefixed("lastLogin")] = ('0000-00-00' != $data[$this->getPrefixed("lastLogin")]) ?
152            strtotime($data[$this->getPrefixed("lastLogin")]) :
153            null;
154        return $data;
155    }
156
157    public function addConditionDepartmentIds(array $departmentIds)
158    {
159        $this->setDistinctSelect();
160        $this->innerJoin(
161            new Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'),
162            'useraccount.NutzerID',
163            '=',
164            'useraccount_department.nutzerid'
165        );
166        $this->query->where('useraccount_department.behoerdenid', 'IN', $departmentIds);
167        return $this;
168    }
169
170    public function addConditionDepartmentIdsAndSearch(array $departmentIds, $queryString = null, $orWhere = false): self
171    {
172        $this->addConditionDepartmentIds($departmentIds);
173
174        if ($queryString) {
175            $this->addConditionSearch($queryString, $orWhere);
176        }
177
178        return $this;
179    }
180
181    public function addConditionExcludeSuperusers(): self
182    {
183        $this->query->where('useraccount.Berechtigung', '!=', 90);
184        return $this;
185    }
186
187    public function addOrderByName(): self
188    {
189        $this->query->orderBy('useraccount.Name', 'ASC');
190        return $this;
191    }
192
193    /**
194     * @SuppressWarnings(UnusedFormalParameter)
195     */
196    public function addConditionWorkstationAccess($workstationUserId, array $workstationDepartmentIds, $isWorkstationSuperuser = false): self
197    {
198        // Superusers can access all useraccounts, no filtering needed
199        if ($isWorkstationSuperuser) {
200            return $this;
201        }
202
203        // Always exclude superusers for non-superuser workstation users
204        $this->query->where('useraccount.Berechtigung', '!=', 90);
205
206        // If no departments, only exclude superusers (already done above)
207        if (empty($workstationDepartmentIds)) {
208            return $this;
209        }
210
211        // Ensure we have a join to nutzerzuordnung for target useraccounts
212        $this->setDistinctSelect();
213        $this->innerJoin(
214            new Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'),
215            'useraccount.NutzerID',
216            '=',
217            'useraccount_department.nutzerid'
218        );
219
220        // Target useraccount must share at least one department with workstation user
221        $this->query->where('useraccount_department.behoerdenid', 'IN', $workstationDepartmentIds);
222
223        return $this;
224    }
225}