Capture real client IPs behind CDN, improve provider fallbacks and negative cache, fix admin credential dependsOn for polling mode, and map country labels to ISO codes for moderation GeoIP blocks.
142 lines
4.4 KiB
PHP
142 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* Comment city / IP geo helpers.
|
|
*
|
|
* Meta: aksrt_comment_addr {country,province,city}
|
|
* Gates: ip_geo_enabled + ip_geo_display has comment + comment_city_s
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!function_exists('aksrt_comment_city_enabled')) :
|
|
function aksrt_comment_city_enabled(): bool {
|
|
if (function_exists('aksrt_ip_geo_display_enabled') && !aksrt_ip_geo_display_enabled('comment')) {
|
|
return false;
|
|
}
|
|
if (!class_exists('\AKSRT\Settings\Settings')) {
|
|
return false;
|
|
}
|
|
$s = \AKSRT\Settings\Settings::get_comment_display_settings();
|
|
return !empty($s['city_s']);
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_comment_city_type')) :
|
|
function aksrt_comment_city_type(): string {
|
|
if (!class_exists('\AKSRT\Settings\Settings')) {
|
|
return function_exists('aksrt_ip_geo_format_key') ? aksrt_ip_geo_format_key() : 'province_city';
|
|
}
|
|
$s = \AKSRT\Settings\Settings::get_comment_display_settings();
|
|
$type = sanitize_key((string) ($s['city_type'] ?? 'province_city'));
|
|
return in_array($type, ['province_city', 'province', 'country_province'], true)
|
|
? $type
|
|
: 'province_city';
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_store_comment_addr')) :
|
|
/**
|
|
* @param int $comment_id Comment ID.
|
|
* @param string|null $ip Optional IP override.
|
|
*/
|
|
function aksrt_store_comment_addr(int $comment_id, ?string $ip = null): void {
|
|
if ($comment_id <= 0 || !aksrt_comment_city_enabled()) {
|
|
return;
|
|
}
|
|
if ($ip === null || $ip === '') {
|
|
$comment = get_comment($comment_id);
|
|
$ip = $comment instanceof WP_Comment ? (string) $comment->comment_author_IP : '';
|
|
}
|
|
$ip = trim((string) $ip);
|
|
|
|
// Private / empty stored IP (CDN edge without proxy headers): resolve live client IP once.
|
|
$needs_live = ($ip === '' || $ip === '0.0.0.0');
|
|
if (!$needs_live && function_exists('filter_var')) {
|
|
$needs_live = !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
|
|
}
|
|
if ($needs_live && function_exists('aksrt_get_client_ip')) {
|
|
$live = trim((string) aksrt_get_client_ip());
|
|
if ($live !== '' && $live !== '0.0.0.0'
|
|
&& filter_var($live, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)
|
|
) {
|
|
$ip = $live;
|
|
}
|
|
}
|
|
|
|
if ($ip === '') {
|
|
return;
|
|
}
|
|
if (function_exists('aksrt_lookup_geo_for_ip')) {
|
|
$addr = aksrt_lookup_geo_for_ip($ip);
|
|
} elseif (class_exists('\AKSRT\Extensions\IPGeo')) {
|
|
$geo = \AKSRT\Extensions\IPGeo::get_instance()->lookup($ip);
|
|
$addr = [
|
|
'country' => (string) ($geo['country'] ?? ''),
|
|
'province' => (string) ($geo['province'] ?? ''),
|
|
'city' => (string) ($geo['city'] ?? ''),
|
|
];
|
|
} else {
|
|
return;
|
|
}
|
|
if ($addr['country'] === '' && $addr['province'] === '' && $addr['city'] === '') {
|
|
return;
|
|
}
|
|
update_comment_meta($comment_id, 'aksrt_comment_addr', $addr);
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_get_comment_addr')) :
|
|
/**
|
|
* @param int|WP_Comment $comment Comment.
|
|
* @return array{country:string,province:string,city:string}
|
|
*/
|
|
function aksrt_get_comment_addr($comment): array {
|
|
$comment_id = $comment instanceof WP_Comment ? (int) $comment->comment_ID : (int) $comment;
|
|
if ($comment_id <= 0) {
|
|
return ['country' => '', 'province' => '', 'city' => ''];
|
|
}
|
|
$raw = get_comment_meta($comment_id, 'aksrt_comment_addr', true);
|
|
if (function_exists('aksrt_normalize_geo_addr')) {
|
|
return aksrt_normalize_geo_addr($raw);
|
|
}
|
|
return is_array($raw) ? $raw : ['country' => '', 'province' => '', 'city' => ''];
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_format_comment_city_label')) :
|
|
/**
|
|
* @param array<string,string> $addr Addr.
|
|
* @param string $type Format.
|
|
*/
|
|
function aksrt_format_comment_city_label(array $addr, string $type = 'province_city'): string {
|
|
if (function_exists('aksrt_format_geo_label')) {
|
|
return aksrt_format_geo_label($addr, $type);
|
|
}
|
|
return '';
|
|
}
|
|
endif;
|
|
|
|
if (!function_exists('aksrt_get_comment_city_badge_html')) :
|
|
function aksrt_get_comment_city_badge_html($comment): string {
|
|
if (!aksrt_comment_city_enabled()) {
|
|
return '';
|
|
}
|
|
if (function_exists('aksrt_get_geo_badge_html')) {
|
|
return aksrt_get_geo_badge_html(
|
|
aksrt_get_comment_addr($comment),
|
|
aksrt_comment_city_type(),
|
|
'badg badg-sm comment-city-badge'
|
|
);
|
|
}
|
|
return '';
|
|
}
|
|
endif;
|
|
|
|
add_action('comment_post', static function ($comment_id): void {
|
|
if (function_exists('aksrt_store_comment_addr')) {
|
|
aksrt_store_comment_addr((int) $comment_id);
|
|
}
|
|
}, 20, 1);
|