report(null, [ 'report_title' => $title, 'report_description' => $description, 'report_status' => $status, 'report_group' => $group, 'report_priority' => $priority, ]); return $report_id; } /** * Update report * * @param int $report_id * @param array $report_data * * @return bool */ public function update(int $report_id, array $report_data): bool { $reports = new Reports(); $suc = $reports->report($report_id, $report_data); return $suc !== false; } /** * Delete report * * @param int $report_id * * @return bool */ public function delete(int $report_id): bool { $reports = new Reports(); $suc = $reports->report($report_id, null); return $suc !== false; } /** * Get report * * @param int $report_id * * @return array */ public function get(int $report_id): array { $reports = new Reports(); return $reports->report($report_id); } /** * Get all reports * * @param array $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived * @param int $page Pagination from 0 * * @return array */ public function getAll(?array $status = null, int $page = 0): array { $page = intval($page); $reports = new Reports(); if ($status === null) $status = array(0, 1, 2, 3); $ret = $reports->search('reports') ->where(['report_status' => $status]) ->order(array('report_priority' => 'DESC', 'ordnum' => 'ASC')) ->limit($page * 10, 10) ->toArray(); return $ret; } /** * Get all reports grouped by status * * @param array $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived * @param int $page Pagination from 0 * * @return array */ public function getAllGrouped(?array $status = null, int $page = 0): array { $page = intval($page); $all = $this->getAll($status, $page); $groups = []; foreach ($all as $report) { $groups[$report['report_status']][] = $report; } return $groups; } /** * Get archived reports * * @param int $page Pagination from 0 * * @return array */ public function getArchived(int $page = 0): array { $page = intval($page); $reports = new Reports(); $ret = $reports->search('reports') ->where(['report_status' => 4]) ->order(array('created_dt' => 'DESC')) ->limit($page * 10, 10) ->toArray(); return $ret; } /** * Update report order number * * @param array $ordnums report_id => ordnum * * @return bool */ public function updateOrdNum(array $ordnums): bool { $reports = new Reports(); $suc = true; foreach ($ordnums as $report_id => $ordnum) { $suc &= $reports->report($report_id, ['ordnum' => $ordnum]); } return $suc; } /** * Update report status * * @param int $report_id * @param int $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived * * @return bool */ public function updateStatus(int $report_id, int $status): bool { $reports = new Reports(); $suc = $reports->report($report_id, ['report_status' => $status]); return $suc !== false; } /** * Add report attachment * * @param int $report_id * @param string $attachment_type "comment" or "file" * @param string $attachment_content * * @return bool */ public function attachmentAdd(int $report_id, string $attachment_type, string $attachment_content): bool { if ($attachment_type == 'file') { $data = json_decode($attachment_content, true); if (!is_array($data)) return false; $base64 = preg_replace('/^data:.*?;base64,/', '', $data['base64']); $base64_data = base64_decode($base64); $filename = 'report_' . $report_id . '_' . time() . '_' . $this->sanitizeFilename($data['filename']); file_put_contents(UPLOAD_DIR_ATTACHMENTS . $filename, $base64_data); $attachment_content = $filename; } $attachments = new Attachments(); $suc = $attachments->attachment(null, [ 'report_id' => $report_id, 'attachment_type' => $attachment_type, 'attachment_content' => $attachment_content, 'created_dt' => date('Y-m-d H:i:s') ]); return $suc !== false; } private function sanitizeFilename($filename, $allowedExtensions = []) { // Rozdelenie názvu a prípony $pathInfo = pathinfo($filename); $name = $pathInfo['filename'] ?? 'file'; $extension = strtolower($pathInfo['extension'] ?? ''); // Odstránenie nebezpečných znakov z názvu $name = preg_replace('/[^a-zA-Z0-9_-]/', '_', $name); $name = substr($name, 0, 100); // voliteľné obmedzenie dĺžky // Validácia prípony, ak je zoznam povolený if ( $allowedExtensions && count($allowedExtensions) > 0 && !in_array($extension, $allowedExtensions) ) { $extension = 'bin'; // fallback ak prípona nie je povolená } return $name . '.' . $extension; } /** * Update report attachment * * @param int $attachment_id * @param string $attachment_content * * @return bool */ public function attachmentUpdate(int $attachment_id, string $attachment_content): bool { if (strlen(trim($attachment_content)) <= 0) return $this->attachmentDelete($attachment_id); $attachments = new Attachments(); $suc = $attachments->attachment($attachment_id, [ 'attachment_content' => $attachment_content, 'updated_dt' => date('Y-m-d H:i:s') ]); return $suc !== false; } /** * Get all report attachments * * @param int $report_id * * @return array */ public function attachmentGetAll(int $report_id): array { $attachments = new Attachments(); $all = $attachments->search('attachments') ->where(['report_id' => $report_id]) ->order(array('created_dt' => 'ASC')) ->toArray(); if (is_array($all)) foreach ($all as $key => $row) { if ($all[$key]['attachment_type'] == 'file') { $all[$key]['attachment_content'] = '?action=attachmentDownload&filename=' . $all[$key]['attachment_content']; } } return $all; } /** * Delete report attachment * * @param int $attachment_id * * @return bool */ public function attachmentDelete(int $attachment_id): bool { $attachments = new Attachments(); $suc = $attachments->attachment($attachment_id, null); return $suc !== false; } /** * Download report attachment * * @param string $filename * * @return void */ public function attachmentDownload(string $filename): void { $filename = $this->sanitizeFilename($filename); $filename = UPLOAD_DIR_ATTACHMENTS . $filename; if (file_exists($filename)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($filename) . '"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($filename)); readfile($filename); exit; } } }