220 lines
7.0 KiB
PHP
220 lines
7.0 KiB
PHP
|
|
<?php
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
class TaskCertificateRepository
|
||
|
|
{
|
||
|
|
public function create(array $data): int
|
||
|
|
{
|
||
|
|
return TaskCertDb::insert(
|
||
|
|
'INSERT INTO task_certificate (
|
||
|
|
task_id,
|
||
|
|
assignment_id,
|
||
|
|
submission_id,
|
||
|
|
main_contact_id,
|
||
|
|
certificate_code,
|
||
|
|
valid_from,
|
||
|
|
valid_until,
|
||
|
|
status
|
||
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
||
|
|
'iiiissss',
|
||
|
|
[
|
||
|
|
$data['task_id'],
|
||
|
|
$data['assignment_id'],
|
||
|
|
$data['submission_id'],
|
||
|
|
$data['main_contact_id'],
|
||
|
|
$data['certificate_code'],
|
||
|
|
$data['valid_from'],
|
||
|
|
$data['valid_until'],
|
||
|
|
$data['status'],
|
||
|
|
]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function findByAssignmentId(int $assignmentId): ?array
|
||
|
|
{
|
||
|
|
return TaskCertDb::fetchOne(
|
||
|
|
'SELECT * FROM task_certificate WHERE assignment_id = ? LIMIT 1',
|
||
|
|
'i',
|
||
|
|
[$assignmentId]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function listAssignmentIdsWithCertificates(array $assignmentIds): array
|
||
|
|
{
|
||
|
|
$assignmentIds = array_values(array_unique(array_map('intval', $assignmentIds)));
|
||
|
|
$assignmentIds = array_values(array_filter($assignmentIds, static function (int $assignmentId): bool {
|
||
|
|
return $assignmentId > 0;
|
||
|
|
}));
|
||
|
|
|
||
|
|
if ($assignmentIds === []) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
$placeholders = implode(',', array_fill(0, count($assignmentIds), '?'));
|
||
|
|
$rows = TaskCertDb::fetchAll(
|
||
|
|
'SELECT DISTINCT assignment_id
|
||
|
|
FROM task_certificate
|
||
|
|
WHERE assignment_id IN (' . $placeholders . ')',
|
||
|
|
str_repeat('i', count($assignmentIds)),
|
||
|
|
$assignmentIds
|
||
|
|
);
|
||
|
|
|
||
|
|
$result = [];
|
||
|
|
foreach ($rows as $row) {
|
||
|
|
$assignmentId = (int) ($row['assignment_id'] ?? 0);
|
||
|
|
if ($assignmentId <= 0) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$result[] = $assignmentId;
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = array_values(array_unique($result));
|
||
|
|
sort($result);
|
||
|
|
|
||
|
|
return $result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function listForUser(int $contactId): array
|
||
|
|
{
|
||
|
|
return TaskCertDb::fetchAll(
|
||
|
|
'SELECT c.*, d.title AS task_title
|
||
|
|
FROM task_certificate c
|
||
|
|
INNER JOIN task_definition d ON d.id = c.task_id
|
||
|
|
WHERE c.main_contact_id = ?
|
||
|
|
ORDER BY c.issued_at DESC',
|
||
|
|
'i',
|
||
|
|
[$contactId]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function listForUserTask(int $contactId, int $taskId): array
|
||
|
|
{
|
||
|
|
return TaskCertDb::fetchAll(
|
||
|
|
'SELECT c.*, a.cycle_key
|
||
|
|
FROM task_certificate c
|
||
|
|
LEFT JOIN task_assignment a ON a.id = c.assignment_id
|
||
|
|
WHERE c.main_contact_id = ?
|
||
|
|
AND c.task_id = ?
|
||
|
|
ORDER BY c.issued_at DESC, c.id DESC',
|
||
|
|
'ii',
|
||
|
|
[$contactId, $taskId]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function summarizeForUserTasks(int $contactId, array $taskIds): array
|
||
|
|
{
|
||
|
|
$taskIds = array_values(array_unique(array_map('intval', $taskIds)));
|
||
|
|
$taskIds = array_values(array_filter($taskIds, static function (int $taskId): bool {
|
||
|
|
return $taskId > 0;
|
||
|
|
}));
|
||
|
|
|
||
|
|
if ($taskIds === []) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
$placeholders = implode(',', array_fill(0, count($taskIds), '?'));
|
||
|
|
$sql = 'SELECT
|
||
|
|
c.task_id,
|
||
|
|
COUNT(*) AS total_count,
|
||
|
|
SUM(CASE WHEN c.status = "valid" THEN 1 ELSE 0 END) AS valid_count,
|
||
|
|
MAX(c.issued_at) AS latest_issued_at,
|
||
|
|
(
|
||
|
|
SELECT c2.valid_until
|
||
|
|
FROM task_certificate c2
|
||
|
|
WHERE c2.main_contact_id = c.main_contact_id
|
||
|
|
AND c2.task_id = c.task_id
|
||
|
|
ORDER BY c2.issued_at DESC, c2.id DESC
|
||
|
|
LIMIT 1
|
||
|
|
) AS latest_valid_until
|
||
|
|
FROM task_certificate c
|
||
|
|
WHERE c.main_contact_id = ?
|
||
|
|
AND c.task_id IN (' . $placeholders . ')
|
||
|
|
GROUP BY c.task_id';
|
||
|
|
|
||
|
|
$types = 'i' . str_repeat('i', count($taskIds));
|
||
|
|
$params = array_merge([$contactId], $taskIds);
|
||
|
|
$rows = TaskCertDb::fetchAll($sql, $types, $params);
|
||
|
|
|
||
|
|
$summaryByTask = [];
|
||
|
|
foreach ($rows as $row) {
|
||
|
|
$taskId = (int) ($row['task_id'] ?? 0);
|
||
|
|
if ($taskId <= 0) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$summaryByTask[$taskId] = [
|
||
|
|
'task_id' => $taskId,
|
||
|
|
'total_count' => (int) ($row['total_count'] ?? 0),
|
||
|
|
'valid_count' => (int) ($row['valid_count'] ?? 0),
|
||
|
|
'latest_issued_at' => (string) ($row['latest_issued_at'] ?? ''),
|
||
|
|
'latest_valid_until' => (string) ($row['latest_valid_until'] ?? ''),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
return $summaryByTask;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function deleteByAssignmentIds(array $assignmentIds): int
|
||
|
|
{
|
||
|
|
$assignmentIds = array_values(array_unique(array_map('intval', $assignmentIds)));
|
||
|
|
$assignmentIds = array_values(array_filter($assignmentIds, static function (int $assignmentId): bool {
|
||
|
|
return $assignmentId > 0;
|
||
|
|
}));
|
||
|
|
|
||
|
|
if ($assignmentIds === []) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
$placeholders = implode(',', array_fill(0, count($assignmentIds), '?'));
|
||
|
|
$types = str_repeat('i', count($assignmentIds));
|
||
|
|
|
||
|
|
return TaskCertDb::execute(
|
||
|
|
'DELETE FROM task_certificate WHERE assignment_id IN (' . $placeholders . ')',
|
||
|
|
$types,
|
||
|
|
$assignmentIds
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function revokeByAssignmentIds(array $assignmentIds, int $revokedBy, string $reason): int
|
||
|
|
{
|
||
|
|
$assignmentIds = array_values(array_unique(array_map('intval', $assignmentIds)));
|
||
|
|
$assignmentIds = array_values(array_filter($assignmentIds, static function (int $assignmentId): bool {
|
||
|
|
return $assignmentId > 0;
|
||
|
|
}));
|
||
|
|
|
||
|
|
if ($assignmentIds === []) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
$placeholders = implode(',', array_fill(0, count($assignmentIds), '?'));
|
||
|
|
$types = 'is' . str_repeat('i', count($assignmentIds));
|
||
|
|
$params = array_merge([$revokedBy, $reason], $assignmentIds);
|
||
|
|
|
||
|
|
return TaskCertDb::execute(
|
||
|
|
'UPDATE task_certificate
|
||
|
|
SET status = "revoked",
|
||
|
|
revoked_at = COALESCE(revoked_at, NOW()),
|
||
|
|
revoked_by = ?,
|
||
|
|
revoke_reason = ?
|
||
|
|
WHERE assignment_id IN (' . $placeholders . ')
|
||
|
|
AND status <> "revoked"',
|
||
|
|
$types,
|
||
|
|
$params
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function markExpiredByDate(string $now): int
|
||
|
|
{
|
||
|
|
return TaskCertDb::execute(
|
||
|
|
'UPDATE task_certificate
|
||
|
|
SET status = "expired"
|
||
|
|
WHERE status = "valid"
|
||
|
|
AND valid_until IS NOT NULL
|
||
|
|
AND valid_until < ?',
|
||
|
|
's',
|
||
|
|
[$now]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|