Files
exchange-2.0/app/Classes/Modules/Affiliate/Services/TracksAffiliateClick.php
T
Edmond Lang 30ed77f304 Merge branch 'affiliate-program' of https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0 into vapor/production
# Conflicts:
#	resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue
#	routes/api.php
2026-01-26 00:13:10 +08:00

89 lines
2.3 KiB
PHP

<?php
namespace App\Classes\Modules\Affiliate\Services;
use App\Models\Affiliate;
use Illuminate\Support\Facades\Cookie;
class TracksAffiliateClick
{
const COOKIE_NAME = 'affiliate_tracking_code';
const COOKIE_EXPIRY_DAYS = 30; // Default, can be overridden by settings
/**
* Track a click on an affiliate link
*
* @param string $code
* @return Affiliate|null
*/
public function execute(string $code): ?Affiliate
{
// Validate code format and length
if (!$this->isValidCode($code)) {
return null;
}
$affiliate = Affiliate::where('code', $code)
->where('is_active', true)
->first();
if (!$affiliate) {
return null;
}
// Increment clicks count
$affiliate->increment('clicks_count');
// Get binding days from settings
$bindingDays = $this->getBindingDays();
// Store in cookie for later use during registration
// Set secure cookie flags for security
Cookie::queue(
cookie(
self::COOKIE_NAME,
$code,
$bindingDays * 24 * 60, // Convert days to minutes
'/', // path
null, // domain (null = current domain)
config('session.secure', false), // secure (HTTPS only)
true, // httpOnly (prevent JavaScript access)
false, // raw
config('session.same_site', 'lax') // sameSite
)
);
return $affiliate;
}
/**
* Validate affiliate code format
*
* @param string $code
* @return bool
*/
private function isValidCode(string $code): bool
{
// Check length (max 255 chars based on database schema)
if (strlen($code) > 255 || strlen($code) < 1) {
return false;
}
// Only allow alphanumeric characters, hyphens, and underscores
return (bool) preg_match('/^[a-zA-Z0-9_-]+$/', $code);
}
/**
* Get code binding days from settings
*
* @return int
*/
private function getBindingDays(): int
{
$settingsService = new GetsAffiliateSettings();
$settings = $settingsService->execute();
return $settings['code_binding_days'] ?? self::COOKIE_EXPIRY_DAYS;
}
}