File: /var/www/studis.kauko.lt/wp-content/plugins/wp-statistics/includes/class-wp-statistics-referred.php
<?php
namespace WP_STATISTICS;
class Referred
{
/**
* Top Referring Transient name
*
* @var string
*/
public static $top_referring_transient = 'wps_top_referring';
/**
* Referrer Spam List
*
* @var string
*/
public static $referrer_spam_link = 'https://cdn.jsdelivr.net/gh/matomo-org/referrer-spam-list@master/spammers.txt';
/**
* Referred constructor.
*/
public function __construct()
{
# Remove Cache When Delete Visitor Table
add_action('wp_statistics_truncate_table', array($this, 'deleteCacheData'));
}
/**
* Get referer URL
*
* @return string
*/
public static function getRefererURL()
{
if (Helper::is_rest_request() && isset($_REQUEST['referred'])) {
$referred = $_REQUEST['referred'];
/**
* Decode the url if the request type is client-side tracking
*/
if (Option::get('use_cache_plugin')) {
$referred = base64_decode($referred);
}
return sanitize_url(wp_unslash(urldecode($referred)));
}
return (isset($_SERVER['HTTP_REFERER']) ? sanitize_url(wp_unslash($_SERVER['HTTP_REFERER'])) : '');
}
/**
* Return the referrer link for the current user.
*
* @return array|bool|string
*/
public static function get()
{
// Get Default
$referred = self::getRefererURL();
// Sanitize Referer Url
$referred = esc_url_raw(wp_strip_all_tags($referred));
// If Referer is empty, set only ''
if (empty($referred)) {
$referred = '';
}
$referred = Helper::FilterQueryStringUrl($referred, Helper::get_query_params_allow_list());
return apply_filters('wp_statistics_user_referer', $referred);
}
/**
* Get referrer link
*
* @param string $referrer
* @param string $title
* @param bool $is_blank
* @return string | void
*/
public static function get_referrer_link($referrer, $title = '', $is_blank = false)
{
// Sanitize Link
$html_referrer = self::html_sanitize_referrer($referrer);
// Check Url Protocol
if (!Helper::check_url_scheme($html_referrer)) {
$html_referrer = '//' . $html_referrer;
}
$html_referrer = esc_url($html_referrer);
// Parse Url
$base_url = @wp_parse_url($html_referrer);
// Get Page title
$title = (trim($title) == "" ? $html_referrer : $title);
// If referrer is the current site or empty, return empty string
if (empty($base_url['host']) || strpos($referrer, site_url()) !== false) {
return \WP_STATISTICS\Admin_Template::UnknownColumn();
}
// Remove Url prefixes
$host_name = Helper::get_domain_name($base_url['host']);
// Special case for android-app
if ($base_url['host'] === 'android-app' && !empty($base_url['path'])) {
$host_name = $base_url['host'] . ':' . $base_url['path'];
}
// Get Html Link
return "<a class='wps-link-arrow' href='{$html_referrer}' title='{$title}'" . ($is_blank === true ? ' target="_blank"' : '') . "><span >{$host_name}</span></a>";
}
/**
* Sanitizes the referrer
*
* @param $referrer
* @param int $length
* @return string
*/
public static function html_sanitize_referrer($referrer, $length = -1)
{
$referrer = trim($referrer);
if ('data:' == strtolower(substr($referrer, 0, 5))) {
$referrer = 'http://127.0.0.1';
}
if ('javascript:' == strtolower(substr($referrer, 0, 11))) {
$referrer = 'http://127.0.0.1';
}
if ($length > 0) {
$referrer = substr($referrer, 0, $length);
}
return $referrer;
}
/**
* Get Number Referer Domain
*
* @param $url
* @param string $type [list|number]
* @param array $time_rang
* @param null $limit
* @return array
* @throws \Exception
*/
public static function get_referer_from_domain($url, $type = 'number', $time_rang = array(), $limit = null)
{
global $wpdb;
//Get Domain Name
$search_url = Helper::get_domain_name($url);
//Prepare SQL
$time_sql = '';
if (count($time_rang) > 0 and !empty($time_rang)) {
$time_sql = sprintf("AND `last_counter` BETWEEN '%s' AND '%s'", $time_rang[0], $time_rang[1]);
}
$sql = $wpdb->prepare(
"SELECT " . ($type == 'number' ? 'COUNT(*)' : '*') . "
FROM `" . DB::table('visitor') . "`
WHERE `referred` REGEXP \"^[A-Za-z0-9\\.-]+\\.[A-Za-z]{2,}\"
AND referred <> ''
AND (`referred` LIKE %s OR `referred` LIKE %s OR `referred` LIKE %s OR `referred` LIKE %s)
" . $time_sql . "
ORDER BY `" . DB::table('visitor') . "`.`ID` DESC " . ($limit != null ? " LIMIT " . $limit : ""),
'https://www.' . $wpdb->esc_like($search_url) . '%',
'https://' . $wpdb->esc_like($search_url) . '%',
'http://www.' . $wpdb->esc_like($search_url) . '%',
'http://' . $wpdb->esc_like($search_url) . '%'
); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
//Get Count
return ($type == 'number' ? $wpdb->get_var($sql) : Visitor::prepareData($wpdb->get_results($sql))); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Downloads the referrer spam database
*
* @see https://github.com/matomo-org/referrer-spam-blacklist.
* @return string
*/
public static function download_referrer_spam()
{
if (Option::get('referrerspam') == false) {
return '';
}
// Download the file from MaxMind, this places it in a temporary location.
$response = wp_remote_get(self::$referrer_spam_link, array('timeout' => 60));
if (is_wp_error($response)) {
return false;
}
$referrerspamlist = wp_remote_retrieve_body($response);
if (is_wp_error($referrerspamlist)) {
return false;
}
if ($referrerspamlist != '' || Option::get('referrerspamlist') != '') {
Option::update('referrerspamlist', $referrerspamlist);
}
return true;
}
/**
* Get Top Referring Site
*
* @param int $number
* @return array
* @throws \Exception
*/
public static function getTop($number = 10)
{
global $wpdb;
//Get Top Referring
if (false === ($get_urls = get_transient(self::$top_referring_transient))) {
$sql = $wpdb->prepare("ORDER BY `number` DESC LIMIT %d", $number);
$result = $wpdb->get_results(self::generateReferSql($sql, '')); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
foreach ($result as $items) {
$get_urls[$items->domain] = self::get_referer_from_domain($items->domain);
}
// Put the results in a transient. Expire after 12 hours.
set_transient(self::$top_referring_transient, $get_urls, 20 * HOUR_IN_SECONDS);
}
// Return Data
return self::PrepareReferData($get_urls);
}
/**
* Prepare Refer Data
*
* @param $get_urls
* @return array
* @throws \Exception
*/
public static function PrepareReferData($referrals)
{
if (empty($referrals)) return [];
$list = [];
foreach ($referrals as $domain => $number) {
$referrerUrl = Referred::html_sanitize_referrer($domain);
$list[] = [
'domain' => $domain,
'page_link' => Menus::admin_url('referrers', ['referrer' => $referrerUrl]),
'number' => number_format_i18n($number)
];
}
// Return Data
return $list;
}
/**
* Get Referred Site List
*
* @param array $args
* @return mixed
*/
public static function getList($args = array())
{
global $wpdb;
// Check Custom Date
$where = '';
if (isset($args['from']) and isset($args['to'])) {
$where = "AND `last_counter` BETWEEN '" . $args['from'] . "' AND '" . $args['to'] . "' ";
}
// Check Min Number
$having = '';
if (isset($args['min'])) {
$having = "HAVING `number` >" . $args['min'];
}
// Check Limit
$limit = '';
if (isset($args['limit'])) {
$limit = "LIMIT " . $args['limit'];
}
// Return List
return $wpdb->get_results(self::generateReferSql($having . " ORDER BY `number` DESC " . $limit, $where)); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Generate Basic SQL Refer List
*
* @param string $where
* @param string $extra
* @return string
*/
public static function generateReferSql($extra = '', $where = '')
{
// Check Protocol Of domain
$domain_name = rtrim(preg_replace('/^https?:\/\//', '', get_site_url()), " / ");
foreach (array("http", "https", "ftp") as $protocol) {
foreach (array('', 'www.') as $w3) {
$where .= " AND `referred` NOT LIKE '{$protocol}://{$w3}{$domain_name}%' ";
}
}
// Return SQL
return "SELECT referred AS `domain`, count(referred) AS `number`
FROM " . DB::table('visitor') . "
WHERE `referred` REGEXP \"^[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}\"
AND referred <> '' " . $where . "
GROUP BY `domain` " . $extra;
}
/**
* Remove Complete Cache Data
* @param $table_name
*/
public function deleteCacheData($table_name)
{
if ($table_name == "visitor") {
delete_transient(self::$top_referring_transient);
}
}
}
new Referred();