PHP WebShell
Текущая директория: /var/www/bitcardoApp/backyard/models/dashboard
Просмотр файла: index.php
<?php
// backyard/models/dashboard/index.php
// Pure functions that read from $conn (procedural MySQLi). No side effects.
// If your project globally enables mysqli exceptions, we can catch them below.
// If not, the try/catch is harmless.
function dash_q_scalar(mysqli $conn, string $sql, string $field = 'c', int|float $default = 0) {
try {
$res = mysqli_query($conn, $sql);
if ($res) {
$row = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if ($row && array_key_exists($field, $row)) {
return is_numeric($row[$field]) ? 0 + $row[$field] : $default;
}
}
} catch (\mysqli_sql_exception $e) {
// Optionally log error somewhere:
// error_log('dash_q_scalar error: ' . $e->getMessage());
}
return $default;
}
/**
* Overview metrics for dashboard header.
* - users_count: total active users
* - transactions_count: total transactions
* - today_giftcard_usd: sum of today's gift card trades in USD-like currency (USD or '$')
* - today_trades_count: number of today's gift card trades
*/
function dash_get_overview(mysqli $conn): array {
$overview = [
'users_count' => 0,
'transactions_count' => 0,
'today_giftcard_usd' => 0.0,
'today_trades_count' => 0,
];
// Users (active)
$overview['users_count'] = (int) dash_q_scalar(
$conn,
"SELECT COUNT(*) AS c FROM `users` WHERE `user_status` = 'Active'"
);
// Transactions (all)
$overview['transactions_count'] = (int) dash_q_scalar(
$conn,
"SELECT COUNT(*) AS c FROM `transactions`"
);
// Today's gift card trades (USD-like)
// Keep single-line SQL to avoid hidden characters
try {
$sql = "SELECT COALESCE(SUM(card_value),0) AS total_value, COUNT(*) AS trade_count FROM `card_trade` WHERE DATE(`trade_created`) = CURDATE() AND (`card_curr` = 'USD' OR `card_curr` = '$')";
$res = mysqli_query($conn, $sql);
if ($res) {
$row = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if ($row) {
$overview['today_giftcard_usd'] = (float) ($row['total_value'] ?? 0);
$overview['today_trades_count'] = (int) ($row['trade_count'] ?? 0);
}
}
} catch (\mysqli_sql_exception $e) {
// error_log('dash_get_overview today USD error: ' . $e->getMessage());
}
return $overview;
}
/**
* Central wallets with aggregated user balances.
* Returns up to $limit rows with keys:
* coin, icon, status, platform_balance, user_balance, growth_percent
*/
function dash_get_platform_wallets(mysqli $conn, int $limit = 6): array {
$wallets = [];
try {
$limit = max(1, (int)$limit);
$sql = "SELECT * FROM `cwallet` ORDER BY `cwallet_id` ASC LIMIT {$limit}";
$res = mysqli_query($conn, $sql);
if (!$res) {
return $wallets;
}
while ($w = mysqli_fetch_assoc($res)) {
$coin = $w['coin'] ?? '';
$icon = $w['icon'] ?? '';
$status = $w['status'] ?? '';
$platform_balance = (float)($w['wallet_balance'] ?? 0);
// Sum of all users' balances for the same coin
$coin_safe = mysqli_real_escape_string($conn, (string)$coin);
$sum_sql = "SELECT COALESCE(SUM(`balance`),0) AS total_user_balance FROM `user_wallets` WHERE `coin` = '{$coin_safe}'";
$user_balance = 0.0;
try {
$sum_res = mysqli_query($conn, $sum_sql);
if ($sum_res) {
$sum_row = mysqli_fetch_assoc($sum_res);
mysqli_free_result($sum_res);
if ($sum_row) {
$user_balance = (float)($sum_row['total_user_balance'] ?? 0);
}
}
} catch (\mysqli_sql_exception $e) {
// error_log('dash_get_platform_wallets sum error: ' . $e->getMessage());
}
// Growth: platform vs users
$growth_percent = 0.0;
if ($user_balance > 0) {
$growth_percent = (($platform_balance - $user_balance) / $user_balance) * 100.0;
}
$wallets[] = [
'coin' => $coin,
'icon' => $icon,
'status' => $status,
'platform_balance' => $platform_balance,
'user_balance' => $user_balance,
'growth_percent' => $growth_percent,
];
}
mysqli_free_result($res);
} catch (\mysqli_sql_exception $e) {
// error_log('dash_get_platform_wallets error: ' . $e->getMessage());
return $wallets;
}
return $wallets;
}
/**
* Recent gift card batches (one row per batch_ref).
* Returns rows:
* - batch_ref, first_name, last_name, total_payout, cards_count
* - ok_count, pending_count, bad_count, last_time
*/
function dash_get_recent_giftcard_batches(mysqli $conn, int $limit = 10): array {
$rows = [];
$limit = max(1, (int)$limit);
// Use MAX() to pick a representative name from the batch (safe for ONLY_FULL_GROUP_BY)
$sql = "
SELECT
ct.batch_ref,
MAX(u.first_name) AS first_name,
MAX(u.last_name) AS last_name,
SUM(ct.est_payout_ngn) AS total_payout,
COUNT(*) AS cards_count,
SUM(ct.trade_status IN ('SUCCESS','COMPLETED','APPROVED')) AS ok_count,
SUM(ct.trade_status IN ('PENDING','PROCESSING')) AS pending_count,
SUM(ct.trade_status IN ('DECLINED','FAILED','REJECTED')) AS bad_count,
MAX(ct.trade_created) AS last_time
FROM card_trade ct
LEFT JOIN users u ON u.user_id = ct.user_id
WHERE ct.batch_ref IS NOT NULL AND ct.batch_ref <> ''
GROUP BY ct.batch_ref
ORDER BY last_time DESC
LIMIT {$limit}
";
try {
if ($res = mysqli_query($conn, $sql)) {
while ($r = mysqli_fetch_assoc($res)) {
$rows[] = [
'batch_ref' => $r['batch_ref'] ?? '',
'first_name' => $r['first_name'] ?? '',
'last_name' => $r['last_name'] ?? '',
'total_payout' => (float)($r['total_payout'] ?? 0),
'cards_count' => (int)($r['cards_count'] ?? 0),
'ok_count' => (int)($r['ok_count'] ?? 0),
'pending_count'=> (int)($r['pending_count'] ?? 0),
'bad_count' => (int)($r['bad_count'] ?? 0),
'last_time' => $r['last_time'] ?? null,
];
}
mysqli_free_result($res);
}
} catch (\mysqli_sql_exception $e) {}
return $rows;
}
/**
* Compute a batch status from component counts.
*/
function dash_batch_status(array $b): string {
$ok = (int)($b['ok_count'] ?? 0);
$pd = (int)($b['pending_count'] ?? 0);
$bd = (int)($b['bad_count'] ?? 0);
$total = (int)($b['cards_count'] ?? 0);
if ($total > 0 && $ok === $total) return 'Success';
if ($pd > 0 && $bd === 0) return 'Pending';
if ($bd > 0 && $ok === 0 && $pd === 0) return 'Declined';
if ($bd > 0 && ($ok > 0 || $pd > 0)) return 'Mixed';
return 'Unknown';
}
/**
* Batch details + member cards for process_order.php
* Returns ['batch' => summary, 'cards' => [...]]
*/
function dash_get_batch_details(mysqli $conn, string $batch_ref): array {
$batch_ref_safe = mysqli_real_escape_string($conn, $batch_ref);
$out = ['batch' => null, 'cards' => []];
// Summary
$sum_sql = "
SELECT
ct.batch_ref,
MAX(u.first_name) AS first_name,
MAX(u.last_name) AS last_name,
SUM(ct.est_payout_ngn) AS total_payout,
COUNT(*) AS cards_count,
SUM(ct.trade_status IN ('SUCCESS','COMPLETED','APPROVED')) AS ok_count,
SUM(ct.trade_status IN ('PENDING','PROCESSING')) AS pending_count,
SUM(ct.trade_status IN ('DECLINED','FAILED','REJECTED')) AS bad_count,
MAX(ct.trade_created) AS last_time
FROM card_trade ct
LEFT JOIN users u ON u.user_id = ct.user_id
WHERE ct.batch_ref = '{$batch_ref_safe}'
GROUP BY ct.batch_ref
LIMIT 1
";
if ($res = mysqli_query($conn, $sum_sql)) {
$out['batch'] = mysqli_fetch_assoc($res) ?: null;
mysqli_free_result($res);
}
// Cards in batch
$cards_sql = "
SELECT
ct.trade_id, ct.trade_ref, ct.trade_status, ct.trade_created,
ct.card_value, ct.card_curr, ct.buy_price_snapshot, ct.est_payout_ngn,
ct.note,
cb.card_brand, gc.demon
FROM card_trade ct
LEFT JOIN card_brands cb ON cb.cbrand_id = ct.cbrand_id
LEFT JOIN gift_cards gc ON gc.gc_id = ct.gc_id
WHERE ct.batch_ref = '{$batch_ref_safe}'
ORDER BY ct.trade_created ASC, ct.trade_id ASC
";
if ($cres = mysqli_query($conn, $cards_sql)) {
while ($row = mysqli_fetch_assoc($cres)) {
$out['cards'][] = $row;
}
mysqli_free_result($cres);
}
return $out;
}
/**
* Images for multiple trade_ids in one call.
* @return array trade_id => [imageRows...]
*/
function dash_get_images_for_trades(mysqli $conn, array $trade_ids): array {
$imgs = [];
if (empty($trade_ids)) return $imgs;
$ids = array_map('intval', $trade_ids);
$idlist = implode(',', $ids);
$sql = "SELECT trade_id, image_id, path, original_name, mime, size, uploaded_at
FROM card_trade_images
WHERE trade_id IN ({$idlist})
ORDER BY trade_id ASC, image_id ASC";
if ($res = mysqli_query($conn, $sql)) {
while ($r = mysqli_fetch_assoc($res)) {
$tid = (int)$r['trade_id'];
if (!isset($imgs[$tid])) $imgs[$tid] = [];
$imgs[$tid][] = $r;
}
mysqli_free_result($res);
}
return $imgs;
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!