$processed, 'failed' => $failed]; } /** * @param array $job */ public static function processJob(array $job) { $type = $job['type'] ?? ''; if ($type === 'insert_full') { return self::insertFull($job['logs'] ?? []) !== null; } if ($type === 'enrich') { return self::enrich((int) ($job['log_id'] ?? 0), $job['logs'] ?? []); } return false; } /** * @param array $logs * @return int|null insert_id */ public static function insertFull(array $logs) { $conn = self::connect(); if (!$conn) { return null; } VisitorLogSchema::ensureColumns($conn); VisitorLogSchema::ensureIndexes($conn); $data = self::escapeLogs($conn, $logs); $d = static function ($key) use ($data, $conn) { return array_key_exists($key, $data) ? $data[$key] : cloak_db_escape($conn, ''); }; $sql = "INSERT INTO `visitor_logs`(`campagin_id`, `visit_md5_code`, `domain`, `visit_date`, `IP`, `country`, `result`, `reason`, `referer`, `client`, `browser`, `page`, `language`, `user_agent`, `http_referer`, `accept_language_raw`, `judge_timing`, `fp_url`, `device`) VALUES ('" . $d('campagin_id') . "','" . $d('visit_md5_code') . "','" . $d('site_name') . "','" . ($data['visit_date'] ?? date('Y-m-d H:i:s')) . "','" . $d('customers_ip') . "','" . $d('country') . "','" . $d('result') . "','" . $d('reason') . "','" . $d('v_referer') . "','" . $d('Client') . "','" . $d('v_Browser') . "','" . $d('v_PageURL') . "','" . $d('accept_language') . "','" . $d('user_agent') . "','" . $d('http_referer') . "','" . $d('accept_language_raw') . "','" . $d('judge_timing') . "','" . $d('fp_url') . "','" . $d('device') . "')"; if ($conn->query($sql) !== true) { VisitorLogQueue::logError('insert_full: ' . $conn->error . ' | ' . $sql); $conn->close(); return null; } $id = (int) $conn->insert_id; $conn->close(); return $id > 0 ? $id : null; } /** * 同步最小 INSERT(二次风控 wait,需立即返回 log_id) * * @param array $logs * @return int|null */ public static function insertMinimal(array $logs) { $conn = self::connect(); if (!$conn) { return null; } VisitorLogSchema::ensureColumns($conn); VisitorLogSchema::ensureIndexes($conn); $data = self::escapeLogs($conn, $logs); $d = static function ($key) use ($data, $conn) { return array_key_exists($key, $data) ? $data[$key] : cloak_db_escape($conn, ''); }; $sql = "INSERT INTO `visitor_logs`(`campagin_id`, `visit_md5_code`, `domain`, `visit_date`, `IP`, `country`, `result`, `reason`, `client`, `browser`, `language`, `fp_url`, `device`) VALUES ('" . $d('campagin_id') . "','" . $d('visit_md5_code') . "','" . $d('site_name') . "','" . date('Y-m-d H:i:s') . "','" . $d('customers_ip') . "','" . $d('country') . "','" . $d('result') . "','" . $d('reason') . "','" . $d('Client') . "','" . $d('v_Browser') . "','" . $d('accept_language') . "','" . $d('fp_url') . "','" . $d('device') . "')"; if ($conn->query($sql) !== true) { VisitorLogQueue::logError('insertMinimal: ' . $conn->error); $conn->close(); return null; } $id = (int) $conn->insert_id; $conn->close(); return $id > 0 ? $id : null; } /** * @param int $logId * @param array $logs */ public static function enrich($logId, array $logs) { if ($logId <= 0) { return false; } $conn = self::connect(); if (!$conn) { return false; } $data = self::escapeLogs($conn, $logs); $sets = []; $map = [ 'referer' => 'v_referer', 'page' => 'v_PageURL', 'user_agent' => 'user_agent', 'http_referer' => 'http_referer', 'accept_language_raw' => 'accept_language_raw', 'judge_timing' => 'judge_timing', ]; foreach ($map as $col => $logKey) { if (array_key_exists($logKey, $data)) { $sets[] = "`{$col}`='" . $data[$logKey] . "'"; } elseif (array_key_exists($col, $data)) { $sets[] = "`{$col}`='" . $data[$col] . "'"; } } if ($sets === []) { $conn->close(); return true; } $sql = 'UPDATE `visitor_logs` SET ' . implode(', ', $sets) . ' WHERE `id`=' . (int) $logId; $ok = $conn->query($sql) === true; if (!$ok) { VisitorLogQueue::logError('enrich: ' . $conn->error); } $conn->close(); return $ok; } /** * @param mysqli $conn * @param array $logs * @return array */ private static function escapeLogs($conn, array $logs) { $data = []; foreach ($logs as $key => $value) { $data[$key] = cloak_db_escape($conn, $value); } if (!isset($data['visit_date'])) { $data['visit_date'] = date('Y-m-d H:i:s'); } return $data; } /** * @return mysqli|null */ private static function connect() { if (!defined('DB_USERNAME') || !defined('DB_PASSWORD') || !defined('DB_NAME')) { return null; } $conn = @new mysqli('localhost', DB_USERNAME, DB_PASSWORD, DB_NAME); if ($conn->connect_error) { VisitorLogQueue::logError('DB connect: ' . $conn->connect_error); return null; } return $conn; } }