Lines 92.39% 255 / 276
Methods 86.04% 37 / 43
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 permissionExists 92.30% 12 / 13 0.00% 0 / 1 2.00
 getEntityMapping 100.00% 41 / 41 100.00% 1 / 1 1
 addConditionLoginName 100.00% 2 / 2 100.00% 1 / 1 1
 addConditionUserId 100.00% 2 / 2 100.00% 1 / 1 1
 addConditionPassword 100.00% 2 / 2 100.00% 1 / 1 1
 addConditionXauthKey 100.00% 3 / 3 100.00% 1 / 1 1
 addConditionRoleName 100.00% 15 / 15 100.00% 1 / 1 1
 addConditionSearch 0.00% 0 / 9 0.00% 0 / 1 6
 reverseEntityMapping 100.00% 13 / 13 100.00% 1 / 1 5
 postProcess 93.75% 15 / 16 0.00% 0 / 1 7.01
 addConditionDepartmentIds 100.00% 9 / 9 100.00% 1 / 1 1
 addConditionDepartmentIdsAndSearch 0.00% 0 / 4 0.00% 0 / 1 6
 addConditionExcludeSuperusers 100.00% 15 / 15 100.00% 1 / 1 1
 addOrderByName 100.00% 2 / 2 100.00% 1 / 1 1
 addConditionWorkstationAccess 85.71% 12 / 14 0.00% 0 / 1 3.03
 [BO\Zmsbackend\Query\Base] __construct 88.23% 30 / 34 0.00% 0 / 1 10.16
 [BO\Zmsbackend\Query\Base] __toString n/a 0 / 0 n/a 0 / 0 4
 [BO\Zmsbackend\Query\Base] getName 100.00% 1 / 1 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] addSelect 100.00% 4 / 4 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] setDistinctSelect 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] setResolveLevel 100.00% 3 / 3 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] getResolveLevel 100.00% 3 / 3 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] getAlias 100.00% 5 / 5 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] getTablename 100.00% 3 / 3 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addTable 100.00% 4 / 4 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addTableAlias 100.00% 4 / 4 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addRequiredJoins 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addResolvedReferences 100.00% 11 / 11 100.00% 1 / 1 3
 [BO\Zmsbackend\Query\Base] setWithEntities 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addJoin 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] leftJoin 100.00% 5 / 5 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] innerJoin 100.00% 5 / 5 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] getSql 100.00% 2 / 2 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] getParameters 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] getReferenceMapping 100.00% 2 / 2 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] expression 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addEntityMapping 100.00% 3 / 3 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] getPrefixed 100.00% 1 / 1 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] getPrefixedList 100.00% 4 / 4 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] addReferenceMapping 100.00% 3 / 3 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] addLimit 100.00% 4 / 4 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] addValues 100.00% 2 / 2 100.00% 1 / 1 1
 [BO\Zmsbackend\Query\Base] postProcessJoins 100.00% 4 / 4 100.00% 1 / 1 2
 [BO\Zmsbackend\Query\Base] shouldLoadEntity 100.00% 3 / 3 100.00% 1 / 1 2
