189 lines
5.4 KiB
PHP
189 lines
5.4 KiB
PHP
<?php
|
|
|
|
class AttachmentController {
|
|
|
|
use RequiresAuth, CheckCSRF;
|
|
|
|
// list attachments
|
|
public function index($f3){
|
|
$this->check_access($f3);
|
|
|
|
$ticket_id = (int) $f3->get('PARAMS.id');
|
|
$db = $f3->get('DB');
|
|
|
|
// fetch attachments
|
|
|
|
$attachments = $db->exec(
|
|
'SELECT a.*, u.username
|
|
FROM attachments a
|
|
LEFT JOIN users u ON u.id = a.uploaded_by
|
|
WHERE a.ticket_id = ?
|
|
ORDER BY a.created_at DESC',
|
|
[$ticket_id]
|
|
);
|
|
|
|
$f3->set('ticket_id', $ticket_id);
|
|
$f3->set('attachments', $attachments);
|
|
|
|
$f3->set('content', 'views/attachment/index.html');
|
|
// echo \Template::instance()->render('templates/layout.html');
|
|
echo \Template::instance()->render($f3->get('content'));
|
|
}
|
|
|
|
// handle file upload
|
|
public function upload($f3){
|
|
$this->check_access($f3);
|
|
$this->checkCSRF($f3, '/ticket/'.$f3->get('PARAMS.id')); // not ideal for AJAX
|
|
|
|
$ticket_id = (int) $f3->get('PARAMS.id');
|
|
$uploaded_by = $f3->get('SESSION.user.id');
|
|
|
|
if(!isset($_FILES['attachment']) || $_FILES['attachment']['error'] !== UPLOAD_ERR_OK){
|
|
$f3->reroute('/ticket/'.$ticket_id.'/attachments');
|
|
}
|
|
|
|
$file_info = $_FILES['attachment'];
|
|
$original_name = $file_info['name'];
|
|
$tmp_path = $file_info['tmp_name'];
|
|
|
|
// create a unique file path
|
|
$upload_dir = '../storage/attachments/tickets/'.$ticket_id.'/';
|
|
if(!is_dir($upload_dir)){
|
|
mkdir($upload_dir, 0777, true);
|
|
}
|
|
|
|
// if file exists increment version
|
|
$db = $f3->get('DB');
|
|
$existing = $db->exec(
|
|
'SELECT * FROM attachments
|
|
WHERE ticket_id =? AND file_name = ?
|
|
ORDER BY version_number DESC
|
|
LIMIT 1',
|
|
[$ticket_id, $original_name]
|
|
);
|
|
|
|
$new_version = 1;
|
|
if($existing){
|
|
$new_version = $existing[0]['version_number'] + 1;
|
|
}
|
|
|
|
$final_path = $upload_dir.$new_version.'_'.$original_name;
|
|
|
|
// move file
|
|
move_uploaded_file($tmp_path, $final_path);
|
|
|
|
// store meta data in DB
|
|
$db->exec(
|
|
'INSERT INTO attachments
|
|
(ticket_id, path, file_name, version_number, uploaded_by, created_at)
|
|
VALUES (?,?,?,?,?,NOW())',
|
|
[$ticket_id, $final_path, $original_name, $new_version, $uploaded_by]
|
|
);
|
|
|
|
$f3->reroute('/ticket/'.$ticket_id.'');
|
|
|
|
// ideal ajax response:
|
|
// $f3->json(['success' => true, 'message' => 'file upload success.', 'filename' => $original_name, 'version' => $new_version]);
|
|
}
|
|
|
|
// download attachment
|
|
public function download($f3){
|
|
$this->check_access($f3);
|
|
|
|
$attachment_id = (int) $f3->get('PARAMS.id');
|
|
$db = $f3->get('DB');
|
|
|
|
$rows = $db->exec('SELECT * FROM attachments WHERE id = ?', [$attachment_id]);
|
|
|
|
if(!$rows){
|
|
$f3->error(404, "File not found");
|
|
return;
|
|
}
|
|
|
|
$attachment = $rows[0];
|
|
$file_path = $attachment['path'];
|
|
$file_name = $attachment['file_name'];
|
|
|
|
// validate file exists
|
|
if(!file_exists($file_path)){
|
|
$f3->error(404, "File not found");
|
|
return;
|
|
}
|
|
|
|
// output headers for download
|
|
header('Content-Description: File Transfer');
|
|
header('Content-Type: application/octet-stream');
|
|
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
|
|
header('Content-Length: '. filesize($file_path));
|
|
|
|
// flush headers
|
|
flush();
|
|
|
|
// read file
|
|
readfile($file_path);
|
|
exit;
|
|
}
|
|
|
|
// delete an attachment
|
|
public function delete($f3){
|
|
$this->check_access($f3);
|
|
|
|
$attachment_id = (int) $f3->get('PARAMS.id');
|
|
$current_user = $f3->get('SESSION.user');
|
|
|
|
$db = $f3->get('DB');
|
|
|
|
$rows = $db->exec('SELECT * FROM attachments WHERE id =? LIMIT 1', [$attachment_id]);
|
|
if(!$rows){
|
|
$f3->error(404, "Attachment not found");
|
|
return;
|
|
}
|
|
|
|
$attachment = $rows[0];
|
|
// TODO: role or ownership
|
|
|
|
if(file_exists($attachment['path'])){
|
|
unlink($attachment['path']);
|
|
}
|
|
|
|
// remove DB row
|
|
$db->exec('DELETE FROM attachments WHERE id =?', [$attachment_id]);
|
|
}
|
|
|
|
// view attachment
|
|
public function view($f3){
|
|
$this->check_access($f3);
|
|
|
|
$attachment_id = (int) $f3->get('PARAMS.id');
|
|
$db = $f3->get('DB');
|
|
|
|
$rows = $db->exec('SELECt * FROM attachments WHERE id = ?', [$attachment_id]);
|
|
|
|
if(!$rows){
|
|
$f3->error(404, "File not found");
|
|
return;
|
|
}
|
|
|
|
$attachment = $rows[0];
|
|
$file_path = $attachment['path'];
|
|
$file_name = $attachment['file_name'];
|
|
|
|
if(!file_exists($file_path)){
|
|
$f3->error(404, "File not found");
|
|
return;
|
|
}
|
|
|
|
// detect mime type
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mime_type = finfo_file($finfo, $file_path);
|
|
finfo_close($finfo);
|
|
|
|
header('Content-Type: ' . $mime_type);
|
|
header('Content-Disposition: inline; filename="' . basename($file_name) . '"');
|
|
header('Content-Length: ' . filesize($file_path));
|
|
|
|
flush();
|
|
readfile($file_path);
|
|
exit;
|
|
}
|
|
} |