mirror of https://github.com/4xmen/xshop.git
added visitor statistics
parent
1c09293f1c
commit
8bef2c82b4
@ -0,0 +1,426 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package Helpers
|
||||||
|
* @author A1Gard <a1gard@4xmen.ir>
|
||||||
|
* @date : 3-April-2013 (14-1-1392)
|
||||||
|
* @time : 20:32
|
||||||
|
* @subpackage TVisitor
|
||||||
|
* @version 1.0
|
||||||
|
* @todo : TVisitor class for get visitor info
|
||||||
|
*/
|
||||||
|
class TVisitor {
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Detect visitor OS
|
||||||
|
* @return int os number
|
||||||
|
*/
|
||||||
|
public static function DetectOSI() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT']))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$os_list = array(
|
||||||
|
'(Linux)',
|
||||||
|
'(Windows NT 11.0)', // Added Windows 11
|
||||||
|
'(Windows NT 10.0)',
|
||||||
|
'(Windows NT 6.3)',
|
||||||
|
'(Windows NT 6.2)',
|
||||||
|
'(Windows NT 6.1)',
|
||||||
|
'(Windows NT 6.0)',
|
||||||
|
'(Windows NT 5.2)',
|
||||||
|
'(Windows NT 5.1)',
|
||||||
|
'(Windows NT 5.0)',
|
||||||
|
'(Windows NT 4.0)',
|
||||||
|
'(Win 9x 4.90)',
|
||||||
|
'(Windows 98)',
|
||||||
|
'(Windows 95)',
|
||||||
|
'(Windows CE)',
|
||||||
|
'Windows (iPhone|iPad)',
|
||||||
|
'(iPhone)|(iPad)',
|
||||||
|
'(Mac OS X)',
|
||||||
|
'(MacPPC)|(Mac_PowerPC)|(Macintosh)',
|
||||||
|
'(Ubuntu)',
|
||||||
|
'(Linux Mint)',
|
||||||
|
'(Debian)',
|
||||||
|
'(Fedora)',
|
||||||
|
'(Red Hat)',
|
||||||
|
'(SuSE)',
|
||||||
|
'(Android)',
|
||||||
|
'(webOS)|(hpwOS)',
|
||||||
|
'(BlackBerry)',
|
||||||
|
'(Symbian)',
|
||||||
|
'(FreeBSD)',
|
||||||
|
'(OpenBSD)',
|
||||||
|
'(NetBSD)',
|
||||||
|
'(SunOS)',
|
||||||
|
'(OpenSolaris)',
|
||||||
|
'(Chrome OS)',
|
||||||
|
'(CrOS)',
|
||||||
|
'(bot)'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($os_list as $index => $match) {
|
||||||
|
if (preg_match("/$match/i", $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return $index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Detect visitor OS
|
||||||
|
* @return string OS name
|
||||||
|
*/
|
||||||
|
public static function DetectOS() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT']))
|
||||||
|
return 'Unknown';
|
||||||
|
|
||||||
|
$os_list = array(
|
||||||
|
'Linux' => '(Linux)',
|
||||||
|
'Windows 11' => '(Windows NT 11.0)', // Added Windows 11
|
||||||
|
'Windows 10' => '(Windows NT 10.0)',
|
||||||
|
'Windows 8.1' => '(Windows NT 6.3)',
|
||||||
|
'Windows 8' => '(Windows NT 6.2)',
|
||||||
|
'Windows 7' => '(Windows NT 6.1)',
|
||||||
|
'Windows Vista' => '(Windows NT 6.0)',
|
||||||
|
'Windows Server 2003/XP x64' => '(Windows NT 5.2)',
|
||||||
|
'Windows XP' => '(Windows NT 5.1)',
|
||||||
|
'Windows 2000' => '(Windows NT 5.0)',
|
||||||
|
'Windows ME' => '(Win 9x 4.90)',
|
||||||
|
'Windows 98' => '(Windows 98)',
|
||||||
|
'Windows 95' => '(Windows 95)',
|
||||||
|
'Windows CE' => '(Windows CE)',
|
||||||
|
'Windows (iPhone/iPad)' => 'Windows (iPhone|iPad)',
|
||||||
|
'iPhone/iPad' => '(iPhone)|(iPad)',
|
||||||
|
'Mac OS X' => '(Mac OS X)',
|
||||||
|
'Mac OS' => '(MacPPC)|(Mac_PowerPC)|(Macintosh)',
|
||||||
|
'Ubuntu' => '(Ubuntu)',
|
||||||
|
'Linux Mint' => '(Linux Mint)',
|
||||||
|
'Debian' => '(Debian)',
|
||||||
|
'Fedora' => '(Fedora)',
|
||||||
|
'Red Hat' => '(Red Hat)',
|
||||||
|
'SuSE' => '(SuSE)',
|
||||||
|
'Android' => '(Android)',
|
||||||
|
'webOS' => '(webOS)|(hpwOS)',
|
||||||
|
'BlackBerry' => '(BlackBerry)',
|
||||||
|
'Symbian' => '(Symbian)',
|
||||||
|
'FreeBSD' => '(FreeBSD)',
|
||||||
|
'OpenBSD' => '(OpenBSD)',
|
||||||
|
'NetBSD' => '(NetBSD)',
|
||||||
|
'SunOS' => '(SunOS)',
|
||||||
|
'OpenSolaris' => '(OpenSolaris)',
|
||||||
|
'Chrome OS' => '(Chrome OS)|(CrOS)',
|
||||||
|
'bot' => '(bot)'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($os_list as $os => $pattern) {
|
||||||
|
if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return $os;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Detect if visitor is using a mobile device
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function IsMobile() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
|
||||||
|
|
||||||
|
// List of mobile devices and operating systems
|
||||||
|
$mobile_agents = [
|
||||||
|
'mobile', 'android', 'iphone', 'ipod', 'ipad', 'windows phone', 'blackberry', 'kindle', 'silk',
|
||||||
|
'opera mini', 'opera mobi', 'webos', 'symbian', 'nokia', 'samsung', 'lg', 'htc', 'mot', 'tablet',
|
||||||
|
'rim tablet', 'meego', 'netfront', 'bolt', 'fennec', 'series60', 'maemo', 'midp', 'cldc', 'up.browser',
|
||||||
|
'up.link', 'mmp', 'symbian', 'smartphone', 'wap'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if user agent contains any mobile keywords
|
||||||
|
foreach ($mobile_agents as $agent) {
|
||||||
|
if (strpos($user_agent, $agent) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for mobile-specific headers
|
||||||
|
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||||||
|
if (strpos(strtolower($_SERVER['HTTP_ACCEPT']), 'application/vnd.wap.xhtml+xml') !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Opera Mini
|
||||||
|
if (isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use PHP's built-in mobile detection (if available)
|
||||||
|
if (function_exists('http_negotiate_language')) {
|
||||||
|
$accept = http_negotiate_language(['wap', 'html']);
|
||||||
|
if ($accept === 'wap') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Get browser name only
|
||||||
|
* @return string browser name
|
||||||
|
*/
|
||||||
|
public static function DetectBrowser() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT']))
|
||||||
|
return 'Unknown';
|
||||||
|
|
||||||
|
$browser_list = array(
|
||||||
|
'Firefox' => '(Firefox)',
|
||||||
|
'Edge' => '(Edg|Edge)',
|
||||||
|
'Chrome' => '(Chrome)(?!.*Edge)',
|
||||||
|
'Safari' => '(Safari)(?!.*Chrome)',
|
||||||
|
'Opera' => '(OPR|Opera)',
|
||||||
|
'Brave' => '(Brave)',
|
||||||
|
'Internet Explorer' => '(MSIE|Trident)',
|
||||||
|
'DeepNet Explorer' => '(Deepnet)',
|
||||||
|
'Flock' => '(Flock)',
|
||||||
|
'Maxthon' => '(Maxthon)',
|
||||||
|
'Avant Browser' => '(Avant)',
|
||||||
|
'AOL' => '(AOL)',
|
||||||
|
'Vivaldi' => '(Vivaldi)',
|
||||||
|
'UC Browser' => '(UCBrowser)',
|
||||||
|
'Yandex Browser' => '(YaBrowser)',
|
||||||
|
'Samsung Internet' => '(SamsungBrowser)',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($browser_list as $browser => $pattern) {
|
||||||
|
if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return $browser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Other';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Get browser name only
|
||||||
|
* @return int browser num
|
||||||
|
*/
|
||||||
|
public static function DetectBrowserI() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT']))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$browser_list = array(
|
||||||
|
'(Firefox)',
|
||||||
|
'(Edg|Edge)',
|
||||||
|
'(Chrome)(?!.*Edge)',
|
||||||
|
'(Safari)(?!.*Chrome)',
|
||||||
|
'(OPR|Opera)',
|
||||||
|
'(Brave)',
|
||||||
|
'(MSIE|Trident)',
|
||||||
|
'(Deepnet)',
|
||||||
|
'(Flock)',
|
||||||
|
'(Maxthon)',
|
||||||
|
'(Avant)',
|
||||||
|
'(AOL)',
|
||||||
|
'(Vivaldi)',
|
||||||
|
'(UCBrowser)',
|
||||||
|
'(YaBrowser)',
|
||||||
|
'(SamsungBrowser)',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($browser_list as $index => $pattern) {
|
||||||
|
if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return $index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Find browser version
|
||||||
|
* @return string version
|
||||||
|
*/
|
||||||
|
public static function BrowserVersion() {
|
||||||
|
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||||
|
$browser = self::DetectBrowser();
|
||||||
|
|
||||||
|
$version = null;
|
||||||
|
|
||||||
|
switch ($browser) {
|
||||||
|
case 'Edge':
|
||||||
|
if (preg_match('/(Edge|Edg)\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Chrome':
|
||||||
|
if (preg_match('/Chrome\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Firefox':
|
||||||
|
if (preg_match('/Firefox\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Safari':
|
||||||
|
if (preg_match('/Version\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Opera':
|
||||||
|
if (preg_match('/(OPR|Opera)\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Internet Explorer':
|
||||||
|
if (preg_match('/MSIE (\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1];
|
||||||
|
} elseif (preg_match('/rv:(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1]; // For IE 11
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Generic version detection for other browsers
|
||||||
|
if (preg_match('/' . preg_quote($browser, '/') . '\/(\d+(\.\d+)*)/', $ua, $matches)) {
|
||||||
|
$version = $matches[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get searched keywords from referrer URL
|
||||||
|
* @param string $referer
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public static function GetKeyword($referer = null) {
|
||||||
|
if ($referer === null) {
|
||||||
|
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($referer)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$engines = [
|
||||||
|
'google' => ['q', 'query'],
|
||||||
|
'bing' => ['q'],
|
||||||
|
'yahoo' => ['p'],
|
||||||
|
'yandex' => ['text'],
|
||||||
|
'baidu' => ['wd', 'word'],
|
||||||
|
'duckduckgo' => ['q'],
|
||||||
|
'ask' => ['q'],
|
||||||
|
'aol' => ['q'],
|
||||||
|
'naver' => ['query'],
|
||||||
|
'ecosia' => ['q'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$parsed_url = parse_url($referer);
|
||||||
|
$host = isset($parsed_url['host']) ? strtolower($parsed_url['host']) : '';
|
||||||
|
$query = isset($parsed_url['query']) ? $parsed_url['query'] : '';
|
||||||
|
|
||||||
|
parse_str($query, $query_params);
|
||||||
|
|
||||||
|
foreach ($engines as $engine => $params) {
|
||||||
|
if (strpos($host, $engine) !== false) {
|
||||||
|
foreach ($params as $param) {
|
||||||
|
if (isset($query_params[$param]) && !empty($query_params[$param])) {
|
||||||
|
return [
|
||||||
|
'engine' => $engine,
|
||||||
|
'keyword' => urldecode($query_params[$param])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @param string $class alternative class
|
||||||
|
// * return vistor os icon
|
||||||
|
// * @uses awesome font
|
||||||
|
// */
|
||||||
|
// static public function GetOSIcon($class = '') {
|
||||||
|
// // get os
|
||||||
|
// $os_int = self::DetectOSI();
|
||||||
|
//
|
||||||
|
// $win = range(1, 16);
|
||||||
|
// $linux = range(17, 19);
|
||||||
|
// $osx = array(20, 21);
|
||||||
|
// $android = array(25);
|
||||||
|
// $searchbot = array(27);
|
||||||
|
// $other = array(0, 22, 23, 24, 26);
|
||||||
|
//
|
||||||
|
// switch (true) {
|
||||||
|
// case in_array($os_int, $win):
|
||||||
|
// $icon = 'windows';
|
||||||
|
// break;
|
||||||
|
// case in_array($os_int, $linux):
|
||||||
|
// $icon = 'linux';
|
||||||
|
// break;
|
||||||
|
// case in_array($os_int, $osx):
|
||||||
|
// $icon = 'apple';
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case in_array($os_int, $android):
|
||||||
|
// $icon = 'android';
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case in_array($os_int, $searchbot):
|
||||||
|
// $icon = 'google';
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// $icon = 'question';
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $result = '<span class="fa fa-' . $icon . ' ' . $class . '" title="'
|
||||||
|
// . self::DetectOS() . '" ></span>';
|
||||||
|
//
|
||||||
|
// return $result;
|
||||||
|
// }
|
||||||
|
// /**
|
||||||
|
// * @param string $class alternative class
|
||||||
|
// * return vistor browser icon
|
||||||
|
// * @uses awesome font
|
||||||
|
// */
|
||||||
|
// static public function GetBrowerIcon($class = '') {
|
||||||
|
// // get os
|
||||||
|
// $bowser = self::DetectBrowser();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// $result = '<span class="fa fa-' . strtolower($bowser) . ' ' . $class . '" title="'
|
||||||
|
// . self::DetectBrowser() . '" ></span>';
|
||||||
|
// return $result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Visitor;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class VisitorController extends Controller
|
||||||
|
{
|
||||||
|
//
|
||||||
|
public function display(Request $request){
|
||||||
|
$visitor = Visitor::where('ip', $request->ip())->orderByDesc('id')->first();
|
||||||
|
if ($visitor != null){
|
||||||
|
$visitor->display = $request->input('display',null);
|
||||||
|
$visitor->save();
|
||||||
|
}
|
||||||
|
return ['OK'=>true];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class VisitorController extends Controller
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Helpers\TVisitor;
|
||||||
|
use App\Models\Visitor;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class VisitorDetector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
|
||||||
|
$visitor = Visitor::where('updated_at','>',date("Y-m-d H:i:s" ,time() - (60*60)))
|
||||||
|
->where('ip', $request->ip())->first();
|
||||||
|
if ($visitor === null) {
|
||||||
|
$visitor = new Visitor();
|
||||||
|
$visitor->ip = $request->ip();
|
||||||
|
$visitor->browser = TVisitor::DetectBrowserI();
|
||||||
|
$visitor->os = TVisitor::DetectOSI();
|
||||||
|
$visitor->version = TVisitor::BrowserVersion();
|
||||||
|
$visitor->keywords = TVisitor::GetKeyword();
|
||||||
|
$visitor->is_mobile = TVisitor::IsMobile();
|
||||||
|
$visitor->save();
|
||||||
|
}else{
|
||||||
|
$visitor->increment('visit');
|
||||||
|
}
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Visitor extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Visitor>
|
||||||
|
*/
|
||||||
|
class VisitorFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
$displays = ['1920x1080','1366x768','1920x1080','1366x768','1280x1024',null, null];
|
||||||
|
$date = $this->faker->dateTimeBetween('-31 days', 'now');
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
'ip' => $this->faker->ipv4(),
|
||||||
|
'visit' => rand(1,rand(2,12)),
|
||||||
|
'browser' => rand(0,5),
|
||||||
|
'os' => rand(0,14),
|
||||||
|
'version' => rand(100,132),
|
||||||
|
'display' => $displays[count($displays)-1],
|
||||||
|
'updated_at' => $date,
|
||||||
|
'created_at' => $date,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('visitors', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->ipAddress('ip');
|
||||||
|
$table->unsignedInteger('visit')->default(1);
|
||||||
|
$table->unsignedInteger('browser')->nullable();
|
||||||
|
$table->unsignedInteger('os')->nullable();
|
||||||
|
$table->string('version')->nullable();
|
||||||
|
$table->string('display')->nullable();
|
||||||
|
$table->string('keywords')->nullable();
|
||||||
|
$table->boolean('is_mobile')->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('visitors');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Visitor;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class VisitorSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Visitor::factory()->count(110)->create();
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 474 KiB |
@ -0,0 +1,49 @@
|
|||||||
|
window.addEventListener('load', function () {
|
||||||
|
const API_COOKIE_NAME = 'last_api_call';
|
||||||
|
const COOKIE_EXPIRY_MINUTES = 59;
|
||||||
|
|
||||||
|
function setCookie(name, value, minutes) {
|
||||||
|
let expires = "";
|
||||||
|
if (minutes) {
|
||||||
|
let date = new Date();
|
||||||
|
date.setTime(date.getTime() + (minutes * 60 * 1000));
|
||||||
|
expires = "; expires=" + date.toUTCString();
|
||||||
|
}
|
||||||
|
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
let nameEQ = name + "=";
|
||||||
|
let ca = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < ca.length; i++) {
|
||||||
|
let c = ca[i];
|
||||||
|
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||||
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canSendData() {
|
||||||
|
let lastCall = getCookie(API_COOKIE_NAME);
|
||||||
|
if (!lastCall) return true;
|
||||||
|
|
||||||
|
let lastCallTime = new Date(parseInt(lastCall));
|
||||||
|
let currentTime = new Date();
|
||||||
|
let timeDiff = (currentTime - lastCallTime) / (1000 * 60); // difference in minutes
|
||||||
|
|
||||||
|
return timeDiff >= COOKIE_EXPIRY_MINUTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canSendData()) {
|
||||||
|
axios.post(document.querySelector('#api-display-url').value, {
|
||||||
|
display: window.screen.availWidth + 'x' + window.screen.availHeight,
|
||||||
|
}).then(function (response) {
|
||||||
|
// If the API call is successful, set the cookie
|
||||||
|
setCookie(API_COOKIE_NAME, new Date().getTime(), COOKIE_EXPIRY_MINUTES);
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.error('Error sending data:', error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Data was sent recently. Skipping this time.');
|
||||||
|
}
|
||||||
|
});
|
@ -1,9 +1,16 @@
|
|||||||
// PLEASE DO NOT EDIT THIS FILE,
|
// PLEASE DO NOT EDIT THIS FILE,
|
||||||
// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom
|
// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom
|
||||||
|
import axios from 'axios';
|
||||||
|
window.axios = axios;
|
||||||
|
|
||||||
|
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
import "./client-custom/assetsNode.js";
|
import "./client-custom/assetsNode.js";
|
||||||
import "./client-custom/confirm.js";
|
import "./client-custom/confirm.js";
|
||||||
|
import "./client-custom/windowLoader.js";
|
||||||
import "../views/segments/preloader/PreloaderCircle/PreloaderCircle.js";
|
import "../views/segments/preloader/PreloaderCircle/PreloaderCircle.js";
|
||||||
import "../views/segments/top/TopSimple/TopSimple.js";
|
import "../views/segments/top/TopSimple/TopSimple.js";
|
||||||
import "../views/segments/slider/SliderSimple/SliderSimple.js";
|
import "../views/segments/slider/SliderSimple/SliderSimple.js";
|
||||||
import "../views/segments/posts/PostsIconSimple/PostsIconSimple.js";
|
import "../views/segments/posts/PostsIconSimple/PostsIconSimple.js";
|
||||||
import "../views/segments/index/GradientTextLink/GradientTextLink.js";
|
import "../views/segments/index/GradientTextLink/GradientTextLink.js";
|
||||||
|
import "../views/segments/category/FavProductWithMeta/FavProductWithMeta.js";
|
||||||
|
import "../views/segments/parallax/ParallaxShort/ParallaxShort.js";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
@yield('custom-foot')
|
@yield('custom-foot')
|
||||||
|
<input type="hidden" id="api-display-url" value="{{route('v1.visitor.display')}}">
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue