mdn-backend / app /Domain /Analytics /AnalyticsIpAnonymizer.php
internationalscholarsprogram's picture
feat(analytics): website analytics pipeline β€” ingestion, rollup, admin query
45dc401
Raw
History Blame Contribute Delete
1.23 kB
<?php
declare(strict_types=1);
namespace App\Domain\Analytics;
/**
* Coarsens an IP address before any persistence.
* Raw IPs are never stored β€” only the anonymised form is passed to the job.
*
* IPv4: zeros the last octet 1.2.3.4 β†’ 1.2.3.0
* IPv6: keeps the first 48 bits 2001:db8::1 β†’ 2001:db8::/48 prefix as string
* Invalid / empty: returns '0.0.0.0'
*/
final class AnalyticsIpAnonymizer
{
public static function coarsen(string $ip): string
{
$ip = trim($ip);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
$parts = explode('.', $ip);
$parts[3] = '0';
return implode('.', $parts);
}
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
// Expand to full 128-bit representation, keep first 48 bits (/48 prefix).
$packed = inet_pton($ip);
if ($packed === false) {
return '0.0.0.0';
}
// Zero bytes 7–15 (keep bytes 0–5, 48 bits)
$zeroed = substr($packed, 0, 6) . str_repeat("\x00", 10);
return inet_ntop($zeroed) . '/48';
}
return '0.0.0.0';
}
}