Router.php

10.94 KB
27/04/2025 16:21
PHP
<?php
class Router
{
    /**
     * @var array
     */
    private $routes = [];
    /**
     * @var mixed
     */
    private $user = null;

    public function __construct()
    {
        // Get base path
        $basePath = str_replace($_SERVER['DOCUMENT_ROOT'], '', __DIR__);
        define('BASE_PATH', $basePath);

        // Check authentication
        $this->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);
    }
}