153 lines
4.7 KiB
PHP
153 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Core\Auth;
|
|
use App\Core\DB;
|
|
use App\Services\WebSocket\EventPublisher;
|
|
|
|
class CommentController
|
|
{
|
|
public function store(): void
|
|
{
|
|
if (!Auth::check()) {
|
|
if ($this->isAjax()) {
|
|
$this->json(['success' => false, 'message' => 'Unauthorized'], 403);
|
|
}
|
|
|
|
header('Location: /login');
|
|
exit;
|
|
}
|
|
|
|
$taskId = (int)($_POST['task_id'] ?? 0);
|
|
$text = trim((string)($_POST['text'] ?? ''));
|
|
|
|
if ($taskId <= 0 || $text === '') {
|
|
if ($this->isAjax()) {
|
|
$this->json(['success' => false, 'message' => 'Комментарий не заполнен'], 400);
|
|
}
|
|
|
|
$_SESSION['error'] = 'Комментарий не заполнен';
|
|
header('Location: /tasks');
|
|
exit;
|
|
}
|
|
|
|
$pdo = DB::connection();
|
|
|
|
// 1. Добавляем комментарий
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO task_comments (
|
|
task_id,
|
|
user_id,
|
|
text,
|
|
created_at,
|
|
updated_at
|
|
) VALUES (?, ?, ?, NOW(), NOW())
|
|
");
|
|
$stmt->execute([
|
|
$taskId,
|
|
Auth::user()['id'],
|
|
$text,
|
|
]);
|
|
|
|
// 2. Получаем мета
|
|
$stmt = $pdo->prepare("
|
|
SELECT
|
|
COUNT(*) AS comment_count,
|
|
MAX(id) AS last_comment_id
|
|
FROM task_comments
|
|
WHERE task_id = ?
|
|
");
|
|
$stmt->execute([$taskId]);
|
|
$commentMeta = $stmt->fetch();
|
|
|
|
// 3. Получаем задачу
|
|
$stmt = $pdo->prepare("
|
|
SELECT id, name, assignee_id
|
|
FROM tasks
|
|
WHERE id = ?
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute([$taskId]);
|
|
$task = $stmt->fetch();
|
|
|
|
// 4. WS — обновление счетчиков
|
|
$publisher = new EventPublisher();
|
|
$publisher->publish([
|
|
'type' => 'comment_added',
|
|
'task_id' => $taskId,
|
|
'comment_count' => (int)($commentMeta['comment_count'] ?? 0),
|
|
'last_comment_id' => (int)($commentMeta['last_comment_id'] ?? 0),
|
|
'author_user_id' => (int)Auth::user()['id'],
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
// 5. Уведомление ответственному
|
|
if ($task && !empty($task['assignee_id'])) {
|
|
|
|
$assigneeId = (int)$task['assignee_id'];
|
|
$currentUserId = (int)Auth::user()['id'];
|
|
|
|
if ($assigneeId !== $currentUserId) {
|
|
|
|
// запись в БД (если есть таблица notifications)
|
|
$stmt = $pdo->prepare("
|
|
INSERT INTO notifications (
|
|
user_id,
|
|
type,
|
|
title,
|
|
message,
|
|
data_json,
|
|
is_read,
|
|
created_at
|
|
) VALUES (?, ?, ?, ?, ?, 0, NOW())
|
|
");
|
|
|
|
$stmt->execute([
|
|
$assigneeId,
|
|
'task_comment_added',
|
|
'Новый комментарий',
|
|
'Задача: ' . (string)$task['name'],
|
|
json_encode(['task_id' => $taskId], JSON_UNESCAPED_UNICODE),
|
|
]);
|
|
|
|
// WS уведомление
|
|
$publisher->publish([
|
|
'type' => 'notification_created',
|
|
'user_id' => $assigneeId,
|
|
'task_id' => $taskId,
|
|
'title' => 'Новый комментарий',
|
|
'message' => 'Задача: ' . (string)$task['name'],
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
}
|
|
}
|
|
|
|
// 6. Ответ
|
|
if ($this->isAjax()) {
|
|
$this->json([
|
|
'success' => true,
|
|
'task_id' => $taskId,
|
|
'comment_count' => (int)($commentMeta['comment_count'] ?? 0),
|
|
'last_comment_id' => (int)($commentMeta['last_comment_id'] ?? 0),
|
|
]);
|
|
}
|
|
|
|
header('Location: /tasks');
|
|
exit;
|
|
}
|
|
private function isAjax(): bool
|
|
{
|
|
return strtolower((string)($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')) === 'xmlhttprequest';
|
|
}
|
|
|
|
private function json(array $data, int $statusCode = 200): void
|
|
{
|
|
http_response_code($statusCode);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
exit;
|
|
}
|
|
} |