'LO', 'city' => 'Local' ); } $key = self::CACHE_PREFIX . md5( $ip ); $cached = get_transient( $key ); if ( is_array( $cached ) ) { return $cached; } $response = wp_remote_get( 'http://ip-api.com/json/' . rawurlencode( $ip ) . '?fields=status,country,countryCode,city', array( 'timeout' => 3 ) ); if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { set_transient( $key, array( 'country' => '', 'city' => '' ), HOUR_IN_SECONDS ); return false; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( ! is_array( $body ) || 'success' !== ( $body['status'] ?? '' ) ) { set_transient( $key, array( 'country' => '', 'city' => '' ), HOUR_IN_SECONDS ); return false; } $geo = array( 'country' => substr( (string) ( $body['countryCode'] ?? '' ), 0, 8 ), 'city' => substr( (string) ( $body['city'] ?? '' ), 0, 80 ), ); set_transient( $key, $geo, DAY_IN_SECONDS ); return $geo; } public static function detect_new_country( $user_login, $user ) { if ( ! $user instanceof WP_User ) { $user = get_user_by( 'login', $user_login ); if ( ! $user ) { return; } } $ip = self::client_ip(); if ( ! $ip ) { return; } $geo = self::lookup( $ip ); if ( ! $geo || empty( $geo['country'] ) ) { return; } $known = (array) get_user_meta( $user->ID, self::USER_META_KEY, true ); if ( in_array( $geo['country'], $known, true ) ) { return; } $known[] = $geo['country']; update_user_meta( $user->ID, self::USER_META_KEY, $known ); // Only emit the warning event when this isn't their very first login (no known countries yet). if ( count( $known ) === 1 ) { return; } APWPM_Logger::log( array( 'action_type' => 'login_new_country', 'object_type' => 'user', 'object_id' => $user->ID, 'object_title' => $user->user_login, 'description' => sprintf( /* translators: 1: user, 2: country, 3: city */ __( 'User %1$s signed in from a new country: %2$s (%3$s)', 'activitypilot' ), $user->user_login, $geo['country'], $geo['city'] ?: '?' ), 'severity' => 'warning', 'context' => array( 'country' => $geo['country'], 'city' => $geo['city'] ), 'user_id' => $user->ID, ) ); } protected static function client_ip() { foreach ( array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR' ) as $key ) { if ( empty( $_SERVER[ $key ] ) ) { continue; } $value = sanitize_text_field( wp_unslash( $_SERVER[ $key ] ) ); if ( strpos( $value, ',' ) !== false ) { $value = trim( explode( ',', $value )[0] ); } if ( filter_var( $value, FILTER_VALIDATE_IP ) ) { return $value; } } return ''; } }