7class Useraccount extends \BO\Zmsbackend\Query\Base implements \BO\Zmsbackend\Query\MappingInterface
8{
9    private const array VALID_PERMISSION_NAMES = [
10        'appointment',
11        'availability',
12        'calldisplay',
13        'capacityreport',
14        'cherrypick',
15        'cluster',
16        'config',
17        'counter',
18        'customersearch',
19        'dayoff',
20        'department',
21        'emergency',
22        'finishedqueue',
23        'finishedqueuepast',
24        'jurisdiction',
25        'logs',
26        'mailtemplates',
27        'missedqueue',
28        'openqueue',
29        'organisation',
30        'overviewcalendar',
31        'parkedqueue',
32        'restrictedscope',
33        'scope',
34        'source',
35        'statistic',
36        'ticketprinter',
37        'useraccount',
38        'waitingqueue',
39        'superuser',
40    ];
41
42    /**
43     * @var String TABLE mysql table reference
44     */
45    const string TABLE = 'nutzer';
46    const string TABLE_ASSIGNMENT = 'nutzerzuordnung';
47
48    const QUERY_READ_ID_BY_USERNAME = '
49        SELECT user.`NutzerID` AS id
50        FROM ' . self::TABLE . ' user
51        WHERE
52            user.`Name`=?
53    ';
54
55    const QUERY_WRITE_ASSIGNED_DEPARTMENTS = '
56        REPLACE INTO
57            ' . self::TABLE_ASSIGNMENT . '
58        SET
59            nutzerid=?,
60            behoerdenid=?
61    ';
62
63    const QUERY_DELETE_ASSIGNED_DEPARTMENTS = '
64        DELETE FROM
65            ' . self::TABLE_ASSIGNMENT . '
66        WHERE
67            nutzerid=?
68        ORDER BY behoerdenid
69    ';
70
71    const string QUERY_DELETE_USER_ROLES = '
72        DELETE FROM user_role WHERE user_id = ?
73    ';
74
75    const string QUERY_INSERT_USER_ROLES_BY_NAME = '
76        INSERT INTO user_role (user_id, role_id)
77        SELECT ?, r.id FROM role r WHERE r.name IN (:roleNames)
78    ';
79
80    const QUERY_READ_SUPERUSER_DEPARTMENTS = '
81        SELECT behoerde.`BehoerdenID` AS id
82        FROM ' . \BO\Zmsbackend\Department\Repository\Department::TABLE . '
83        ORDER BY behoerde.Name
84    ';
85
86    const QUERY_READ_ASSIGNED_DEPARTMENTS = '
87        SELECT userAssignment.`behoerdenid` AS id
88        FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment
89        LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.Name = :useraccountName
90        WHERE
91            useraccount.`NutzerID` = userAssignment.`nutzerid`
92        ORDER BY userAssignment.`behoerdenid`
93    ';
94
95    const QUERY_READ_ASSIGNED_DEPARTMENTS_FOR_ALL = '
96        SELECT useraccount.Name as useraccountName,
97            userAssignment.`behoerdenid` AS id
98        FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment
99        LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.NutzerID = userAssignment.nutzerid
100        WHERE
101            useraccount.Name IN (:useraccountNames)
102        ORDER BY useraccount.Name, userAssignment.`behoerdenid`
103    ';
104
105    /**
106     * Build an SQL expression that checks whether the current useraccount has
107     * a permission via user_role -> role_permission -> permission.
108     */
109    protected function permissionExists(string $permissionName): \BO\Zmsbackend\Query\Builder\Expression
110    {
111        if (!in_array($permissionName, self::VALID_PERMISSION_NAMES, true)) {
112            throw new \InvalidArgumentException("Invalid permission name: $permissionName");
113        }
114        $quoted = "'" . $permissionName . "'";
115        return self::expression(
116            'EXISTS('
117            . 'SELECT 1 '
118            . 'FROM user_role ur '
119            . 'JOIN role_permission rp ON rp.role_id = ur.role_id '
120            . 'JOIN permission p ON p.id = rp.permission_id '
121            . 'WHERE ur.user_id = useraccount.NutzerID '
122            . 'AND p.name = ' . $quoted
123            . ')'
124        );
125    }
126
127    /**
128     * @return (\BO\Zmsbackend\Query\Builder\Expression|mixed|string)[]
129     *
130     */
131    #[\Override]
132    public function getEntityMapping()
133    {
134        return [
135            'id' => 'useraccount.Name',
136            'password' => 'useraccount.Passworthash',
137            'lastLogin' => 'useraccount.lastUpdate',
138            'roles' => self::expression(
139                '(SELECT GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR \',\') '
140                . 'FROM user_role ur '
141                . 'JOIN role r ON r.id = ur.role_id '
142                . 'WHERE ur.user_id = useraccount.NutzerID)'
143            ),
144            'permissions__appointment' => $this->permissionExists('appointment'),
145            'permissions__availability' => $this->permissionExists('availability'),
146            'permissions__calldisplay' => $this->permissionExists('calldisplay'),
147            'permissions__capacityreport' => $this->permissionExists('capacityreport'),
148            'permissions__cherrypick' => $this->permissionExists('cherrypick'),
149            'permissions__cluster' => $this->permissionExists('cluster'),
150            'permissions__config' => $this->permissionExists('config'),
151            'permissions__counter' => $this->permissionExists('counter'),
152            'permissions__customersearch' => $this->permissionExists('customersearch'),
153            'permissions__dayoff' => $this->permissionExists('dayoff'),
154            'permissions__department' => $this->permissionExists('department'),
155            'permissions__emergency' => $this->permissionExists('emergency'),
156            'permissions__finishedqueue' => $this->permissionExists('finishedqueue'),
157            'permissions__finishedqueuepast' => $this->permissionExists('finishedqueuepast'),
158            'permissions__jurisdiction' => $this->permissionExists('jurisdiction'),
159            'permissions__logs' => $this->permissionExists('logs'),
160            'permissions__mailtemplates' => $this->permissionExists('mailtemplates'),
161            'permissions__missedqueue' => $this->permissionExists('missedqueue'),
162            'permissions__openqueue' => $this->permissionExists('openqueue'),
163            'permissions__organisation' => $this->permissionExists('organisation'),
164            'permissions__overviewcalendar' => $this->permissionExists('overviewcalendar'),
165            'permissions__parkedqueue' => $this->permissionExists('parkedqueue'),
166            'permissions__restrictedscope' => $this->permissionExists('restrictedscope'),
167            'permissions__scope' => $this->permissionExists('scope'),
168            'permissions__source' => $this->permissionExists('source'),
169            'permissions__statistic' => $this->permissionExists('statistic'),
170            'permissions__ticketprinter' => $this->permissionExists('ticketprinter'),
171            'permissions__useraccount' => $this->permissionExists('useraccount'),
172            'permissions__waitingqueue' => $this->permissionExists('waitingqueue'),
173            'permissions__superuser' => $this->permissionExists('superuser'),
174        ];
175    }
176
177    public function addConditionLoginName($loginName): static
178    {
179        $this->query->where('useraccount.Name', '=', $loginName);
180        return $this;
181    }
182
183    public function addConditionUserId($userId): static
184    {
185        $this->query->where('useraccount.NutzerID', '=', $userId);
186        return $this;
187    }
188
189    public function addConditionPassword($password): static
190    {
191        $this->query->where('useraccount.Passworthash', '=', $password);
192        return $this;
193    }
194
195    public function addConditionXauthKey(string $xAuthKey): static
196    {
197        $this->query->where('useraccount.SessionID', '=', $xAuthKey);
198        $this->query->where('useraccount.SessionExpiry', '>', date('Y-m-d H:i:s', time() - App::SESSION_DURATION));
199        return $this;
200    }
201
202    public function addConditionRoleName(string $roleName): self
203    {
204        $this->setDistinctSelect();
205
206        $this->innerJoin(
207            new \BO\Zmsbackend\Query\Alias('user_role', 'useraccount_role'),
208            'useraccount.NutzerID',
209            '=',
210            'useraccount_role.user_id'
211        );
212
213        $this->innerJoin(
214            new \BO\Zmsbackend\Query\Alias('role', 'useraccount_role_name'),
215            'useraccount_role.role_id',
216            '=',
217            'useraccount_role_name.id'
218        );
219
220        $this->query->where('useraccount_role_name.name', '=', $roleName);
221
222        return $this;
223    }
224
225    public function addConditionSearch($queryString, bool $orWhere = false): static
226    {
227        $condition = function (\BO\Zmsbackend\Query\Builder\ConditionBuilder $query) use ($queryString) {
228            $queryString = trim($queryString);
229            $query->orWith('useraccount.NutzerID', 'LIKE', "%$queryString%");
230            $query->orWith('useraccount.Name', 'LIKE', "%$queryString%");
231        };
232        if ($orWhere) {
233            $this->query->orWhere($condition);
234        } else {
235            $this->query->where($condition);
236        }
237        return $this;
238    }
239
240    /**
241     * @return (int|mixed)[]
242     *
243     */
244    public function reverseEntityMapping(\BO\Zmsentities\Useraccount $entity): array
245    {
246        $data = array();
247        $data['Name'] = $entity->id;
248        $data['Passworthash'] = (isset($entity->password)) ? $entity->password : null;
249        $data['BehoerdenID'] = 0;
250        $department = $entity->getDepartmentList()->getFirst();
251        if (!$entity->isSuperUser() && $department !== null) {
252            $data['BehoerdenID'] = $department->id;
253        }
254        //default values because of strict mode
255        $data['notrufinitiierung'] = 0;
256        $data['notrufantwort'] = 0;
257
258        $data = array_filter($data, function ($value) {
259            return ($value !== null && $value !== false);
260        });
261        return $data;
262    }
263
264    #[\Override]
265    public function postProcess($data)
266    {
267        $data[$this->getPrefixed("lastLogin")] = ('0000-00-00' != $data[$this->getPrefixed("lastLogin")]) ?
268            strtotime($data[$this->getPrefixed("lastLogin")]) :
269            null;
270
271        $rolesKey = $this->getPrefixed('roles');
272        $rawRoles = $data[$rolesKey] ?? null;
273        if ($rawRoles === null || $rawRoles === '') {
274            $data[$rolesKey] = [];
275        } elseif (is_string($rawRoles)) {
276            $data[$rolesKey] = array_values(array_filter(array_map('trim', explode(',', $rawRoles)), function ($v) {
277                return $v !== '';
278            }));
279        }
280
281        $permissionsPrefix = $this->getPrefixed('permissions__');
282        foreach ($data as $key => $value) {
283            if (0 === strpos($key, $permissionsPrefix)) {
284                $data[$key] = (bool) $value;
285            }
286        }
287
288        return $data;
289    }
290
291    public function addConditionDepartmentIds(array $departmentIds): static
292    {
293        $this->setDistinctSelect();
294        $this->innerJoin(
295            new \BO\Zmsbackend\Query\Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'),
296            'useraccount.NutzerID',
297            '=',
298            'useraccount_department.nutzerid'
299        );
300        $this->query->where('useraccount_department.behoerdenid', 'IN', $departmentIds);
301        return $this;
302    }
303
304    public function addConditionDepartmentIdsAndSearch(array $departmentIds, $queryString = null, bool $orWhere = false): self
305    {
306        $this->addConditionDepartmentIds($departmentIds);
307
308        if ($queryString) {
309            $this->addConditionSearch($queryString, $orWhere);
310        }
311
312        return $this;
313    }
314
315    public function addConditionExcludeSuperusers(): self
316    {
317        $this->setDistinctSelect();
318
319        $this->innerJoin(
320            new \BO\Zmsbackend\Query\Alias('user_role', 'exclude_superuser_user_role'),
321            'useraccount.NutzerID',
322            '=',
323            'exclude_superuser_user_role.user_id'
324        );
325
326        $this->innerJoin(
327            new \BO\Zmsbackend\Query\Alias('role', 'exclude_superuser_role'),
328            'exclude_superuser_user_role.role_id',
329            '=',
330            'exclude_superuser_role.id'
331        );
332
333        $this->query->where('exclude_superuser_role.name', '!=', 'system_admin');
334
335        return $this;
336    }
337
338    public function addOrderByName(): self
339    {
340        $this->query->orderBy('useraccount.Name', 'ASC');
341        return $this;
342    }
343
344    /**
345     * @SuppressWarnings(UnusedFormalParameter)
346     *
347     * @param false $isWorkstationSuperuser
348     */
349    public function addConditionWorkstationAccess($workstationUserId, array $workstationDepartmentIds, bool $isWorkstationSuperuser = false): self
350    {
351        // Superusers can access all useraccounts, no filtering needed
352        if ($isWorkstationSuperuser) {
353            return $this;
354        }
355
356        $this->addConditionExcludeSuperusers();
357
358        // If no departments, only exclude superusers (already done above)
359        if (empty($workstationDepartmentIds)) {
360            return $this;
361        }
362
363        // Ensure we have a join to nutzerzuordnung for target useraccounts
364        $this->setDistinctSelect();
365        $this->innerJoin(
366            new \BO\Zmsbackend\Query\Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'),
367            'useraccount.NutzerID',
368            '=',
369            'useraccount_department.nutzerid'
370        );
371
372        // Target useraccount must share at least one department with workstation user
373        $this->query->where('useraccount_department.behoerdenid', 'IN', $workstationDepartmentIds);
374
375        return $this;
376    }
377}

