*/ public function findPaginated( string $tenantId, ?string $status, ?string $search, int $page, int $limit, ): PaginatedResult { $params = $this->buildBaseParams($tenantId); $whereClause = $this->buildBaseWhere(); if ($status !== null && $status !== '') { $whereClause .= ' AND u.image_rights_status = :status'; $params['status'] = $status; } if ($search !== null && $search !== '') { $whereClause .= ' AND (u.first_name ILIKE :search OR u.last_name ILIKE :search OR u.email ILIKE :search)'; $params['search'] = '%' . $search . '%'; } $countSql = "SELECT COUNT(*) FROM users u WHERE {$whereClause}"; /** @var int|string|false $totalRaw */ $totalRaw = $this->connection->fetchOne($countSql, $params); $total = (int) $totalRaw; $offset = ($page - 1) * $limit; $selectSql = <<connection->fetchAllAssociative($selectSql, $params); $items = array_map(self::mapRowToDto(...), $rows); return new PaginatedResult( items: $items, total: $total, page: $page, limit: $limit, ); } /** * @return StudentImageRightsDto[] */ public function findAll( string $tenantId, ?string $status, ): array { $params = $this->buildBaseParams($tenantId); $whereClause = $this->buildBaseWhere(); if ($status !== null && $status !== '') { $whereClause .= ' AND u.image_rights_status = :status'; $params['status'] = $status; } $sql = <<connection->fetchAllAssociative($sql, $params); return array_map(self::mapRowToDto(...), $rows); } /** * @return array */ private function buildBaseParams(string $tenantId): array { return [ 'tenant_id' => $tenantId, 'role' => json_encode([Role::ELEVE->value], JSON_THROW_ON_ERROR), ]; } private function buildBaseWhere(): string { return 'u.tenant_id = :tenant_id AND u.roles::jsonb @> :role::jsonb'; } /** * @param array $row */ private static function mapRowToDto(array $row): StudentImageRightsDto { /** @var string $id */ $id = $row['id']; /** @var string $firstName */ $firstName = $row['first_name']; /** @var string $lastName */ $lastName = $row['last_name']; /** @var string|null $email */ $email = $row['email']; /** @var string $imageRightsStatusValue */ $imageRightsStatusValue = $row['image_rights_status']; /** @var string|null $imageRightsUpdatedAt */ $imageRightsUpdatedAt = $row['image_rights_updated_at']; /** @var string|null $className */ $className = $row['class_name'] ?? null; $statusEnum = ImageRightsStatus::from($imageRightsStatusValue); return new StudentImageRightsDto( id: $id, firstName: $firstName, lastName: $lastName, email: $email ?? '', imageRightsStatus: $statusEnum->value, imageRightsStatusLabel: $statusEnum->label(), imageRightsUpdatedAt: $imageRightsUpdatedAt !== null ? new DateTimeImmutable($imageRightsUpdatedAt) : null, className: $className, ); } }