PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.22.0
Independent Analytics – WordPress Analytics Plugin v1.22.0
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / IAWP / Queries / View.php
independent-analytics / IAWP / Queries Last commit date
Campaigns.php 3 years ago City_Statistics.php 3 years ago Country_Statistics.php 3 years ago Current_Traffic_Finder.php 3 years ago Interval.php 3 years ago Minute_Interval.php 3 years ago Range_Query.php 3 years ago Referrers.php 3 years ago Reset_Database.php 3 years ago Resources.php 3 years ago Ten_Second_Interval.php 3 years ago View.php 3 years ago Views.php 3 years ago Visitors_Over_Time_Finder.php 3 years ago
View.php
255 lines
1 <?php
2
3 namespace IAWP_SCOPED\IAWP\Queries;
4
5 use IAWP_SCOPED\IAWP\Models\Page_Author_Archive;
6 use IAWP_SCOPED\IAWP\Models\Page_Date_Archive;
7 use IAWP_SCOPED\IAWP\Models\Page_Home;
8 use IAWP_SCOPED\IAWP\Models\Page_Not_Found;
9 use IAWP_SCOPED\IAWP\Models\Page_Post_Type_Archive;
10 use IAWP_SCOPED\IAWP\Models\Page_Search;
11 use IAWP_SCOPED\IAWP\Models\Page_Singular;
12 use IAWP_SCOPED\IAWP\Models\Page_Term_Archive;
13 use IAWP_SCOPED\IAWP\Models\Visitor;
14 use IAWP_SCOPED\IAWP\Query;
15 use IAWP_SCOPED\IAWP\Utils\String_Util;
16 use IAWP_SCOPED\IAWP\Utils\URL;
17 class View
18 {
19 private $payload;
20 private $referrer_url;
21 private $visitor;
22 private $campaign_fields;
23 private $viewed_at;
24 private $resource;
25 private $session;
26 /**
27 * @param array $payload
28 * @param string|null $referrer_url
29 * @param Visitor $visitor
30 * @param array $campaign_fields
31 * @param null $viewed_at
32 */
33 public function __construct(array $payload, ?string $referrer_url, Visitor $visitor, array $campaign_fields, $viewed_at = null)
34 {
35 $this->payload = $payload;
36 $this->referrer_url = \trim($referrer_url);
37 $this->visitor = $visitor;
38 $this->campaign_fields = $campaign_fields;
39 $this->viewed_at = $viewed_at;
40 $this->resource = $this->fetch_or_create_resource();
41 $this->session = $this->fetch_or_create_session();
42 $view_id = $this->create_view();
43 $this->set_sessions_initial_view($view_id);
44 }
45 private function set_sessions_initial_view(int $view_id)
46 {
47 global $wpdb;
48 $sessions_table = Query::get_table_name(Query::SESSIONS);
49 $wpdb->query($wpdb->prepare("UPDATE {$sessions_table} SET initial_view_id = %d WHERE session_id = %d AND initial_view_id IS NULL", $view_id, $this->session));
50 }
51 private function create_view()
52 {
53 $date = \is_null($this->viewed_at) ? new \DateTime() : $this->viewed_at;
54 $viewed_at = $date->format('Y-m-d H:i:s');
55 return Query::query('create_view', ['resource_id' => $this->resource, 'viewed_at' => $viewed_at, 'page' => $this->payload['page'], 'session_id' => $this->session])->last_inserted_id();
56 }
57 private function fetch_resource()
58 {
59 global $wpdb;
60 $resources_table = Query::get_table_name(Query::RESOURCES);
61 $query = '';
62 $payload_copy = \array_merge($this->payload);
63 unset($payload_copy['page']);
64 switch ($payload_copy['resource']) {
65 case 'singular':
66 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND singular_id = %d", $payload_copy['resource'], $payload_copy['singular_id']);
67 break;
68 case 'author_archive':
69 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND author_id = %d", $payload_copy['resource'], $payload_copy['author_id']);
70 break;
71 case 'date_archive':
72 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND date_archive = %s", $payload_copy['resource'], $payload_copy['date_archive']);
73 break;
74 case 'post_type_archive':
75 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND post_type = %s", $payload_copy['resource'], $payload_copy['post_type']);
76 break;
77 case 'term_archive':
78 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND term_id = %s", $payload_copy['resource'], $payload_copy['term_id']);
79 break;
80 case 'search':
81 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND search_query = %s", $payload_copy['resource'], $payload_copy['search_query']);
82 break;
83 case 'home':
84 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s ", $payload_copy['resource']);
85 break;
86 case '404':
87 $query = $wpdb->prepare("SELECT * FROM {$resources_table} WHERE resource = %s AND not_found_url = %s", $payload_copy['resource'], $payload_copy['not_found_url']);
88 break;
89 }
90 $resource = $wpdb->get_row($query);
91 if (\is_null($resource)) {
92 return null;
93 }
94 return $resource;
95 }
96 private function fetch_or_create_resource() : int
97 {
98 global $wpdb;
99 $resources_table = Query::get_table_name(Query::RESOURCES);
100 $resource = $this->fetch_resource();
101 if (\is_null($resource)) {
102 $payload_copy = \array_merge($this->payload);
103 unset($payload_copy['page']);
104 $wpdb->insert($resources_table, $payload_copy);
105 $resource = $this->fetch_resource();
106 }
107 // Todo - This probably shouldn't happen here... A call should be make to the page and then the page should
108 // know if it's a page type that needs to be cached or not.
109 switch ($resource->resource) {
110 case 'singular':
111 (new Page_Singular($resource))->update_cache();
112 break;
113 case 'author_archive':
114 (new Page_Author_Archive($resource))->update_cache();
115 break;
116 case 'post_type_archive':
117 (new Page_Post_Type_Archive($resource))->update_cache();
118 break;
119 case 'term_archive':
120 (new Page_Term_Archive($resource))->update_cache();
121 break;
122 case 'home':
123 (new Page_Home($resource))->update_cache();
124 break;
125 case 'date_archive':
126 (new Page_Date_Archive($resource))->update_cache();
127 break;
128 case '404':
129 (new Page_Not_Found($resource))->update_cache();
130 break;
131 case 'search':
132 (new Page_Search($resource))->update_cache();
133 break;
134 }
135 return $resource->id;
136 }
137 /**
138 * @param string|null $referrer_url
139 * @return bool
140 */
141 private function from_internal_page(?string $referrer_url) : bool
142 {
143 return !empty($referrer_url) && String_Util::str_starts_with(\strtolower($referrer_url), \strtolower(\site_url()));
144 }
145 /**
146 * @return int|null ID of the session that should be used for this view
147 */
148 private function fetch_or_create_session() : ?int
149 {
150 $from_external_page = !$this->from_internal_page($this->referrer_url);
151 $session = Query::query('get_current_session', ['visitor_id' => $this->visitor->id()])->row();
152 if (\is_null($session)) {
153 return $this->create_session();
154 }
155 $same_referrer = $this->fetch_referrer() === $session->referrer_id;
156 $same_resource = \intval($this->fetch_resource()->id) === $this->fetch_last_viewed_resource();
157 $same_as_previous_view = $same_referrer && $same_resource;
158 // The goal here is to prevent a page refresh from creating another session
159 if ($from_external_page && !$same_as_previous_view) {
160 return $this->create_session();
161 }
162 return $session->session_id;
163 }
164 /**
165 * @return int ID of newly created session
166 */
167 public function create_session() : int
168 {
169 $date = \is_null($this->viewed_at) ? new \DateTime() : $this->viewed_at;
170 $created_at = $date->format('Y-m-d H:i:s');
171 return Query::query('create_session', ['visitor_id' => $this->visitor->id(), 'referrer_id' => $this->fetch_or_create_referrer(), 'campaign_id' => $this->get_campaign(), 'created_at' => $created_at])->last_inserted_id();
172 }
173 /**
174 * Fetch the last view, if any.
175 *
176 * @return int|null
177 */
178 function fetch_last_viewed_resource() : ?int
179 {
180 global $wpdb;
181 $views_table = Query::get_table_name(Query::VIEWS);
182 $session = Query::query('get_current_session', ['visitor_id' => $this->visitor->id()])->row();
183 if (\is_null($session)) {
184 return null;
185 }
186 $view = $wpdb->get_row($wpdb->prepare("\n SELECT * FROM {$views_table} WHERE session_id = %d ORDER BY viewed_at DESC LIMIT 1\n ", $session->session_id));
187 if (\is_null($view)) {
188 return null;
189 }
190 return $view->resource_id;
191 }
192 /**
193 * @return int|null ID of referrer, if any
194 */
195 function fetch_referrer() : ?int
196 {
197 if (!isset($this->referrer_url) || \strlen($this->referrer_url) === 0) {
198 return null;
199 }
200 $url = new URL($this->referrer_url);
201 if (!$url->is_valid_url()) {
202 return null;
203 }
204 if ($this->from_internal_page($this->referrer_url)) {
205 return null;
206 }
207 $referrer = Query::query('get_referrer', ['domain' => $url->get_domain()])->row();
208 if (\is_null($referrer)) {
209 return null;
210 }
211 return $referrer->id;
212 }
213 private function fetch_or_create_referrer() : ?int
214 {
215 $referrer_id = $this->fetch_referrer();
216 if (!\is_null($referrer_id)) {
217 return $referrer_id;
218 }
219 $url = new URL($this->referrer_url);
220 if (!$url->is_valid_url()) {
221 return null;
222 }
223 if ($this->from_internal_page($this->referrer_url)) {
224 return null;
225 }
226 Query::query('create_referrer', ['domain' => $url->get_domain()]);
227 return $this->fetch_referrer();
228 }
229 private function get_campaign() : ?int
230 {
231 global $wpdb;
232 $required_fields = ['utm_source', 'utm_medium', 'utm_campaign'];
233 $valid = \true;
234 foreach ($required_fields as $field) {
235 if (!isset($this->campaign_fields[$field])) {
236 $valid = \false;
237 }
238 }
239 if (!$valid) {
240 return null;
241 }
242 $campaigns_table = Query::get_table_name(Query::CAMPAIGNS);
243 $campaign = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$campaigns_table} WHERE utm_source = %s AND utm_medium = %s AND utm_campaign = %s AND (utm_term = %s OR (%d = 0 AND utm_term IS NULL)) AND (utm_content = %s OR (%d = 0 AND utm_content IS NULL))", $this->campaign_fields['utm_source'], $this->campaign_fields['utm_medium'], $this->campaign_fields['utm_campaign'], $this->campaign_fields['utm_term'], isset($this->campaign_fields['utm_term']) ? 1 : 0, $this->campaign_fields['utm_content'], isset($this->campaign_fields['utm_content']) ? 1 : 0));
244 if (!\is_null($campaign)) {
245 return $campaign->campaign_id;
246 }
247 $wpdb->insert($campaigns_table, ['utm_source' => $this->campaign_fields['utm_source'], 'utm_medium' => $this->campaign_fields['utm_medium'], 'utm_campaign' => $this->campaign_fields['utm_campaign'], 'utm_term' => $this->campaign_fields['utm_term'], 'utm_content' => $this->campaign_fields['utm_content']]);
248 $campaign = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$campaigns_table} WHERE utm_source = %s AND utm_medium = %s AND utm_campaign = %s AND (utm_term = %s OR (%d = 0 AND utm_term IS NULL)) AND (utm_content = %s OR (%d = 0 AND utm_content IS NULL))", $this->campaign_fields['utm_source'], $this->campaign_fields['utm_medium'], $this->campaign_fields['utm_campaign'], $this->campaign_fields['utm_term'], isset($this->campaign_fields['utm_term']) ? 1 : 0, $this->campaign_fields['utm_content'], isset($this->campaign_fields['utm_content']) ? 1 : 0));
249 if (!\is_null($campaign)) {
250 return $campaign->campaign_id;
251 }
252 return null;
253 }
254 }
255