checkAuth(); } private function checkAuth() { // Public routes - no authentication required $publicRoutes = [ 'auth/login' => true, 'auth/verify' => true ]; // Get request URI and method $requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if (strpos($requestUri, BASE_PATH) === 0) { $requestUri = substr($requestUri, strlen(BASE_PATH)); } $requestUri = str_replace('index.php', '', $requestUri); // Parse the URI $uriParts = explode('/', trim($requestUri, '/')); $module = $uriParts[0] ?? ''; $action = $uriParts[1] ?? ''; if (!isset($publicRoutes["$module/$action"])) { $headers = getallheaders(); $authHeader = $headers['Authorization'] ?? ''; if (empty($authHeader) || strpos($authHeader, 'Bearer ') !== 0) { Response::error('Authentication required', 401); exit; } $token = substr($authHeader, 7); $decoded = TokenService::validate($token); if (!$decoded) { Response::error('Invalid or expired token', 401); exit; } // Store user data $this->user = $decoded; } } public function registerRoutes() { // Auth routes $this->routes[] = ['route' => 'auth/login', 'controller' => 'AuthController', 'method' => 'login']; $this->routes[] = ['route' => 'auth/verify', 'controller' => 'AuthController', 'method' => 'verify']; // Inventory routes $this->routes[] = ['route' => 'inventory/categories', 'controller' => 'InventoryController', 'method' => 'getCategories', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/categories', 'controller' => 'InventoryController', 'method' => 'createCategory', 'verb' => 'POST']; $this->routes[] = ['route' => 'inventory/category', 'controller' => 'InventoryController', 'method' => 'getCategory', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/category', 'controller' => 'InventoryController', 'method' => 'updateCategory', 'verb' => 'PUT']; $this->routes[] = ['route' => 'inventory/category', 'controller' => 'InventoryController', 'method' => 'deleteCategory', 'verb' => 'DELETE']; // Product routes $this->routes[] = ['route' => 'inventory/products', 'controller' => 'InventoryController', 'method' => 'getProducts', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/products', 'controller' => 'InventoryController', 'method' => 'createProduct', 'verb' => 'POST']; $this->routes[] = ['route' => 'inventory/product', 'controller' => 'InventoryController', 'method' => 'getProduct', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/product', 'controller' => 'InventoryController', 'method' => 'updateProduct', 'verb' => 'PUT']; $this->routes[] = ['route' => 'inventory/product', 'controller' => 'InventoryController', 'method' => 'deleteProduct', 'verb' => 'DELETE']; $this->routes[] = ['route' => 'inventory/low-stock', 'controller' => 'InventoryController', 'method' => 'getLowStock', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/transactions', 'controller' => 'InventoryController', 'method' => 'getTransactions', 'verb' => 'GET']; $this->routes[] = ['route' => 'inventory/transactions', 'controller' => 'InventoryController', 'method' => 'createTransaction', 'verb' => 'POST']; // Sales routes $this->routes[] = ['route' => 'sales/create', 'controller' => 'SalesController', 'method' => 'createSale', 'verb' => 'POST']; $this->routes[] = ['route' => 'sales/list', 'controller' => 'SalesController', 'method' => 'getSales', 'verb' => 'GET']; $this->routes[] = ['route' => 'sales/details', 'controller' => 'SalesController', 'method' => 'getSaleDetails', 'verb' => 'GET']; $this->routes[] = ['route' => 'sales/void', 'controller' => 'SalesController', 'method' => 'voidSale', 'verb' => 'POST']; $this->routes[] = ['route' => 'sales/export', 'controller' => 'SalesController', 'method' => 'exportSales', 'verb' => 'GET']; // Reports routes $this->routes[] = ['route' => 'reports/dashboard-stats', 'controller' => 'ReportsController', 'method' => 'getDashboardStats', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/sales-chart', 'controller' => 'ReportsController', 'method' => 'getSalesChart', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/recent-sales', 'controller' => 'ReportsController', 'method' => 'getRecentSales', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/sales-report', 'controller' => 'ReportsController', 'method' => 'getSalesReport', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/product-sales', 'controller' => 'ReportsController', 'method' => 'getProductSales', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/inventory-report', 'controller' => 'ReportsController', 'method' => 'getInventoryReport', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/cashier-performance', 'controller' => 'ReportsController', 'method' => 'getCashierPerformance', 'verb' => 'GET']; $this->routes[] = ['route' => 'reports/tax-report', 'controller' => 'ReportsController', 'method' => 'getTaxReport', 'verb' => 'GET']; // Users routes $this->routes[] = ['route' => 'users/all', 'controller' => 'UsersController', 'method' => 'getAllUsers', 'verb' => 'GET']; $this->routes[] = ['route' => 'users', 'controller' => 'UsersController', 'method' => 'createUser', 'verb' => 'POST']; $this->routes[] = ['route' => 'users/user', 'controller' => 'UsersController', 'method' => 'getUser', 'verb' => 'GET']; $this->routes[] = ['route' => 'users/user', 'controller' => 'UsersController', 'method' => 'updateUser', 'verb' => 'PUT']; $this->routes[] = ['route' => 'users/user', 'controller' => 'UsersController', 'method' => 'deleteUser', 'verb' => 'DELETE']; $this->routes[] = ['route' => 'users/change-password', 'controller' => 'UsersController', 'method' => 'changePassword', 'verb' => 'POST']; $this->routes[] = ['route' => 'users/activity-log', 'controller' => 'UsersController', 'method' => 'getActivityLog', 'verb' => 'GET']; $this->routes[] = ['route' => 'users/profile', 'controller' => 'UsersController', 'method' => 'getProfile', 'verb' => 'GET']; $this->routes[] = ['route' => 'users/profile', 'controller' => 'UsersController', 'method' => 'updateProfile', 'verb' => 'PUT']; $this->routes[] = ['route' => 'users/change-own-password', 'controller' => 'UsersController', 'method' => 'changeOwnPassword', 'verb' => 'POST']; // Settings routes $this->routes[] = ['route' => 'settings/store', 'controller' => 'SettingsController', 'method' => 'getStoreSettings', 'verb' => 'GET']; $this->routes[] = ['route' => 'settings/store', 'controller' => 'SettingsController', 'method' => 'saveStoreSettings', 'verb' => 'POST']; $this->routes[] = ['route' => 'settings/system', 'controller' => 'SettingsController', 'method' => 'getSystemSettings', 'verb' => 'GET']; $this->routes[] = ['route' => 'settings/system', 'controller' => 'SettingsController', 'method' => 'saveSystemSettings', 'verb' => 'POST']; $this->routes[] = ['route' => 'settings/backup/create', 'controller' => 'SettingsController', 'method' => 'createBackup', 'verb' => 'POST']; $this->routes[] = ['route' => 'settings/backup/restore', 'controller' => 'SettingsController', 'method' => 'restoreBackup', 'verb' => 'POST']; $this->routes[] = ['route' => 'settings/backup/history', 'controller' => 'SettingsController', 'method' => 'getBackupHistory', 'verb' => 'GET']; $this->routes[] = ['route' => 'settings/backup/download', 'controller' => 'SettingsController', 'method' => 'downloadBackup', 'verb' => 'GET']; $this->routes[] = ['route' => 'settings/backup/delete', 'controller' => 'SettingsController', 'method' => 'deleteBackup', 'verb' => 'POST']; // Customers routes $this->routes[] = ['route' => 'customers', 'controller' => 'CustomersController', 'method' => 'getCustomers', 'verb' => 'GET']; $this->routes[] = ['route' => 'customers', 'controller' => 'CustomersController', 'method' => 'createCustomer', 'verb' => 'POST']; $this->routes[] = ['route' => 'customers/customer', 'controller' => 'CustomersController', 'method' => 'getCustomer', 'verb' => 'GET']; $this->routes[] = ['route' => 'customers/customer', 'controller' => 'CustomersController', 'method' => 'updateCustomer', 'verb' => 'PUT']; $this->routes[] = ['route' => 'customers/customer', 'controller' => 'CustomersController', 'method' => 'deleteCustomer', 'verb' => 'DELETE']; } public function dispatch() { // Get request URI and method $requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $requestMethod = $_SERVER['REQUEST_METHOD']; if (strpos($requestUri, BASE_PATH) === 0) { $requestUri = substr($requestUri, strlen(BASE_PATH)); } $requestUri = str_replace('index.php', '', $requestUri); // Parse the URI $routeKey = trim($requestUri, '/'); // Find matching route with correct HTTP verb $matchedRoute = null; foreach ($this->routes as $config) { if ($config['route'] === $routeKey && (!isset($config['verb']) || $config['verb'] === $requestMethod)) { $matchedRoute = $config; break; } } if (!$matchedRoute) { Response::error('Endpoint not found or method not allowed', 404); exit; } // Get ID from query string or URL path $pathId = $uriParts[2] ?? null; $queryId = isset($_GET['id']) ? $_GET['id'] : null; $id = $pathId ?? $queryId; // Convert ID to integer if numeric if ($id !== null && is_numeric($id)) { $id = intval($id); } // Instantiate controller and execute method $controllerName = $matchedRoute['controller']; $methodName = $matchedRoute['method']; if (!class_exists($controllerName)) { Response::error("Controller not found", 500); exit; } $controller = new $controllerName($this->user); if (!method_exists($controller, $methodName)) { Response::error("Method not found in controller", 500); exit; } $controller->$methodName($id); } }