335 lines
12 KiB
PHP
335 lines
12 KiB
PHP
<?php
|
|
|
|
use Detection\MobileDetect;
|
|
|
|
if (!function_exists('detectDeviceInfo')) {
|
|
/**
|
|
* Deteksi informasi device menggunakan Mobile Detect Library
|
|
*
|
|
* @param string|null $userAgent User agent string (opsional)
|
|
* @return array Device information
|
|
*/
|
|
function detectDeviceInfo($userAgent = null)
|
|
{
|
|
$detect = new MobileDetect();
|
|
|
|
if ($userAgent !== null) {
|
|
$detect->setUserAgent($userAgent);
|
|
}
|
|
|
|
$ua = $detect->getUserAgent();
|
|
|
|
// === DETECT BRAND ===
|
|
$brand = 'Unknown';
|
|
|
|
// CEK BRAND SPESIFIK DULU
|
|
if (preg_match('/POCO/i', $ua)) {
|
|
$brand = 'POCO';
|
|
} elseif (preg_match('/Redmi/i', $ua)) {
|
|
$brand = 'Redmi';
|
|
} elseif (preg_match('/Infinix/i', $ua)) {
|
|
$brand = 'Infinix';
|
|
} elseif (preg_match('/Samsung|SM-|GT-|SCH-/i', $ua)) {
|
|
$brand = 'Samsung';
|
|
} elseif (preg_match('/OPPO|CPH/i', $ua)) {
|
|
$brand = 'Oppo';
|
|
} elseif (preg_match('/vivo|V\d{4}/i', $ua)) {
|
|
$brand = 'Vivo';
|
|
} elseif (preg_match('/Realme|RMX/i', $ua)) {
|
|
$brand = 'Realme';
|
|
} else {
|
|
$androidBrands = [
|
|
'Xiaomi', 'Huawei', 'OnePlus', 'Asus', 'Nokia', 'Sony',
|
|
'Motorola', 'LG', 'Lenovo', 'Tecno',
|
|
'Google', 'HTC', 'Meizu', 'ZTE'
|
|
];
|
|
|
|
foreach ($androidBrands as $b) {
|
|
if ($detect->is($b)) {
|
|
$brand = $b;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Detect iPhone & iPad
|
|
if ($detect->isiOS() && !$detect->isTablet()) {
|
|
$brand = 'iPhone';
|
|
} elseif ($detect->isiOS() && $detect->isTablet()) {
|
|
$brand = 'iPad';
|
|
}
|
|
|
|
// === DETECT MODEL ===
|
|
$model = 'Unknown';
|
|
|
|
// Samsung models
|
|
if ($brand === 'Samsung') {
|
|
if (preg_match('/(SM-[A-Z]\d{3,4}[A-Z]?|GT-[A-Z0-9]+|SCH-[A-Z0-9]+)/i', $ua, $matches)) {
|
|
$model = $matches[1];
|
|
}
|
|
}
|
|
// ⭐ FIX: POCO models - bisa berupa nama atau kode angka
|
|
elseif ($brand === 'POCO') {
|
|
// Cari pattern: POCO [nama model] atau kode angka (contoh: 21121210G)
|
|
if (preg_match('/POCO\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'POCO ' . trim($matches[1]);
|
|
}
|
|
// Jika tidak ada nama POCO, cari kode angka Xiaomi
|
|
elseif (preg_match('/\s([0-9]{8,9}[A-Z]?)(?:\s+Build)/i', $ua, $matches)) {
|
|
$model = $matches[1] . ' (POCO)';
|
|
}
|
|
}
|
|
// Redmi models
|
|
elseif ($brand === 'Redmi') {
|
|
if (preg_match('/Redmi\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'Redmi ' . trim($matches[1]);
|
|
}
|
|
// Fallback: kode angka
|
|
elseif (preg_match('/\s([0-9]{8,9}[A-Z]?)(?:\s+Build)/i', $ua, $matches)) {
|
|
$model = $matches[1] . ' (Redmi)';
|
|
}
|
|
}
|
|
// Xiaomi models
|
|
elseif ($brand === 'Xiaomi') {
|
|
if (preg_match('/Mi\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'Mi ' . trim($matches[1]);
|
|
}
|
|
// Fallback: kode angka
|
|
elseif (preg_match('/\s([0-9]{8,9}[A-Z]?)(?:\s+Build)/i', $ua, $matches)) {
|
|
$model = $matches[1] . ' (Xiaomi)';
|
|
}
|
|
}
|
|
// Infinix models
|
|
elseif ($brand === 'Infinix') {
|
|
if (preg_match('/Infinix\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'Infinix ' . trim($matches[1]);
|
|
}
|
|
elseif (preg_match('/(X\d{3,4}[A-Z]?)/i', $ua, $matches)) {
|
|
$model = $matches[1];
|
|
}
|
|
}
|
|
// Oppo models
|
|
elseif ($brand === 'Oppo') {
|
|
if (preg_match('/(CPH\d+|PBAM\d+|PBEM\d+)/i', $ua, $matches)) {
|
|
$model = $matches[1];
|
|
}
|
|
elseif (preg_match('/OPPO\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'OPPO ' . trim($matches[1]);
|
|
}
|
|
}
|
|
// Vivo models
|
|
elseif ($brand === 'Vivo') {
|
|
if (preg_match('/(V\d{4})/i', $ua, $matches)) {
|
|
$model = $matches[1];
|
|
}
|
|
elseif (preg_match('/vivo\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'vivo ' . trim($matches[1]);
|
|
}
|
|
}
|
|
// Realme models
|
|
elseif ($brand === 'Realme') {
|
|
if (preg_match('/(RMX\d+)/i', $ua, $matches)) {
|
|
$model = $matches[1];
|
|
}
|
|
elseif (preg_match('/Realme\s+([A-Z0-9\s\-]+?)(?:\s+Build|\)|;)/i', $ua, $matches)) {
|
|
$model = 'Realme ' . trim($matches[1]);
|
|
}
|
|
}
|
|
// iPhone models
|
|
elseif ($brand === 'iPhone') {
|
|
if (preg_match('/iPhone(\d+[,\d]*)?/i', $ua, $matches)) {
|
|
$model = 'iPhone' . ($matches[1] ? ' ' . str_replace(',', '.', $matches[1]) : '');
|
|
} else {
|
|
$model = 'iPhone';
|
|
}
|
|
}
|
|
// iPad models
|
|
elseif ($brand === 'iPad') {
|
|
if (preg_match('/iPad[\d,]*;/i', $ua, $matches)) {
|
|
$model = trim(str_replace(';', '', $matches[0]));
|
|
}
|
|
}
|
|
|
|
// === DETECT OS & VERSION ===
|
|
$os = 'Unknown';
|
|
$osVersion = 'Unknown';
|
|
|
|
if ($detect->isiOS()) {
|
|
$os = 'iOS';
|
|
$osVersion = $detect->version('iOS') ?: 'Unknown';
|
|
} elseif ($detect->isAndroidOS()) {
|
|
$os = 'Android';
|
|
$osVersion = $detect->version('Android') ?: 'Unknown';
|
|
} elseif (preg_match('/Windows/i', $ua)) {
|
|
$os = 'Windows';
|
|
if (preg_match('/Windows NT ([0-9\.]+)/i', $ua, $matches)) {
|
|
$osVersion = $matches[1];
|
|
}
|
|
}
|
|
|
|
// === DETECT BROWSER ===
|
|
$browser = 'Unknown';
|
|
$browserVersion = 'Unknown';
|
|
|
|
// Chrome
|
|
if (preg_match('/Chrome\/([0-9\.]+)/i', $ua, $matches)) {
|
|
$browser = 'Chrome';
|
|
$browserVersion = $matches[1];
|
|
}
|
|
// Safari (non-Chrome)
|
|
elseif (preg_match('/Safari\/([0-9\.]+)/i', $ua, $matches) && !preg_match('/Chrome/i', $ua)) {
|
|
$browser = 'Safari';
|
|
if (preg_match('/Version\/([0-9\.]+)/i', $ua, $vMatches)) {
|
|
$browserVersion = $vMatches[1];
|
|
}
|
|
}
|
|
// Firefox
|
|
elseif (preg_match('/Firefox\/([0-9\.]+)/i', $ua, $matches)) {
|
|
$browser = 'Firefox';
|
|
$browserVersion = $matches[1];
|
|
}
|
|
|
|
// === DEVICE TYPE ===
|
|
$deviceType = 'desktop';
|
|
if ($detect->isTablet()) {
|
|
$deviceType = 'tablet';
|
|
} elseif ($detect->isMobile()) {
|
|
$deviceType = 'phone';
|
|
}
|
|
|
|
return [
|
|
'brand' => $brand,
|
|
'model' => $model,
|
|
'os' => $os,
|
|
'os_version' => $osVersion,
|
|
'browser' => $browser,
|
|
'browser_version' => $browserVersion,
|
|
'device_type' => $deviceType,
|
|
'is_mobile' => $detect->isMobile(),
|
|
'is_tablet' => $detect->isTablet(),
|
|
'is_phone' => $detect->isMobile() && !$detect->isTablet(),
|
|
'user_agent' => $ua
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('getCameraVersionSupport')) {
|
|
/**
|
|
* Get camera version support untuk device tertentu
|
|
*
|
|
* @param string $deviceBrand Brand device (Samsung, POCO, dll)
|
|
* @param string $deviceModel Model device (SM-S931B, POCO X5, dll)
|
|
* @return array Camera version support info
|
|
*/
|
|
function getCameraVersionSupport($deviceBrand, $deviceModel)
|
|
{
|
|
$db = \Config\Database::connect();
|
|
|
|
// Cek apakah ada mapping SPESIFIK untuk model ini
|
|
$compatibility = $db->table('device_camera_compatibility')
|
|
->where('device_brand', $deviceBrand)
|
|
->where('device_model', $deviceModel)
|
|
->where('is_active', true)
|
|
->get()
|
|
->getRow();
|
|
|
|
// Jika tidak ada, cek mapping untuk BRAND (device_model = NULL)
|
|
if (!$compatibility) {
|
|
$compatibility = $db->table('device_camera_compatibility')
|
|
->where('device_brand', $deviceBrand)
|
|
->where('device_model', null)
|
|
->where('is_active', true)
|
|
->get()
|
|
->getRow();
|
|
}
|
|
|
|
// JIKA TIDAK ADA DI DATABASE = SUPPORT SEMUA VERSI (DEFAULT)
|
|
if (!$compatibility) {
|
|
return [
|
|
'support_version_1' => true,
|
|
'support_version_2' => true,
|
|
'support_version_3' => true,
|
|
'recommended_version' => 3, // Recommend versi tertinggi
|
|
'available_versions' => [1, 2, 3],
|
|
'notes' => 'Device tidak ada limitasi - support semua versi kamera',
|
|
'is_default' => true // Flag untuk tahu ini default behavior
|
|
];
|
|
}
|
|
|
|
// Build available versions array
|
|
$availableVersions = [];
|
|
if ($compatibility->support_version_1) $availableVersions[] = 1;
|
|
if ($compatibility->support_version_2) $availableVersions[] = 2;
|
|
if ($compatibility->support_version_3) $availableVersions[] = 3;
|
|
|
|
return [
|
|
'support_version_1' => (bool)$compatibility->support_version_1,
|
|
'support_version_2' => (bool)$compatibility->support_version_2,
|
|
'support_version_3' => (bool)$compatibility->support_version_3,
|
|
'recommended_version' => $compatibility->recommended_version,
|
|
'available_versions' => $availableVersions,
|
|
'notes' => $compatibility->notes,
|
|
'is_default' => false // Ini bukan default, ada di database
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('getDeviceFingerprint')) {
|
|
function getDeviceFingerprint($userAgent, $ipAddress)
|
|
{
|
|
return md5($userAgent . '|' . $ipAddress);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('isDeviceTrusted')) {
|
|
/**
|
|
* Cek apakah device sudah dipercaya
|
|
*
|
|
* @param string $deviceFingerprint
|
|
* @param string $superUserId
|
|
* @return bool
|
|
*/
|
|
function isDeviceTrusted($deviceFingerprint, $superUserId)
|
|
{
|
|
$db = \Config\Database::connect();
|
|
|
|
$device = $db->table('user_devices')
|
|
->where('device_fingerprint', $deviceFingerprint)
|
|
->where('super_user_id', $superUserId)
|
|
->where('is_trusted', true)
|
|
->where('is_blocked', false)
|
|
->get()
|
|
->getRow();
|
|
|
|
return $device !== null;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('isDeviceBlocked')) {
|
|
/**
|
|
* Cek apakah device diblokir
|
|
*
|
|
* @param string $deviceFingerprint
|
|
* @return array|null Device info if blocked, null otherwise
|
|
*/
|
|
function isDeviceBlocked($deviceFingerprint)
|
|
{
|
|
$db = \Config\Database::connect();
|
|
|
|
$device = $db->table('user_devices')
|
|
->where('device_fingerprint', $deviceFingerprint)
|
|
->where('is_blocked', true)
|
|
->get()
|
|
->getRow();
|
|
|
|
if ($device) {
|
|
return [
|
|
'is_blocked' => true,
|
|
'reason' => $device->blocked_reason,
|
|
'blocked_at' => $device->blocked_at
|
|
];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
} |