| Server IP : 38.190.208.107 / Your IP : 216.73.217.46 Web Server : nginx/1.28.1 System : Linux ht2026040333114 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.37-1 (2023-07-03) x86_64 User : root ( 0) PHP Version : 8.2.28 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv,eval,assert,passthru,system,exec,shell_exec,popen,proc_open MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /www/wwwroot/wp.3/wp-content/plugins/wp-statistics/src/Service/Analytics/ |
Upload File : |
<?php
namespace WP_Statistics\Service\Analytics;
/**
* Resolves page type and ID from URL path for SPA tracking support.
*
* When tracking hits via REST API, the client sends the page_uri parameter.
* This class resolves that URI to the correct source_type and source_id,
* fixing the issue where SPA navigations send stale client-side values.
*/
class UrlResolver
{
/**
* Resolve page type and ID from URL path
*
* @param string $pageUri URL path (e.g., "/blog/my-post/")
* @return array ['type' => string, 'id' => int, 'search_query' => string]
*/
public static function resolve($pageUri)
{
$result = ['type' => 'unknown', 'id' => 0, 'search_query' => ''];
if (empty($pageUri)) {
return $result;
}
// Normalize URI
$pageUri = '/' . ltrim($pageUri, '/');
// 1. Home page
if ($pageUri === '/') {
return ['type' => 'home', 'id' => 0, 'search_query' => ''];
}
// 2. Search page
if (preg_match('/[?&]s=([^&]*)/', $pageUri, $matches)) {
return [
'type' => 'search',
'id' => 0,
'search_query' => sanitize_text_field(urldecode($matches[1]))
];
}
// 3. Try to resolve as post/page using WordPress
$fullUrl = home_url($pageUri);
$postId = url_to_postid($fullUrl);
if ($postId > 0) {
$postType = get_post_type($postId);
$type = self::mapPostType($postType);
return ['type' => $type, 'id' => $postId, 'search_query' => ''];
}
// 4. Try to resolve as taxonomy term
$termResult = self::resolveTaxonomy($pageUri);
if ($termResult) {
return $termResult;
}
// 5. Try to resolve as author
$authorResult = self::resolveAuthor($pageUri);
if ($authorResult) {
return $authorResult;
}
// 6. Return unknown - fallback to client values
return $result;
}
/**
* Map WordPress post type to WP Statistics source type
*
* @param string $postType WordPress post type
* @return string WP Statistics source type
*/
private static function mapPostType($postType)
{
if ($postType === 'post') {
return 'post';
}
if ($postType === 'page') {
return 'page';
}
if ($postType === 'attachment') {
return 'attachment';
}
if ($postType === 'product') {
return 'product';
}
return 'post_type_' . $postType;
}
/**
* Resolve taxonomy term from URL
*
* @param string $pageUri URL path
* @return array|null Resolved taxonomy data or null
*/
private static function resolveTaxonomy($pageUri)
{
// Get category base
$categoryBase = get_option('category_base');
if (empty($categoryBase)) {
$categoryBase = 'category';
}
// Check category
if (preg_match('#/' . preg_quote($categoryBase, '#') . '/([^/]+)/?#', $pageUri, $matches)) {
$term = get_term_by('slug', $matches[1], 'category');
if ($term && !is_wp_error($term)) {
return ['type' => 'category', 'id' => $term->term_id, 'search_query' => ''];
}
}
// Get tag base
$tagBase = get_option('tag_base');
if (empty($tagBase)) {
$tagBase = 'tag';
}
// Check tag
if (preg_match('#/' . preg_quote($tagBase, '#') . '/([^/]+)/?#', $pageUri, $matches)) {
$term = get_term_by('slug', $matches[1], 'post_tag');
if ($term && !is_wp_error($term)) {
return ['type' => 'post_tag', 'id' => $term->term_id, 'search_query' => ''];
}
}
// Check custom taxonomies
$customTaxonomies = get_taxonomies(['public' => true, '_builtin' => false], 'objects');
foreach ($customTaxonomies as $taxonomy) {
$rewriteSlug = isset($taxonomy->rewrite['slug']) ? $taxonomy->rewrite['slug'] : $taxonomy->name;
if (preg_match('#/' . preg_quote($rewriteSlug, '#') . '/([^/]+)/?#', $pageUri, $matches)) {
$term = get_term_by('slug', $matches[1], $taxonomy->name);
if ($term && !is_wp_error($term)) {
return ['type' => 'tax_' . $taxonomy->name, 'id' => $term->term_id, 'search_query' => ''];
}
}
}
return null;
}
/**
* Resolve author from URL
*
* @param string $pageUri URL path
* @return array|null Resolved author data or null
*/
private static function resolveAuthor($pageUri)
{
global $wp_rewrite;
$authorBase = !empty($wp_rewrite->author_base) ? $wp_rewrite->author_base : 'author';
if (preg_match('#/' . preg_quote($authorBase, '#') . '/([^/]+)/?#', $pageUri, $matches)) {
$author = get_user_by('slug', $matches[1]);
if ($author) {
return ['type' => 'author', 'id' => $author->ID, 'search_query' => ''];
}
}
return null;
}
}