use WP_STATISTICS\Country;
use WP_STATISTICS\IP;
use WP_STATISTICS\Pages;
use WP_Statistics\Service\Analytics\DeviceDetection\DeviceHelper;
use WP_Statistics\Service\Analytics\DeviceDetection\UserAgent;
use WP_Statistics\Service\Geolocation\GeolocationFactory;
use WP_Statistics\Service\Admin\PrivacyAudit\Faqs\RequireConsent;
use WP_STATISTICS\TimeZone;
use WP_STATISTICS\User;
/**
* Get Current User IP
*/
function wp_statistics_get_user_ip()
{
return IP::getIP();
}
/**
* Get Current User Data
*
* @throws Exception
*/
function wp_statistics_get_current_user_data()
{
// Get Current User country and City
$data = wp_statistics_get_user_location();
// Get Current User IP
$data['ip'] = wp_statistics_get_user_ip();
// Get User Agent contain Browser and Platform
$data['agent'] = UserAgent::getUserAgent();
// Get User info if Registered in WordPress
if (User::is_login()) {
$data['user'] = User::get();
}
// Return
return $data;
}
/**
* Get User Statistics Data By IP
*
* @param bool $ip
* @return array
* @throws Exception
*/
function wp_statistics_get_user_location($ip = false)
{
$ip = ($ip === false ? wp_statistics_get_user_ip() : $ip);
$data = array(
'country' => '',
'city' => '',
);
// Get the location
$location = GeolocationFactory::getLocation($ip);
$country = $location['country'];
$data['country'] = array(
'code' => $location,
'name' => Country::getName($country),
'flag' => Country::flag($country)
);
// Get User City
$data['city'] = $location['city'];
return $data;
}
/**
* Get Current Users online
*
* @param array $options
* @return mixed
*/
function wp_statistics_useronline($options = array())
{
global $wpdb;
//Check Parameter
$defaults = array(
/**
* Type Of Page in WordPress
* @See Frontend\get_page_type
*
* -- Acceptable values --
*
* post -> WordPress Post single page From All of public post Type
* page -> WordPress page single page
* product -> WooCommerce product single page
* home -> Home Page website
* category -> WordPress Category Page
* post_tag -> WordPress Post Tags Page
* tax -> WordPress Term Page for all Taxonomies
* author -> WordPress Users page
* 404 -> 404 Not Found Page
* archive -> WordPress Archive Page
* all -> All Site Page
*
*/
'type' => 'all',
/**
* WordPress Query object ID
* @example array('type' => 'product', 'ID' => 5)
*/
'ID' => 0,
/**
* Get number of logged users or all users
*
* -- Acceptable values --
* false -> Get Number of all users
* true -> Get Number of all logged users in wordpress
*/
'logged_users' => false,
/**
* Get number User From Custom Country
*
* -- Acceptable values --
* ISO Country Code -> For Get List @See \wp-statistics\includes\functions\country-code.php
*
*/
'location' => 'all',
/**
* Search Filter by User agent name
* e.g : Firefox , Chrome , Safari , Unknown ..
* @see wp_statistics_get_browser_list()
*
*/
'agent' => 'all',
/**
* Search filter by User Operating System name
* e.g : Windows, iPad, Macintosh, Unknown, ..
*
*/
'platform' => 'all',
/**
* Return Of Data
*
* -- Acceptable values --
* count -> Get number of user online
* all -> Get List of User Online data
*/
'return' => 'count'
);
// Parse incoming $args into an array and merge it with $defaults
$arg = wp_parse_args($options, $defaults);
//Basic SQL
$type_request = ($arg['return'] == "all" ? '*' : 'COUNT(*)');
$sql = "SELECT {$type_request} FROM " . WP_STATISTICS\DB::table('useronline') . " as useronline JOIN " . WP_STATISTICS\DB::table('visitor') . " as visitor ON useronline.visitor_id = visitor.ID";
//Check Where Condition
$where = [];
//Check Type of Page
if ($arg['type'] != "all") {
$where[] = "`visitor`.`last_page` = " . $arg['ID'];
}
//Check Custom user
if ($arg['logged_users'] === true) {
$where[] = "`user_id` > 0";
}
//Check Location
if ($arg['location'] != "all") {
$ISOCountryCode = Country::getList();
if (array_key_exists($arg['location'], $ISOCountryCode)) {
$where[] = "`location` = '" . $arg['location'] . "'";
}
}
//Check User Agent
if ($arg['agent'] != "all") {
$where[] = "`agent` = '" . $arg['agent'] . "'";
}
//Check User Platform
if ($arg['platform'] != "all") {
$where[] = "`platform` = '" . $arg['platform'] . "'";
}
//Push Conditions to SQL
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
//Return Number od user Online
return ($arg['return'] == "count" ? $wpdb->get_var($sql) : $wpdb->get_results($sql)); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* This function get the visit statistics for a given time frame
*
* @param $time
* @param null $daily
* @return int
*/
function wp_statistics_visit($time, $daily = null)
{
global $wpdb;
//Date Column Name in visits table
$table_name = WP_STATISTICS\DB::table('visit');
$date_column = 'last_counter';
//Prepare Selector Sql
$selector = 'SUM(visit)';
if ($daily == true) {
$selector = '*';
}
//Generate Base Sql
$sql = "SELECT " . $selector . " FROM `" . $table_name . "` ";
//Create Sum Views variable
$sum = 0;
//Check if daily Report
if ($daily === true) {
// Check Sanitize Datetime
if (TimeZone::isValidDate($time)) {
$d = $time;
} else {
$d = TimeZone::getCurrentDate('Y-m-d', $time);
}
$result = $wpdb->get_row($sql . " WHERE `$date_column` = '" . $d . "'"); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
if (null !== $result) {
$sum = $result->visit;
}
} else {
//Generate MySql Time Conditions
if (is_array($time) && array_key_exists('start', $time) && array_key_exists('end', $time)) {
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, '', $time);
if (!empty($mysql_time_sql)) {
$sql = $sql . ' WHERE ' . $mysql_time_sql;
}
} else {
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, $time);
if (!empty($mysql_time_sql)) {
$sql = $sql . ' WHERE ' . $mysql_time_sql;
}
}
//Request To database
$result = $wpdb->get_var($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
//Custom Action
if ($time == "total") {
$result += WP_STATISTICS\Historical::get('visits');
}
$sum = $result;
}
return !is_numeric($sum) ? 0 : $sum;
}
/**
* This function gets the visitor statistics for a given time frame.
*
* @param $time
* @param null $daily
* @param bool $count_only
* @param array $options
* @return int|null|string
*/
function wp_statistics_visitor($time, $daily = null, $count_only = false, $options = array())
{
global $wpdb;
//Check Parameter
$defaults = array(
/**
* Type Of Page in WordPress
* @See Frontend\get_page_type
*
* -- Acceptable values --
*
* post -> WordPress Post single page From All of public post Type
* page -> WordPress page single page
* product -> WooCommerce product single page
* home -> Home Page website
* category -> WordPress Category Page
* post_tag -> WordPress Post Tags Page
* tax -> WordPress Term Page for all Taxonomies
* author -> WordPress Users page
* 404 -> 404 Not Found Page
* archive -> WordPress Archive Page
* all -> All Site Page
*
*/
'type' => 'all',
/**
* WordPress Query object ID
* @example array('type' => 'product', 'ID' => 5)
*/
'ID' => 0,
/**
* Get number User From Custom Country
*
* -- Acceptable values --
* ISO Country Code -> For Get List @See \wp-statistics\includes\functions\country-code.php
*
*/
'location' => 'all',
/**
* Search Filter by User agent name
* e.g : Firefox , Chrome , Safari , Unknown ..
* @see wp_statistics_get_browser_list()
*
*/
'agent' => 'all',
/**
* Search filter by User Operating System name
* e.g : Windows, iPad, Macintosh, Unknown, ..
*
*/
'platform' => 'all'
);
// Parse incoming $args into an array and merge it with $defaults
$arg = wp_parse_args($options, $defaults);
//Create History Visitors variable
$history = 0;
//Prepare Selector Sql
$date_column = 'last_counter';
$selector = '*';
if ($count_only == true) {
$selector = 'count(last_counter)';
}
//Generate Base Sql
if ($arg['type'] != "all" and WP_STATISTICS\Option::get('visitors_log') == true) {
$sql = "SELECT {$selector} FROM `" . WP_STATISTICS\DB::table('visitor') . "` INNER JOIN `" . WP_STATISTICS\DB::table("visitor_relationships") . "` ON `" . WP_STATISTICS\DB::table("visitor_relationships") . "`.`visitor_id` = `" . WP_STATISTICS\DB::table('visitor') . "`.`ID` INNER JOIN `" . WP_STATISTICS\DB::table('pages') . "` ON `" . WP_STATISTICS\DB::table('pages') . "`.`page_id` = `" . WP_STATISTICS\DB::table("visitor_relationships") . "` . `page_id`";
} else {
$sql = "SELECT {$selector} FROM `" . WP_STATISTICS\DB::table('visitor') . "`";
}
//Check Where Condition
$where = [];
//Check Type of Page
if ($arg['type'] != "all" and WP_STATISTICS\Option::get('visitors_log') == true) {
$where[] = "`" . WP_STATISTICS\DB::table('pages') . "`.`type`='" . $arg['type'] . "' AND `" . WP_STATISTICS\DB::table('pages') . "`.`page_id` = " . $arg['ID'];
}
//Check Location
if ($arg['location'] != "all") {
$ISOCountryCode = Country::getList();
if (array_key_exists($arg['location'], $ISOCountryCode)) {
$where[] = "`" . WP_STATISTICS\DB::table('visitor') . "`.`location` = '" . $arg['location'] . "'";
}
}
//Check User Agent
if ($arg['agent'] != "all") {
$where[] = "`" . WP_STATISTICS\DB::table('visitor') . "`.`agent` = '" . $arg['agent'] . "'";
}
//Check User Platform
if ($arg['platform'] != "all") {
$where[] = "`" . WP_STATISTICS\DB::table('visitor') . "`.`platform` = '" . $arg['platform'] . "'";
}
//Check Date Time report
if ($daily == true) {
// Check Sanitize Datetime
if (TimeZone::isValidDate($time)) {
$d = $time;
} else {
$d = TimeZone::getCurrentDate('Y-m-d', $time);
}
//Get Only Current Day Visitors
$where[] = "`" . WP_STATISTICS\DB::table('visitor') . "`.`last_counter` = '" . $d . "'";
} else {
//Generate MySql Time Conditions
if (is_array($time) && array_key_exists('start', $time) && array_key_exists('end', $time)) {
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, '', $time);
if (!empty($mysql_time_sql)) {
$sql = $sql . ' WHERE ' . $mysql_time_sql;
}
} else {
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, $time);
if (!empty($mysql_time_sql)) {
$where[] = $mysql_time_sql;
}
}
}
//Push Conditions to SQL
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
//Custom Action
if ($time == "total" and $arg['type'] == "all") {
$history = WP_STATISTICS\Historical::get('visitors');
}
// Execute the SQL call, if we're only counting we can use get_var(), otherwise we use query().
if ($count_only == true) {
$sum = $wpdb->get_var($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$sum += $history;
} else {
$sum = $wpdb->query($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
return $sum;
}
/**
* This function returns the statistics for a given page.
*
* @param $time
* @param string $page_uri
* @param int $id
* @param null $rangestartdate
* @param null $rangeenddate
* @param bool $type
* @return int|null|string
*
* @todo Replace all instances of this function with `ViewsModel->countViews()`.
*/
function wp_statistics_pages($time, $page_uri = '', $id = -1, $rangestartdate = null, $rangeenddate = null, $type = false)
{
global $wpdb;
//Date Column Name in visits table
$table_name = WP_STATISTICS\DB::table('pages');
$date_column = 'date';
// History Vars
$history = 0;
$history_key = null;
$history_id = null;
//Check Where Condition
$where = [];
//Check Query By Page ID or Page Url
if ($type) {
$query = $wpdb->prepare("`type` = %s", $type);
if ($id != -1) {
$query .= $wpdb->prepare(" AND `id` = %d", $id);
$history_key = 'page';
$history_id = absint($id);
}
if ($page_uri != '') {
$page_uri_sql = esc_sql($page_uri);
$query .= $wpdb->prepare(" AND `URI` = %s", $page_uri_sql);
$history_key = 'uri';
$history_id = $page_uri;
}
$where[] = apply_filters('wp_statistics_pages_where_type_query', $query, $id, $type);
} else {
// If no page URI has been passed in, get the current page URI.
if ($page_uri == '') {
$page_uri = Pages::get_page_uri();
}
$page_uri_sql = esc_sql($page_uri);
// If a page/post ID has been passed, use it to select the rows, otherwise use the URI.
if ($id != -1) {
$where[] = "`id`= " . absint($id);
$history_key = 'page';
$history_id = absint($id);
} else {
$where[] = "`URI` = '{$page_uri_sql}'";
$history_key = 'uri';
$history_id = $page_uri;
}
}
//Custom Action
if ($time == "total") {
if ($history_key && $history_id) {
$history = WP_STATISTICS\Historical::get($history_key, $history_id);
}
}
//Prepare Time
$time_array = array();
if (is_numeric($time) || TimeZone::isValidDate($time)) {
$time_array['is_day'] = true;
}
if (!is_null($rangestartdate) and !is_null($rangeenddate)) {
$time_array = array('start' => $rangestartdate, 'end' => $rangeenddate);
}
//Check MySql Time Conditions
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, $time, $time_array);
if (!empty($mysql_time_sql)) {
$where[] = $mysql_time_sql;
}
//Generate Base Sql
$sql = "SELECT SUM(count) FROM {$table_name}";
//Push Conditions to SQL
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
//Request Get data
$sum = $wpdb->get_var($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$sum += $history;
//Return Number Statistic
return ($sum == '' ? 0 : $sum);
}
/**
* Get top Pages between Time
*
* @param null $rangestartdate
* @param null $rangeenddate
* @param null $limit
* @param null $post_type
* @return array
*/
function wp_statistics_get_top_pages($rangestartdate = null, $rangeenddate = null, $limit = null, $post_type = null)
{
global $wpdb;
$spliceLimit = ($limit != null ? $limit : 5);
$limit = null;
// Get every unique URI from the pages database.
if ($rangestartdate != null && $rangeenddate != null) {
$whereType = ($post_type != null ? $wpdb->prepare(" AND `type`=%s", $post_type) : '');
$result = $wpdb->get_results(
$wpdb->prepare("SELECT `uri`,`id`,`type` FROM " . \WP_STATISTICS\DB::table('pages') . " WHERE `date` BETWEEN %s AND %s {$whereType} GROUP BY `id`" . ($limit != null ? ' LIMIT ' . $limit : ''), $rangestartdate, $rangeenddate), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
ARRAY_N);
} else {
$limitQuery = '';
if ($limit) {
$limitQuery = $wpdb->prepare(" LIMIT %d", $limit);
}
$whereType = ($post_type != null ? $wpdb->prepare(" WHERE `type`=%s", $post_type) : '');
$result = $wpdb->get_results("SELECT `uri`, `id`, `type` FROM " . \WP_STATISTICS\DB::table('pages') . " {$whereType} GROUP BY `id` {$limitQuery}", ARRAY_N); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
$total = 0;
$uris = array();
// Now get the total page visit count for each unique URI.
foreach ($result as $out) {
//Prepare item
list($url, $page_id, $page_type) = $out;
// Check if item is of specific post type (string or part of an array) or if post type is set to null
if (is_null($post_type) || $page_type == $post_type || (is_array($post_type) && in_array($page_type, $post_type))) {
// Increment the total number of results.
$total++;
//Get Page Title
$page_info = Pages::get_page_info($page_id, $page_type);
$title = mb_substr($page_info['title'], 0, 200, "utf-8");
$page_url = $page_info['link'];
// Check age Title if page id or type not exist
if ($page_info['link'] == "") {
$page_url = path_join(get_site_url(), $url);
$id = WP_STATISTICS\Pages::uri_to_id($out[0]);
$post = get_post($id);
if (is_object($post)) {
$title = esc_html($post->post_title);
} else {
if ($out[0] == '/') {
$title = get_bloginfo();
} else {
$title = '';
}
}
}
//Check Title is empty
if (empty($title)) {
$title = '-';
}
// Add the current post to the array.
if ($rangestartdate != null && $rangeenddate != null) {
$uris[] = array(
urldecode_deep($out[0]),
wp_statistics_pages('range', $out[0], -1, $rangestartdate, $rangeenddate, $post_type),
$page_id,
$title,
$page_url,
);
} else {
$uris[] = array(
urldecode_deep($out[0]),
wp_statistics_pages('total', $out[0], -1, $rangestartdate, $rangeenddate, $post_type),
$page_id,
$title,
$page_url
);
}
}
}
// If we have more than one result, let's sort them using usort.
if (count($uris) > 1) {
usort($uris, array('\WP_STATISTICS\Helper', 'compare_uri_hits_int'));
}
array_splice($uris, $spliceLimit);
return array($spliceLimit, $uris);
// return array($total, $uris);
}
/**
* Returns all unique user agents in the database.
*
* @param null $rangestartdate
* @param null $rangeenddate
* @return array
*/
function wp_statistics_ua_list($rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null && $rangeenddate != null) {
if ($rangeenddate == 'CURDATE()') {
$result = $wpdb->get_results(
$wpdb->prepare("SELECT DISTINCT agent FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `last_counter` BETWEEN %s AND CURDATE()", $rangestartdate),
ARRAY_N);
} else {
$result = $wpdb->get_results(
$wpdb->prepare("SELECT DISTINCT agent FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `last_counter` BETWEEN %s AND %s", $rangestartdate, $rangeenddate),
ARRAY_N);
}
} else {
$result = $wpdb->get_results(
"SELECT DISTINCT agent FROM `" . \WP_STATISTICS\DB::table('visitor') . "` ",
ARRAY_N);
}
$Browsers = array();
$default_browser = DeviceHelper::getBrowserList();
foreach ($result as $out) {
//Check Browser is defined in wp-statistics
if (array_key_exists(strtolower($out[0]), $default_browser)) {
$Browsers[] = esc_html($out[0]);
}
}
return $Browsers;
}
/**
* Count User By User Agent
*
* @param $agent
* @param null $rangestartdate
* @param null $rangeenddate
* @return mixed
*/
function wp_statistics_useragent($agent, $rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null || $rangeenddate != null) {
if ($rangeenddate == null) {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(*) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `agent` = %s AND `last_counter` = %s", $agent, $rangestartdate)
);
} else {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(*) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `agent` = %s AND `last_counter` BETWEEN %s AND %s", $agent, $rangestartdate, $rangeenddate)
);
}
} else {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(*) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `agent` = %s", $agent)
);
}
return $result;
}
/**
* Returns all unique platform types from the database.
*
* @param null $rangestartdate
* @param null $rangeenddate
* @return array
*/
function wp_statistics_platform_list($rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null && $rangeenddate != null) {
$result = $wpdb->get_results(
$wpdb->prepare("SELECT DISTINCT platform FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `last_counter` BETWEEN %s AND %s", $rangestartdate, $rangeenddate),
ARRAY_N);
} else {
$result = $wpdb->get_results(
"SELECT DISTINCT platform FROM `" . \WP_STATISTICS\DB::table('visitor') . "` ",
ARRAY_N);
}
$Platforms = array();
foreach ($result as $out) {
$Platforms[] = esc_html($out[0]);
}
return $Platforms;
}
/**
* Returns the count of a given platform in the database.
*
* @param $platform
* @param null $rangestartdate
* @param null $rangeenddate
* @return mixed
*/
function wp_statistics_platform($platform, $rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null && $rangeenddate != null) {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(platform) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `platform` = %s AND `last_counter` BETWEEN %s AND %s", $platform, $rangestartdate, $rangeenddate)
);
} else {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(platform) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE `platform` = %s", $platform)
);
}
return $result;
}
/**
* Returns all unique versions for a given agent from the database.
*
* @param $agent
* @param null $rangestartdate
* @param null $rangeenddate
* @return array
*/
function wp_statistics_agent_version_list($agent, $rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null && $rangeenddate != null) {
$result = $wpdb->get_results(
$wpdb->prepare("SELECT DISTINCT `version` FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE agent = %s AND `last_counter` BETWEEN %s AND %s", $agent, $rangestartdate, $rangeenddate),
ARRAY_N);
} else {
$result = $wpdb->get_results(
$wpdb->prepare("SELECT DISTINCT `version` FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE agent = %s", $agent),
ARRAY_N);
}
$Versions = array();
foreach ($result as $out) {
$Versions[] = $out[0];
}
return $Versions;
}
/**
* Returns the statistics for a given agent/version pair from the database.
*
* @param $agent
* @param $version
* @param null $rangestartdate
* @param null $rangeenddate
* @return mixed
*/
function wp_statistics_agent_version($agent, $version, $rangestartdate = null, $rangeenddate = null)
{
global $wpdb;
if ($rangestartdate != null && $rangeenddate != null) {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(version) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE agent = %s AND version = %s AND `last_counter` BETWEEN %s AND %s", $agent, $version, $rangestartdate, $rangeenddate)
);
} else {
$result = $wpdb->get_var(
$wpdb->prepare("SELECT COUNT(version) FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE agent = %s AND version = %s", $agent, $version)
);
}
return $result;
}
/**
* Return the SQL WHERE clause for getting the search engine.
*
* @param string $search_engine
* @return bool|string
*/
function wp_statistics_searchengine_query($search_engine = 'all')
{
global $wpdb;
$search_query = '';
// Are we getting results for all search engines or a specific one?
if (strtolower($search_engine) == 'all') {
$search_query .= "`source_channel` in ('search')";
} else {
// Are we getting results for all search engines or a specific one?
$search_query .= $wpdb->prepare("`source_name` = %s", $search_engine);
}
return $search_query;
}
/**
* Get Search engine Statistics
*
* @param string $search_engine
* @param string $time
* @param string $search_by [query / name]
* @param array $range
* @return mixed
*/
function wp_statistics_get_search_engine_query($search_engine = 'all', $time = 'total', $search_by = 'query', $range = [])
{
global $wpdb;
//Prepare Table Name
$table_name = \WP_STATISTICS\DB::table('visitor');
//Date Column table
$date_column = 'last_counter';
// Get a complete list of search engines
if ($search_by == "query") {
$search_query = wp_statistics_searchengine_query($search_engine);
}
//Generate Base Sql
$sql = "SELECT COUNT(ID) FROM {$table_name} WHERE ({$search_query})";
// Check Sanitize Datetime
if (TimeZone::isValidDate($time)) {
if (empty($range)) $range = ['is_day' => true];
} else {
if (empty($range)) $range = ['current_date' => true];
}
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions($date_column, $time, $range);
//Generate MySql Time Conditions
if (!empty($mysql_time_sql)) {
$sql = $sql . ' AND (' . $mysql_time_sql . ')';
}
//Request Data
return $wpdb->get_var($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* This function will return the statistics for a given search engine.
*
* @param string $search_engine
* @param string $time
* @param array $range
* @return mixed
*/
function wp_statistics_searchengine($search_engine = 'all', $time = 'total', $range = [])
{
return wp_statistics_get_search_engine_query($search_engine, $time, $search_by = 'query', $range);
}
/**
* Return Refer List
*
* @param null $time
* @param array $range
* @return int
*/
function wp_statistics_referrer($time = null, $range = [])
{
global $wpdb;
$sql = "SELECT `referred` FROM `" . \WP_STATISTICS\DB::table('visitor') . "` WHERE referred <> ''";
// Check Sanitize Datetime
if (TimeZone::isValidDate($time)) {
if (empty($range)) $range = ['is_day' => true];
} else {
if (empty($range)) $range = ['current_date' => true];
}
$mysql_time_sql = WP_STATISTICS\Helper::mysql_time_conditions('last_counter', $time, $range);
//Generate MySql Time Conditions
if (!empty($mysql_time_sql)) {
$sql = $sql . ' AND (' . $mysql_time_sql . ')';
}
$result = $wpdb->get_results($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$urls = array();
foreach ($result as $item) {
$url = wp_parse_url($item->referred);
if (empty($url['host']) || stripos(get_bloginfo('url'), $url['host']) !== false) {
continue;
}
$urls[] = $url['scheme'] . '://' . $url['host'];
}
$get_urls = array_count_values($urls);
return count($get_urls);
}
/**
* Checks if consent is required for collecting user statistics.
*
* This function evaluates several conditions that determine whether consent
* is needed to collect and store user data for statistics purposes. If any
* of the conditions are not met, it indicates that consent is required.
*
* @return bool Returns true if consent is required, false otherwise.
* @since 14.10.1
*/
function wp_statistics_needs_consent()
{
// Get the current status of the consent requirement
$status = RequireConsent::getStatus();
// Check if consent is required
if ($status == 'warning') {
return true; // Consent is required
}
// Return false if consent is not required
return false;
}
阿冈昆公园两日行程的公路之旅:Kiosk、Brent 和 Achray 露营地 ⋆ 晒鱼
Skip to content
作者:Cody – Algonquin & Beyond
原文链接在底部
========================
简易导航 背景 第一天 – 驾车前往 Kiosk 营地和 Brent 营地 第二天 – 驾车前往 Achray 营地 后续 营地信息及营地照片
背景 我于2023年底为我的网站启动了“已开发露营地”项目。该项目的目标是什么?走访并记录阿冈昆公园内每个营地的每一个营地。公园内有1300多个营地,分布在12个已开发营地中。大多数营地都位于60号公路沿线,只有三个位于公园的边缘。这三个营地——Kiosk、Brent和Achray——是我需要记录的最后几个营地。
Kiosk营地位于公园的最北端。Brent营地几乎同样位于公园的北边,略偏东。而Achray营地则位于公园的最东端。鉴于阿冈昆公园的土地面积巨大(超过7600平方公里!),这三个营地彼此相距甚远,而且离我住的地方也很远。但我想完成这个项目,这意味着一趟公路旅行是必要的。
我的计划是一大早就出发,先开车去Kiosk露营地。光是开车这一趟就需要大约4个小时,然后我预计在Kiosk的工作大约需要2个小时。然后我会开车1.5个小时到Brent,再花2个小时记录Brent。之后我会再开1.5个小时回到我预订的民宿Top of Algonquin。由于我原路返回,所以这家民宿会占用更多时间,但相比我在网上看到的其他住宿,我最喜欢Top of Algonquin的住宿。第二天,我会开车3个小时到Achray,花大约4个小时记录露营地,最后再开6个小时的车回家。
这将是一个充满挑战的两日行程,需要大量的步行和驾驶。我知道 Elo 可以忍受步行,但我希望她可以忍受所有的驾驶!
第一天 — 开车前往 Kiosk 营地和 Brent 营地 我早上 5:30 就上路了,希望能在 9:30 到达 Kiosk 营地。11 号公路的最后一段路段紧急封闭。显然是一辆卡车翻了。在弯路和死胡同里堵了 20 分钟后,我终于找到一个人给我指了个方向。我折返到 Powassan,然后一路绕道前往 Kiosk。至少,正是在绕道上,我第一次看到了野生动物!路中间有三只鹿,但它们在我拍到好照片之前就跳进了灌木丛。
从 17 号公路通往 Kiosk 营地的 630 号公路路况良好。大部分路段平坦,几乎没有松散的碎石,直到营地附近的最后一公里,路面才开始变得比较碎石。路上没有太多坑洼或障碍物需要担心。转入 630 号高速公路后不久,手机信号就中断了,到达露营地后仍然无法使用。
距离营地约20公里的布伦特路没有手机信号。我就是在这里看到一个狩猎队的。我完全忘了现在是狩猎季节,但布伦特营地和附近的其他地方都贴着“禁止狩猎”的标志。
我以前从未去过布伦特营地,虽然我迫不及待地想探索这里,但首先我需要在车里小睡一会儿。我从营地西端出发,按从小到大的顺序参观了营地。参观完前23个营地以及一些偏远地区的跳水点后,我开车经过了历史悠久的城镇,把车停在营地东端,准备参观最后几个营地。护林员小屋锁着,所以我没能进去,但我可以绕着营地走了一圈,偷偷地透过窗户拍了几张营地内部的照片。
我非常喜欢布伦特露营地。这座历史悠久的小镇遗址就坐落在露营地的中心,是一段引人入胜的历史。大多数露营地都很宽敞,私密性很好,很多露营地甚至还提供水源。大多数露营地都会有一些相邻的营地,但这些营地与露营地的其他部分保持着私密性。虽然仍然有可能遇到吵闹的邻居,但作为一个整体的露营地,它比60号公路沿线的任何露营地都更加隐蔽和私密。
我花了两个小时记录布伦特,下午4点结束,当时天空还有些许光线。第一次尝试沿着碎石路行驶时,我吸取了教训,所以在出发时开得更慢、更谨慎。当我回到17号公路时,阳光很快就消失了。下午5点45分,我到达了阿冈昆山顶,在一片占地68英亩的广阔土地上发现了一栋漂亮的房子。我的住处位于房子的地下室,配备了宽敞的起居区、一张舒适的大床和一间私人浴室。
Top of Algonquin 是一处共享住宿,房东住在楼上。不过他们一次只接受一位预订,这营造了一种更加私密的氛围。它感觉不像传统的住宿,因为,嗯,它确实不是。你是被邀请到别人家做客,从你到达的那一刻起,你就感觉像是在朋友家过夜,而不是付费住宿。地下室有一个单独的入口,但我是从主层进入的。房东 Rick 和 Colleen 非常热情好客。他们养了三只狗,其中一只和 Elo 成了最好的朋友。我以为 Elo 在经历了漫长的一天开车和散步之后会筋疲力尽,但我不应该怀疑她……她是一只澳大利亚牧牛犬,当然,她也找到了精力来和一只当地的小狗一起玩 Zoomies!
安顿下来后,我在楼上和 Rick 聊天、弹吉他。晚上8点,我回到地下室,准备安顿下来。我早上5点就醒了,开了8个小时的车,走了超过17000步。谢天谢地,大床很舒服!
第二天 — 开车前往阿赫雷露营地 阿冈昆之巅(Top of Algonquin)早上提供早餐,但我今天行程非常漫长,想趁还没来得及胃口大开就上路。凌晨五点半刚过,我出发时,里克和科琳都醒了。我开得很慢,很小心,因为我知道野生动物随时都可能跳到我的车前。我本来希望能看到野生动物,因为我喜欢观察它们,但为了安全起见,我庆幸自己最终什么也没看到。
从阿冈昆之巅到阿赫雷露营地的整个行程大约花了三个小时。离开17号公路后,沿着巴伦峡谷路行驶了大约50公里,路况非常好,只有很少的松散碎石。行驶过程中,手机信号断了一会儿。经过沙湖门办公室时,信号短暂地重新出现,然后很快就消失了。由于没有手机信号,我强烈建议您事先将露营地的信息添加到您的GPS中。从巴伦峡谷路 (Barron Canyon Road) 到阿克雷路 (Achray Road) 有一个转弯,千万不要错过。我还想提醒大家,在这段路程中最好不要使用 GPS,因为谷歌地图会试图引导你穿过一些非官方的偏僻小路,这些小路不对公众开放。我建议在巴伦峡谷路起点附近的两家户外用品店 Algonquin Portage 或 Algonquin Bound 稍作停留,以确保 GPS 能带你走正确的路。
淡季时,通往阿赫雷露营地的道路会设门禁,距离营地约1.5公里。那里有一小块区域可以停放几辆车。从门禁区到营地,一路下坡,大约需要10到15分钟。在Kiosk和Brent露营地完全被我占据后,我到达阿赫雷露营地时,惊讶地发现那里有几位公园工作人员。
我早上9点到达,开始在营地里忙碌,包括9个偏远地区的跳水营地。几个小时后,我稍事休息,拍摄了在主办公楼附近跑来跑去的蓝鸦和松鼠。我的短暂休息比预期的要长,但这是有原因的。我和公园的一位工作人员拉里聊了聊,他已经在公园工作了40年!这是我第一次来到阿冈昆公园的最东端,所以和一位对这里如此了解的人交谈感觉很棒。我们聊了大约30分钟,然后我继续工作。
在我参观的三个营地中,阿赫雷营地是我最喜欢的。那里的营地环境相当隐蔽,而且大多数营地都有水源。许多营地也各具特色,无论是海岸线、火坑周围的岩石,还是营地的整体地形。许多其他露营地,尤其是60号公路沿线的露营地,往往看起来千篇一律,缺乏特色。但阿赫雷露营地的每个营地都感觉独一无二。此外,这里的沙滩是阿冈昆公园所有露营地中最好的。沙子洁白美丽,触感细腻柔软,宛如加勒比海滩。从这里还能欣赏到格兰德湖的壮丽景色。
Kiosk 和 Brent 营地的偏远跳水营地感觉更像是营地的延伸(它们看起来和主营地几乎没有什么区别),但 Achray 营地则真正感觉像“跳水”营地。Achray 的跳水营地很小,而且只有一个目的:搭帐篷、睡一觉,然后第二天开始你的独木舟之旅。
天气是典型的十一月变幻莫测。清晨和第一天差不多;气温在个位数左右,天空晴朗,还刮着几阵强风。然而,到了上午晚些时候,风力增强,而且变得非常猛烈。还下了一阵短暂的雨。走回车的路上,我听到森林里一棵树在我身边轰然倒下,大概是风吹的。希望是风吹的……
我在 Achray 营地总共待了 4 个小时,包括和 Larry 聊天的漫长休息时间。等我处理完事情,准备上路的时候已经是下午一点多了。当然,是在车里小憩了一会之后。
我有三个选择:
选项一:直接开车回家,走最快的路线,大约5.5小时。
选项二:取道60号公路回家,大约增加30分钟的车程,总时长6小时。
选项三:住在60号公路上的狼穴酒店,把车程分成两天。
出发前,我原本计划的是选项三。但我的体力出奇地旺盛,而且时间还早,大部分路程都在日落之前,所以我放弃了选项三。
我选择了方案二,决定走60号公路。没错,这会让本来就漫长的一天更加耗时,但我选择这个方案有几个原因。最重要的是我对这条路线了如指掌。对我来说,这趟车程完全不用费脑子。我不用担心跟着GPS走、错过弯道之类的,很轻松。另一个重要原因是,这样我开车穿过公园时就有机会看到野生动物,这真是个不错的选择。而且,我也很享受这种开车方式;沿着60号公路开车是我的快乐源泉。这也意味着我知道哪里可以找到洗手间、哪里可以停车小憩,哪里可以遛Elo(我可没打算让她在后座上连续坐6个小时)。最后,方案三也保留了可能性,以防我在中途改变主意。我已经在17个小时的公路旅行中,多出来的30分钟算什么呢?对吧!
在公园东门附近,我看到了一只几周前有机会拍到的狐狸。它太漂亮了。它是我见过的最可爱、最上镜的动物……当然,仅次于Elo!单是这次邂逅就让方案2的额外时间变得值得。我对拍到的照片非常满意。当时快到下午4点了,我知道拍狐狸意味着要在黑暗中开车回家的时间更长,但这是我愿意接受的。
第一次遇到狐狸后不久,我在公路边又看到了一只狐狸。如果我没有和之前的那只狐狸拍到精彩的照片,我可能就得靠边停车了。于是,我优先考虑了已经越来越少的日照时间,继续开车。
到目前为止,Elo 在我们一路开车的过程中表现得非常棒。她大部分时间都在睡觉。每天超过 17,000 步的步数可能对她有帮助!但即使她醒着,也没有呜咽或抱怨过一次。她表现得非常好。我想确保她在长达 6 个小时的车程中感到舒适,所以我在 60 号公路的中途停下来给她吃晚饭,然后带她出去散步。
散步结束后,我看到一群蓝鸦正在地上吃着食物残渣。一共有五只蓝鸦,这让我意识到,我以前从未见过这样的一群蓝鸦。我每次都只看到一只,或者两只。由于它们不停地飞来飞去,我没能拍到它们聚在一起的好照片,但我还是拍到了一些不错的单独照片。
我在车里小憩了 10 分钟,然后在下午 5 点之前开始了回家的最后一趟旅程。一直到亨茨维尔地区,天色才刚刚亮,之后就黑了。还好,车里的小憩给了我充足的能量,让我在接下来的车程中保持清醒和活力。
后续 这趟旅程的两天非常忙碌。我每天步行超过17000步,总共开车17个小时。两天我都是早上5点起床,总共花了8个小时记录三个不同的营地。虽然非常累,但我很高兴自己做到了。我之前从未去过布伦特营地和阿赫雷营地,所以我非常享受在无人的情况下探索这些营地的乐趣。
就十一月而言,天气非常好。气温一直徘徊在个位数左右,但整个旅程都是晴朗的天空,只有几分钟的降雨。如果风再小一点就好了,尤其是在阿赫雷营地,但风还是可以忍受的。
阿冈昆之巅是完美的住宿选择。里克和科琳热情地邀请我到他们美丽的房子里过夜,他们真是热情好客的主人。是的,它仍然是付费住宿,但我更乐意住在阿尔冈昆之巅,而不是路边的汽车旅馆。Elo 也更开心,因为她交了个新朋友。
最重要的是,我很高兴终于把这些营地从我的“已开发营地”项目清单中划掉了。营地关闭和地面积雪之间只有很短的时间间隔,所以我的日程安排很难抽出时间进行这次公路旅行。但我还是做到了。而且,观赏野生动物更是锦上添花。
文章导航