pdo = $pdo; $this->uploadDir = __DIR__ . '/../uploads/announcements/'; // Ensure upload directory exists if (!is_dir($this->uploadDir) && !mkdir($this->uploadDir, 0775, true) && !is_dir($this->uploadDir)) { throw new RuntimeException('Unable to create announcements upload directory.'); } } /** * Adds a new announcement to the database. * * @param string $title The title of the announcement. * @param string $description The full description of the announcement. * @param string|null $photopath The filename of the uploaded photo, or null if no photo. * @param string $status The status of the announcement (e.g., 'Draft', 'Published', 'Archived'). * @param int $reg_by The ID of the user who registered the announcement. * @return bool True on success, false on failure. * @throws Exception If a database error occurs. */ public function addAnnouncement(string $title, string $description, ?string $photopath, string $status, int $reg_by): bool { $sql = "INSERT INTO dsps_tbl_announcement (dspsann_title, dspsann_description, dspsann_photopath, dspsann_status, dspsann_reg_by) VALUES (:title, :description, :photopath, :status, :reg_by)"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':title', $title); $stmt->bindParam(':description', $description); $stmt->bindParam(':photopath', $photopath); $stmt->bindParam(':status', $status); $stmt->bindParam(':reg_by', $reg_by); return $stmt->execute(); } catch (PDOException $e) { error_log("Error adding announcement: " . $e->getMessage()); throw new Exception("Could not add announcement. Please try again later."); } } /** * Updates an existing announcement in the database. * * @param int $id The ID of the announcement to update. * @param string $title The new title. * @param string $description The new description. * @param string|null $photopath The new filename of the photo, or null. * @param string $status The new status. * @param int $mod_by The ID of the user who modified the announcement. * @return bool True on success, false on failure. * @throws Exception If a database error occurs. */ public function updateAnnouncement(int $id, string $title, string $description, ?string $photopath, string $status, int $mod_by): bool { $sql = "UPDATE dsps_tbl_announcement SET dspsann_title = :title, dspsann_description = :description, dspsann_photopath = :photopath, dspsann_status = :status, dspsann_mod_datetime = CURRENT_TIMESTAMP, dspsann_reg_by = :mod_by WHERE pkdspsann_id = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':title', $title); $stmt->bindParam(':description', $description); $stmt->bindParam(':photopath', $photopath); $stmt->bindParam(':status', $status); $stmt->bindParam(':mod_by', $mod_by); $stmt->bindParam(':id', $id); return $stmt->execute(); } catch (PDOException $e) { error_log("Error updating announcement (ID: $id): " . $e->getMessage()); throw new Exception("Could not update announcement. Please try again later."); } } /** * Deletes an announcement from the database and its associated photo file. * * @param int $id The ID of the announcement to delete. * @return bool True on success, false on failure. * @throws Exception If a database error occurs. */ public function deleteAnnouncement(int $id): bool { // First, get the photo path to delete the file $announcement = $this->getAnnouncementById($id); if ($announcement && !empty($announcement['dspsann_photopath'])) { $filePath = $this->uploadDir . $announcement['dspsann_photopath']; if (file_exists($filePath)) { unlink($filePath); // Delete the file } } $sql = "DELETE FROM dsps_tbl_announcement WHERE pkdspsann_id = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id); return $stmt->execute(); } catch (PDOException $e) { error_log("Error deleting announcement (ID: $id): " . $e->getMessage()); throw new Exception("Could not delete announcement. Please try again later."); } } /** * Retrieves a single announcement by its ID. * * @param int $id The ID of the announcement. * @return array|false The announcement data as an associative array, or false if not found. * @throws Exception If a database error occurs. */ public function getAnnouncementById(int $id) { $sql = "SELECT * FROM dsps_tbl_announcement WHERE pkdspsann_id = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log("Error fetching announcement by ID ($id): " . $e->getMessage()); throw new Exception("Could not retrieve announcement. Please try again later."); } } /** * Retrieves all announcements, optionally filtered by status. * * @param string|null $status Optional status to filter by (e.g., 'Published'). * @param int|null $limit Optional limit for the number of results. * @return array An array of announcement data. * @throws Exception If a database error occurs. */ public function getAllAnnouncements(?string $status = null, ?int $limit = null): array { $sql = "SELECT * FROM dsps_tbl_announcement"; $conditions = []; $params = []; if ($status) { $conditions[] = "dspsann_status = :status"; $params[':status'] = $status; } if (!empty($conditions)) { $sql .= " WHERE " . implode(" AND ", $conditions); } $sql .= " ORDER BY dspsann_reg_datetime DESC"; if ($limit) { $sql .= " LIMIT :limit"; $params[':limit'] = $limit; } try { $stmt = $this->pdo->prepare($sql); foreach ($params as $key => &$val) { $stmt->bindParam($key, $val, is_int($val) ? PDO::PARAM_INT : PDO::PARAM_STR); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log("Error fetching all announcements: " . $e->getMessage()); throw new Exception("Could not retrieve announcements. Please try again later."); } } /** * Gets the total count of announcements. * * @return int The total number of announcements. * @throws Exception If a database error occurs. */ public function getTotalAnnouncements(): int { $sql = "SELECT COUNT(*) FROM dsps_tbl_announcement"; try { $stmt = $this->pdo->query($sql); return $stmt->fetchColumn(); } catch (PDOException $e) { error_log("Error getting total announcements count: " . $e->getMessage()); throw new Exception("Could not retrieve announcement count. Please try again later."); } } /** * Handles the upload of an announcement photo. * * @param array $file The $_FILES array for the uploaded photo. * @return string The unique filename of the uploaded photo. * @throws Exception If the upload fails or file type is invalid. */ public function handlePhotoUpload(array $file): string { if ($file['error'] !== UPLOAD_ERR_OK) { throw new Exception('File upload error: ' . $file['error']); } $allowedTypes = ['image/jpeg', 'image/png', 'image/gif']; $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->file($file['tmp_name']); if (!in_array($mimeType, $allowedTypes)) { throw new Exception('Invalid file type. Only JPEG, PNG, and GIF images are allowed.'); } $extension = pathinfo($file['name'], PATHINFO_EXTENSION); $uniqueFilename = uniqid('announcement_') . '.' . $extension; $destination = $this->uploadDir . $uniqueFilename; if (!move_uploaded_file($file['tmp_name'], $destination)) { throw new Exception('Failed to move uploaded file.'); } return $uniqueFilename; } }