38682-vm/includes/functions.php
2026-02-23 03:43:41 +00:00

187 lines
6.9 KiB
PHP

<?php
// Function to fetch company settings from DB
function get_company_settings() {
static $settings = null;
if ($settings === null) {
$pdo = db();
try {
$stmt = $pdo->query("SELECT * FROM company_settings LIMIT 1");
$settings = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
// Log error or ignore if table doesn't exist yet
}
// Default values if no settings found
if (!$settings) {
$settings = [
'company_name' => 'My Restaurant',
'address' => '123 Food Street',
'phone' => '555-0199',
'email' => 'info@restaurant.com',
'vat_rate' => 0.00,
'currency_symbol' => '$',
'currency_decimals' => 2
];
}
}
return $settings;
}
// Function to format currency using settings
function format_currency($amount) {
$settings = get_company_settings();
return $settings['currency_symbol'] . number_format((float)$amount, (int)$settings['currency_decimals']);
}
/**
* 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, default to 20 if not standard, allow custom if needed but standardizing is safer
if ($limit != -1 && !in_array($limit, [20, 50, 100])) {
$limit = $default_limit;
}
// 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
// Note: PDO parameters for LIMIT/OFFSET can be tricky with some drivers, sticking to direct injection for integers is safe here
$query .= " LIMIT " . (int)$limit . " OFFSET " . (int)$offset;
$stmt = $pdo->prepare($query);
$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 '<div class="d-flex justify-content-between align-items-center mb-3 bg-white p-2 rounded border">';
echo '<div class="d-flex align-items-center">';
echo '<form method="GET" class="d-flex align-items-center mb-0">';
// Preserve other GET params
foreach ($params as $key => $val) {
if ($key !== 'limit') echo '<input type="hidden" name="'.htmlspecialchars($key).'" value="'.htmlspecialchars($val).'">';
}
echo '<small class="me-2 text-muted">Show:</small>';
echo '<select name="limit" class="form-select form-select-sm border-0 bg-light" style="width: auto; font-weight: 500;" onchange="this.form.submit()">';
foreach ($limits as $l) {
$label = $l == -1 ? 'All' : $l;
$selected = $limit == $l ? 'selected' : '';
echo "<option value='$l' $selected>$label</option>";
}
echo '</select>';
echo '</form>';
// Total Count
echo '<span class="text-muted small ms-3 border-start ps-3">Total: <strong>' . $pagination['total_rows'] . '</strong></span>';
echo '</div>';
// Pagination Links
if ($total_pages > 1) {
echo '<nav><ul class="pagination pagination-sm mb-0">';
// Previous
$prev_disabled = $page <= 1 ? 'disabled' : '';
$prev_page = max(1, $page - 1);
$url_params = array_merge($params, ['page' => $prev_page, 'limit' => $limit]);
$prev_url = '?' . http_build_query($url_params);
echo "<li class='page-item $prev_disabled'><a class='page-link' href='$prev_url'>&laquo;</a></li>";
// Logic to show limited page numbers with ellipsis
// Always show first, last, current, and surrounding
$shown_pages = [];
$shown_pages[] = 1;
$shown_pages[] = $total_pages;
for ($i = $page - 2; $i <= $page + 2; $i++) {
if ($i > 1 && $i < $total_pages) {
$shown_pages[] = $i;
}
}
sort($shown_pages);
$shown_pages = array_unique($shown_pages);
$prev_p = 0;
foreach ($shown_pages as $p) {
if ($prev_p > 0 && $p > $prev_p + 1) {
echo "<li class='page-item disabled'><span class='page-link'>...</span></li>";
}
$active = $p == $page ? 'active' : '';
$url_params = array_merge($params, ['page' => $p, 'limit' => $limit]);
$url = '?' . http_build_query($url_params);
echo "<li class='page-item $active'><a class='page-link' href='$url'>$p</a></li>";
$prev_p = $p;
}
// Next
$next_disabled = $page >= $total_pages ? 'disabled' : '';
$next_page = min($total_pages, $page + 1);
$url_params = array_merge($params, ['page' => $next_page, 'limit' => $limit]);
$next_url = '?' . http_build_query($url_params);
echo "<li class='page-item $next_disabled'><a class='page-link' href='$next_url'>&raquo;</a></li>";
echo '</ul></nav>';
}
echo '</div>';
}