Files
CRM-IKZ/app/Controllers/TaskFileController.php
T
2026-07-14 08:19:56 +04:00

281 lines
7.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Core\Auth;
use App\Core\DB;
class TaskFileController
{
public function upload(): void
{
if (!Auth::check()) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Unauthorized'], 403);
}
header('Location: /login');
exit;
}
$taskId = (int)($_POST['task_id'] ?? 0);
if ($taskId <= 0 || empty($_FILES['file'])) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Файл не выбран'], 400);
}
$_SESSION['error'] = 'Файл не выбран';
header('Location: /tasks');
exit;
}
$file = $_FILES['file'];
if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Ошибка загрузки файла'], 400);
}
$_SESSION['error'] = 'Ошибка загрузки файла';
header('Location: /tasks');
exit;
}
$uploadDir = __DIR__ . '/../../storage/uploads/tasks/' . $taskId;
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0775, true);
}
$originalName = (string)$file['name'];
$tmpName = (string)$file['tmp_name'];
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
$storedName = uniqid('task_', true) . ($extension ? '.' . $extension : '');
$targetPath = $uploadDir . '/' . $storedName;
if (!move_uploaded_file($tmpName, $targetPath)) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Не удалось сохранить файл'], 500);
}
$_SESSION['error'] = 'Не удалось сохранить файл';
header('Location: /tasks');
exit;
}
$relativePath = 'storage/uploads/tasks/' . $taskId . '/' . $storedName;
$fileSize = (int)filesize($targetPath);
$mimeType = mime_content_type($targetPath) ?: null;
$pdo = DB::connection();
$stmt = $pdo->prepare("
INSERT INTO task_files (
task_id,
uploaded_by,
original_name,
stored_name,
file_path,
file_size,
mime_type,
created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, NOW())
");
$stmt->execute([
$taskId,
Auth::user()['id'],
$originalName,
$storedName,
$relativePath,
$fileSize,
$mimeType,
]);
if ($this->isAjax()) {
$this->json([
'success' => true,
'task_id' => $taskId,
]);
}
header('Location: /tasks');
exit;
}
public function download(): void
{
if (!Auth::check()) {
header('Location: /login');
exit;
}
$fileId = (int)($_GET['id'] ?? 0);
if ($fileId <= 0) {
http_response_code(404);
echo 'Файл не найден';
return;
}
$pdo = DB::connection();
$stmt = $pdo->prepare("
SELECT *
FROM task_files
WHERE id = ?
LIMIT 1
");
$stmt->execute([$fileId]);
$file = $stmt->fetch();
if (!$file) {
http_response_code(404);
echo 'Файл не найден';
return;
}
$absolutePath = __DIR__ . '/../../' . $file['file_path'];
if (!is_file($absolutePath)) {
http_response_code(404);
echo 'Файл не найден на диске';
return;
}
header('Content-Description: File Transfer');
header('Content-Type: ' . ($file['mime_type'] ?: 'application/octet-stream'));
header('Content-Disposition: attachment; filename="' . basename((string)$file['original_name']) . '"');
header('Content-Length: ' . filesize($absolutePath));
header('Pragma: public');
readfile($absolutePath);
exit;
}
public function view(): void
{
if (!Auth::check()) {
header('Location: /login');
exit;
}
$fileId = (int)($_GET['id'] ?? 0);
if ($fileId <= 0) {
http_response_code(404);
echo 'Файл не найден';
return;
}
$pdo = DB::connection();
$stmt = $pdo->prepare("
SELECT *
FROM task_files
WHERE id = ?
LIMIT 1
");
$stmt->execute([$fileId]);
$file = $stmt->fetch();
if (!$file) {
http_response_code(404);
echo 'Файл не найден';
return;
}
$absolutePath = __DIR__ . '/../../' . $file['file_path'];
if (!is_file($absolutePath)) {
http_response_code(404);
echo 'Файл не найден на диске';
return;
}
$mimeType = $file['mime_type'] ?: mime_content_type($absolutePath) ?: 'application/octet-stream';
header('Content-Type: ' . $mimeType);
header('Content-Length: ' . filesize($absolutePath));
header('Content-Disposition: inline; filename="' . basename((string)$file['original_name']) . '"');
readfile($absolutePath);
exit;
}
public function delete(): void
{
if (!Auth::check()) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Unauthorized'], 403);
}
header('Location: /login');
exit;
}
$fileId = (int)($_POST['id'] ?? 0);
if ($fileId <= 0) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Файл не найден'], 404);
}
$_SESSION['error'] = 'Файл не найден';
header('Location: /tasks');
exit;
}
$pdo = DB::connection();
$stmt = $pdo->prepare("
SELECT *
FROM task_files
WHERE id = ?
LIMIT 1
");
$stmt->execute([$fileId]);
$file = $stmt->fetch();
if (!$file) {
if ($this->isAjax()) {
$this->json(['success' => false, 'message' => 'Файл не найден'], 404);
}
$_SESSION['error'] = 'Файл не найден';
header('Location: /tasks');
exit;
}
$absolutePath = __DIR__ . '/../../' . $file['file_path'];
$stmt = $pdo->prepare("DELETE FROM task_files WHERE id = ?");
$stmt->execute([$fileId]);
if (is_file($absolutePath)) {
@unlink($absolutePath);
}
if ($this->isAjax()) {
$this->json([
'success' => true,
'file_id' => $fileId,
]);
}
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;
}
}