Inherited from BO\Zmsbackend\Query\Base

96    public function __construct(
97        $queryType,
98        $prefix = '',
99        string|false $name = false,
100        mixed $resolveLevel = null,
101        array $withEntities = []
102    ) {
103        $this->prefix = $prefix;
104        $this->name = $name;
105        $this->withEntities = $withEntities;
106        $this->setResolveLevel($resolveLevel);
107        $dialect = new MySQL();
108        if (self::SELECT === $queryType) {
109            $this->query = new Select($dialect);
110            $this->addSelect();
111        } elseif (self::INSERT === $queryType) {
112            $this->query = new Insert($dialect);
113            $this->addTable();
114        } elseif (self::UPDATE === $queryType) {
115            $this->query = new Update($dialect);
116            $this->addTableAlias();
117        } elseif (self::REPLACE === $queryType) {
118            $this->query = new INSERT($dialect);
119            $this->query->queryBaseStatement('REPLACE INTO');
120            $this->addTable();
121        } elseif (self::DELETE === $queryType) {
122            $this->query = new Delete($dialect);
123            $this->query->queryBaseStatement('DELETE ' . $this::getAlias() . ' FROM');
124            $this->addTableAlias();
125        } elseif ($queryType instanceof self) {
126            $this->query = $queryType->query;
127            // Share join-alias state with the parent query (intentional by-ref).
128            /** @psalm-suppress UnsupportedPropertyReferenceUsage */
129            $this->joinedAliasList =& $queryType->joinedAliasList;
130            $this->resolveLevel = $queryType->resolveLevel - 1;
131        } elseif ($queryType instanceof QueryBuilder) {
132            $this->query = $queryType;
133        } else {
134            throw new \InvalidArgumentException(
135                'Unsupported query type for ' . static::class . ': '
136                . (is_object($queryType) ? $queryType::class : gettype($queryType))
137            );
138        }
139        if ($this->query instanceof Select) {
140            $this->addRequiredJoins();
141        }
142    }
147    public function __toString()
148    {
149        if ($this->name) {
150            $name = $this->name . '_' . $this->prefix . (string) $this->resolveLevel;
151            if (!isset(static::$sqlCache[$name])) {
152                static::$sqlCache[$name] = $this->getSql();
153            }
154            return static::$sqlCache[$name];
155        }
156        if ($this->currentSqlString) {
157            $sql = $this->currentSqlString;
158        } else {
159            $sql = $this->getSql();
160        }
161        return $sql;
162    }
164    public function getName()
165    {
166        return $this->name ? $this->name : get_class($this);
167    }
174    protected function addSelect(): static
175    {
176        $table = $this::getTablename();
177        $alias = $this::getAlias();
178        $this->query->from($table, $alias);
179        return $this;
180    }
182    public function setDistinctSelect(): void
183    {
184        $this->query->queryBaseStatement('SELECT DISTINCT');
185    }
187    public function setResolveLevel(int|null $resolveLevel): static
188    {
189        if ($resolveLevel !== null) {
190            $this->resolveLevel = $resolveLevel;
191        }
192        return $this;
193    }
195    public function getResolveLevel()
196    {
197        if (null === $this->resolveLevel) {
198            throw new \Exception("Required setting for resolveReferenceLevel missing in " . get_class($this));
199        }
200        return $this->resolveLevel;
201    }
210    public static function getAlias()
211    {
212        $class = get_called_class();
213        $alias = constant($class . '::ALIAS');
214        if (null === $alias) {
215            $alias = lcfirst(preg_replace('#^.*\\\#', '', $class));
216        }
217        return $alias;
218    }
225    public static function getTablename()
226    {
227        $class = get_called_class();
228        $table = constant($class . '::TABLE');
229        return $table;
230    }
237    protected function addTable(): static
238    {
239        $table = $this::getTablename();
240        $alias = $this::getAlias();
241        $this->query->table($table, $alias);
242        return $this;
243    }
250    protected function addTableAlias(): static
251    {
252        $table = $this::getTablename();
253        $alias = $this::getAlias();
254        $this->query->table(self::expression($table . ' ' . $alias));
255        return $this;
256    }
264    protected function addRequiredJoins()
265    {
266    }
273    public function addResolvedReferences($depth): static
274    {
275        $this->setResolveLevel($depth);
276        if ($depth > 0) {
277            $queryList = $this->addJoin();
278            foreach ($queryList as $query) {
279                $query->setResolveLevel($depth);
280                $query->setWithEntities($this->withEntities);
281                $query->addResolvedReferences($depth - 1);
282                $query->addEntityMapping();
283            }
284            $this->joinedQueryList = $queryList;
285        } else {
286            $this->addReferenceMapping();
287        }
288        return $this;
289    }
294    public function setWithEntities($withEntities = []): void
295    {
296        $this->withEntities = $withEntities;
297    }
304    protected function addJoin()
305    {
306        return [];
307    }
309    protected function leftJoin(Alias $alias, string|Expression|null $left = null, string|null $operator = null, string|null $right = null): QueryBuilder
310    {
311        $aliasId = $alias->getAliasIdentifier();
312        if (!in_array($aliasId, $this->joinedAliasList)) {
313            $this->joinedAliasList[] = $aliasId;
314            $this->query->leftJoin($alias, $left, $operator, $right);
315        } else {
316            //throw new \Exception("Tried to add Alias ".$aliasId);
317        }
318        return $this->query;
319    }
321    protected function innerJoin(Alias $alias, string|null $left = null, string|null $operator = null, string|null $right = null): QueryBuilder
322    {
323        $aliasId = $alias->getAliasIdentifier();
324        if (!in_array($aliasId, $this->joinedAliasList)) {
325            $this->joinedAliasList[] = $aliasId;
326            $this->query->join($alias, $left, $operator, $right);
327        }
328        return $this->query;
329    }
337    public function getSql()
338    {
339        $this->currentSqlString = (string)$this->query;
340        return $this->currentSqlString;
341    }
348    public function getParameters()
349    {
350        return $this->query->params();
351    }
357    public function getReferenceMapping()
358    {
359        return [
360        ];
361    }
368    protected static function expression(string $string)
369    {
370        return new Expression($string);
371    }
379    public function addEntityMapping(mixed $type = null): static
380    {
381        // Concrete query classes provide getEntityMapping(); not all declare MappingInterface.
382        /** @psalm-suppress UndefinedMethod, TooManyArguments */
383        $entityMapping = $this->getPrefixedList($this->getEntityMapping($type));
384        $this->query->select($entityMapping);
385        return $this;
386    }
388    protected function getPrefixed($prefix): string
389    {
390        return $this->prefix . $prefix;
391    }
393    protected function getPrefixedList(array $unprefixedList): array
394    {
395        $prefixed = [];
396        foreach ($unprefixedList as $key => $value) {
397            $prefixed[$this->getPrefixed($key)] = $value;
398        }
399        return $prefixed;
400    }
405    protected function addReferenceMapping(): static
406    {
407        $referenceMapping = $this->getPrefixedList($this->getReferenceMapping());
408        $this->query->select($referenceMapping);
409        return $this;
410    }
412    public function addLimit(int $count, ?int $offset = null): static
413    {
414        $this->query->limit($count);
415        if ($offset) {
416            $this->query->offset($offset);
417        }
418        return $this;
419    }
424    public function addValues(array $values): static
425    {
426        $this->query->values($values);
427        return $this;
428    }
445    public function postProcessJoins(array $data)
446    {
447        $data = $this->postProcess($data);
448        foreach ($this->joinedQueryList as $query) {
449            $data = $query->postProcess($data);
450        }
451        return $data;
452    }
454    public function shouldLoadEntity(string $name): bool
455    {
456        if (empty($this->withEntities)) {
457            return true;
458        }
459
460        return in_array($name, $this->withEntities);
461    }