hotter color. */ function cut_class(int $cut): string { return $cut >= 75 ? 'cut-hi' : ($cut >= 50 ? 'cut-mid' : 'cut-lo'); } /** * Deal rating label comparing current price to the all-time low. */ function deal_rating(float $hl, float $price): array { $ratio = $price > 0 ? $hl / $price : 0; return match (true) { $ratio >= 0.99 => ['label' => '🔥 Hot', 'cls' => 'rating-best', 'ratio' => $ratio], $ratio >= 0.85 => ['label' => '🔥 Hot', 'cls' => 'rating-great', 'ratio' => $ratio], $ratio >= 0.6 => ['label' => 'Good deal', 'cls' => 'rating-good', 'ratio' => $ratio], $ratio >= 0.35 => ['label' => 'Fair deal', 'cls' => 'rating-fair', 'ratio' => $ratio], default => ['label' => 'High price', 'cls' => 'rating-high', 'ratio' => $ratio], }; } /** * Build a URL like the current one with query params overridden. */ function qs_url(array $overrides = [], array $remove = []): string { $get = service('request')->getGet(); $get = array_map(static fn ($v) => is_array($v) ? array_values(array_filter($v, 'strlen')) : $v, $get); foreach ($remove as $key) { unset($get[$key]); } $get = array_merge($get, $overrides); // drop empty / zero-default params for clean URLs foreach ($get as $key => $val) { if (is_array($val)) { if ($val === []) unset($get[$key]); continue; } if ($key === 'min_cut' && (int) $val === 0) { unset($get[$key]); continue; } if ($key === 'kind' && $val === '') { unset($get[$key]); continue; } if ($key === 'page' && ($val === null || (int) $val === 1)) { unset($get[$key]); continue; } if (($key === 'min_price' || $key === 'max_price' || $key === 'q') && $val === '') { unset($get[$key]); continue; } } $qs = http_build_query($get); // keep the current path (e.g. /games/rpg) so filters stay within it $path = '/' . ltrim(uri_string(), '/'); return $path . ($qs !== '' ? '?' . $qs : ''); } function store_initials(string $name): string { $words = preg_split('/\s+/', $name) ?: []; $ini = ''; foreach ($words as $w) { if ($w === '' || ! ctype_alpha($w[0])) { continue; } $ini .= strtoupper($w[0]); if (strlen($ini) >= 2) { break; } } return $ini !== '' ? $ini : strtoupper(substr($name, 0, 2)); } function time_ago(int|string|MongoDB\BSON\UTCDateTime $ts): string { if ($ts instanceof MongoDB\BSON\UTCDateTime) { $ts = $ts->toDateTime()->getTimestamp(); } $diff = max(1, time() - (int) $ts); if ($diff < 3600) return floor($diff / 60) . ' min ago'; if ($diff < 86400) return floor($diff / 3600) . ' h ago'; if ($diff < 86400*30) return floor($diff / 86400) . ' days ago'; if ($diff < 86400*365) return floor($diff / (86400*30)) . ' months ago'; return floor($diff / (86400*365)) . ' y ago'; } function bson_date($ts): ?string { if (! $ts instanceof MongoDB\BSON\UTCDateTime) { return null; } return date('M j, Y', $ts->toDateTime()->getTimestamp()); }