diff --git a/api/get_template.php b/api/get_template.php index c7b3b3b..6a1a35e 100644 --- a/api/get_template.php +++ b/api/get_template.php @@ -1,48 +1,50 @@ false, 'error' => 'Not authenticated']); - exit; -} - -// Get template ID from query parameter -$templateId = $_GET['template_id'] ?? null; - -if (!$templateId || !is_numeric($templateId)) { - echo json_encode(['success' => false, 'error' => 'Valid template ID required']); - exit; -} - -// Cast to integer for safety -$templateId = (int)$templateId; - -// Create database connection -$conn = new mysqli( - $GLOBALS['config']['DB_HOST'], - $GLOBALS['config']['DB_USER'], - $GLOBALS['config']['DB_PASS'], - $GLOBALS['config']['DB_NAME'] -); - -if ($conn->connect_error) { - echo json_encode(['success' => false, 'error' => 'Database connection failed']); - exit; -} - -// Get template -$templateModel = new TemplateModel($conn); -$template = $templateModel->getTemplateById($templateId); - -$conn->close(); - -if ($template) { - echo json_encode(['success' => true, 'template' => $template]); -} else { - echo json_encode(['success' => false, 'error' => 'Template not found']); +try { + session_start(); + require_once dirname(__DIR__) . '/config/config.php'; + require_once dirname(__DIR__) . '/helpers/Database.php'; + require_once dirname(__DIR__) . '/models/TemplateModel.php'; + + header('Content-Type: application/json'); + + // Check authentication + if (!isset($_SESSION['user']) || !isset($_SESSION['user']['user_id'])) { + ErrorHandler::sendUnauthorizedError('Not authenticated'); + } + + // Get template ID from query parameter + $templateId = $_GET['template_id'] ?? null; + + if (!$templateId || !is_numeric($templateId)) { + ErrorHandler::sendValidationError( + ['template_id' => 'Valid template ID required'], + 'Invalid request' + ); + } + + // Cast to integer for safety + $templateId = (int)$templateId; + + // Get template + $conn = Database::getConnection(); + $templateModel = new TemplateModel($conn); + $template = $templateModel->getTemplateById($templateId); + + if ($template) { + echo json_encode(['success' => true, 'template' => $template]); + } else { + ErrorHandler::sendNotFoundError('Template not found'); + } + +} catch (Exception $e) { + ErrorHandler::log($e->getMessage(), E_ERROR); + ErrorHandler::sendErrorResponse('Failed to retrieve template', 500, $e); } diff --git a/helpers/ErrorHandler.php b/helpers/ErrorHandler.php new file mode 100644 index 0000000..82de9e4 --- /dev/null +++ b/helpers/ErrorHandler.php @@ -0,0 +1,263 @@ +getMessage(), + $exception->getFile(), + $exception->getLine(), + $exception->getTraceAsString() + ); + + self::log($message, E_ERROR); + + // Send error response if headers not sent + if (!headers_sent()) { + self::sendErrorResponse( + 'An unexpected error occurred', + 500, + $exception + ); + } + } + + /** + * Handle fatal errors on shutdown + */ + public static function handleShutdown() { + $error = error_get_last(); + + if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { + $message = sprintf( + "Fatal Error: %s in %s on line %d", + $error['message'], + $error['file'], + $error['line'] + ); + + self::log($message, E_ERROR); + + if (!headers_sent()) { + self::sendErrorResponse('A fatal error occurred', 500); + } + } + } + + /** + * Log an error message + * + * @param string $message Error message + * @param int $level Error level + * @param array $context Additional context + */ + public static function log($message, $level = E_USER_NOTICE, $context = []) { + $timestamp = date('Y-m-d H:i:s'); + $levelName = self::getErrorTypeName($level); + + $logMessage = "[$timestamp] [$levelName] $message"; + + if (!empty($context)) { + $logMessage .= " | Context: " . json_encode($context); + } + + error_log($logMessage); + } + + /** + * Send a JSON error response + * + * @param string $message User-facing error message + * @param int $httpCode HTTP status code + * @param Throwable|null $exception Original exception (for debug info) + */ + public static function sendErrorResponse($message, $httpCode = 500, $exception = null) { + http_response_code($httpCode); + + if (!headers_sent()) { + header('Content-Type: application/json'); + } + + $response = [ + 'success' => false, + 'error' => $message + ]; + + // Add debug info in development (check for debug mode) + if (isset($GLOBALS['config']['DEBUG']) && $GLOBALS['config']['DEBUG'] && $exception) { + $response['debug'] = [ + 'type' => get_class($exception), + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine() + ]; + } + + echo json_encode($response); + exit; + } + + /** + * Send a validation error response + * + * @param array $errors Array of validation errors + * @param string $message Overall error message + */ + public static function sendValidationError($errors, $message = 'Validation failed') { + http_response_code(422); + + if (!headers_sent()) { + header('Content-Type: application/json'); + } + + echo json_encode([ + 'success' => false, + 'error' => $message, + 'validation_errors' => $errors + ]); + exit; + } + + /** + * Send a not found error response + * + * @param string $message Error message + */ + public static function sendNotFoundError($message = 'Resource not found') { + self::sendErrorResponse($message, 404); + } + + /** + * Send an unauthorized error response + * + * @param string $message Error message + */ + public static function sendUnauthorizedError($message = 'Authentication required') { + self::sendErrorResponse($message, 401); + } + + /** + * Send a forbidden error response + * + * @param string $message Error message + */ + public static function sendForbiddenError($message = 'Access denied') { + self::sendErrorResponse($message, 403); + } + + /** + * Get error type name from error number + * + * @param int $errno Error number + * @return string Error type name + */ + private static function getErrorTypeName($errno) { + $types = [ + E_ERROR => 'ERROR', + E_WARNING => 'WARNING', + E_PARSE => 'PARSE', + E_NOTICE => 'NOTICE', + E_CORE_ERROR => 'CORE_ERROR', + E_CORE_WARNING => 'CORE_WARNING', + E_COMPILE_ERROR => 'COMPILE_ERROR', + E_COMPILE_WARNING => 'COMPILE_WARNING', + E_USER_ERROR => 'USER_ERROR', + E_USER_WARNING => 'USER_WARNING', + E_USER_NOTICE => 'USER_NOTICE', + E_STRICT => 'STRICT', + E_RECOVERABLE_ERROR => 'RECOVERABLE_ERROR', + E_DEPRECATED => 'DEPRECATED', + E_USER_DEPRECATED => 'USER_DEPRECATED', + ]; + + return $types[$errno] ?? 'UNKNOWN'; + } + + /** + * Get recent error log entries + * + * @param int $lines Number of lines to return + * @return array Log entries + */ + public static function getRecentErrors($lines = 50) { + if (self::$logFile === null || !file_exists(self::$logFile)) { + return []; + } + + $file = file(self::$logFile); + if ($file === false) { + return []; + } + + return array_slice($file, -$lines); + } +}