diff --git a/admin/index.php b/admin/index.php index 98edba2..8704f70 100644 --- a/admin/index.php +++ b/admin/index.php @@ -2,6 +2,9 @@ require_once __DIR__ . '/../db/config.php'; require_once __DIR__ . '/../includes/functions.php'; +// Ensure user is logged in first +require_login(); + $pdo = db(); require_permission('dashboard_view'); diff --git a/includes/functions.php b/includes/functions.php index 04a1f32..b803e60 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -60,22 +60,196 @@ function get_product_price($product) { return $price; } -function get_base_url() { - $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 ? "https://" : "http://"; - $domainName = $_SERVER['HTTP_HOST']; - - // Check for Flatlogic VM base URL (if needed) - // For now, standard detection - $path = str_replace(basename($_SERVER['SCRIPT_NAME']), "", $_SERVER['SCRIPT_NAME']); - - // Normalize path: ensure it ends with / - if (substr($path, -1) !== '/') { - $path .= '/'; +/** + * Paginate a query result. + * + * @param PDO $pdo The PDO connection object. + * @param string $query The base SQL query (without LIMIT/OFFSET). + * @param array $params Query parameters. + * @param int $default_limit Default items per page. + * @return array Pagination result with keys: data, total_rows, total_pages, current_page, limit. + */ +function paginate_query($pdo, $query, $params = [], $default_limit = 20) { + // Get current page + $page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1; + if ($page < 1) $page = 1; + + // Get limit (allow 20, 50, 100, or -1 for all) + $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : $default_limit; + // Validate limit + if ($limit != -1 && !in_array($limit, [20, 50, 100])) { + $limit = $default_limit; } - // If we are in admin/ or api/ or other subdirs, we might need to go up - // But this function is usually called from root files or with knowledge of its location - return $protocol . $domainName . $path; + // If limit is -1, fetch all + if ($limit == -1) { + $stmt = $pdo->prepare($query); + $stmt->execute($params); + $data = $stmt->fetchAll(); + return [ + 'data' => $data, + 'total_rows' => count($data), + 'total_pages' => 1, + 'current_page' => 1, + 'limit' => -1 + ]; + } + + // Count total rows using a subquery to handle complex queries safely + $count_sql = "SELECT COUNT(*) FROM ($query) as count_table"; + $stmt = $pdo->prepare($count_sql); + $stmt->execute($params); + $total_rows = $stmt->fetchColumn(); + + $total_pages = ceil($total_rows / $limit); + if ($page > $total_pages && $total_pages > 0) $page = $total_pages; + + // Calculate offset + $offset = ($page - 1) * $limit; + if ($offset < 0) $offset = 0; + + // Add LIMIT and OFFSET + $query_with_limit = $query . " LIMIT " . (int)$limit . " OFFSET " . (int)$offset; + + $stmt = $pdo->prepare($query_with_limit); + $stmt->execute($params); + $data = $stmt->fetchAll(); + + return [ + 'data' => $data, + 'total_rows' => $total_rows, + 'total_pages' => $total_pages, + 'current_page' => $page, + 'limit' => $limit + ]; +} + +/** + * Render pagination controls and limit selector. + * + * @param array $pagination The result array from paginate_query. + * @param array $extra_params Additional GET parameters to preserve. + */ +function render_pagination_controls($pagination, $extra_params = []) { + $page = $pagination['current_page']; + $total_pages = $pagination['total_pages']; + $limit = $pagination['limit']; + + // Build query string for limit change + $params = array_merge($_GET, $extra_params); + unset($params['page']); // Reset page when limit changes + + // Limit Selector + $limits = [20, 50, 100, -1]; + echo '