PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.10
Independent Analytics – WordPress Analytics Plugin v1.10
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 / inc / queries / views.php
independent-analytics / inc / queries Last commit date
geos.php 3 years ago range_query.php 3 years ago referrers.php 3 years ago resources.php 3 years ago views.php 3 years ago
views.php
221 lines
1 <?php
2
3 namespace IAWP;
4
5 class Views extends Range_Query
6 {
7 const REFERRERS = 'REFERRERS';
8 const RESOURCES = 'RESOURCES';
9 const GEO = 'GEO';
10 private $views;
11 private $prev_period_views;
12 private $daily_views;
13 private $visitors;
14 private $prev_period_visitors;
15 private $daily_visitors;
16
17 public function __construct($type, $ids = null, $start = null, $end = null)
18 {
19 parent::__construct($start, $end);
20 if ($type == self::RESOURCES || $type == self::REFERRERS || $type == self::GEO) {
21 $this->query($type, $ids);
22 } else {
23 throw new \Exception('IAWP_Views: Unsupported type');
24 }
25 }
26
27 public function views()
28 {
29 return $this->views;
30 }
31
32 public function prev_period_views()
33 {
34 return $this->prev_period_views;
35 }
36
37 public function daily_views()
38 {
39 return $this->daily_views;
40 }
41
42 public function views_percentage_growth()
43 {
44 if ($this->views() == 0 || $this->prev_period_views() == 0) {
45 return 0;
46 } else {
47 return round((($this->views() / $this->prev_period_views()) - 1) * 100);
48 }
49 }
50
51 public function visitors()
52 {
53 return $this->visitors;
54 }
55
56 public function visitors_percentage_growth()
57 {
58 if ($this->visitors() == 0 || $this->prev_period_visitors() == 0) {
59 return 0;
60 } else {
61 return round((($this->visitors() / $this->prev_period_visitors()) - 1) * 100);
62 }
63 }
64
65 public function prev_period_visitors()
66 {
67 return $this->prev_period_visitors;
68 }
69
70 public function daily_visitors()
71 {
72 return $this->daily_visitors;
73 }
74
75 private function query($type, $ids)
76 {
77 global $wpdb;
78 $views_table = DB::views_table();
79 $visitors_table = DB::visitors_table();
80
81 if (is_null($ids)) {
82 $skip_in = 1;
83 $ids = [0];
84 $in = '%s';
85 } elseif (count($ids) == 0) {
86 $skip_in = 0;
87 $ids = [0];
88 $in = '%s';
89 } else {
90 $skip_in = 0;
91 $in = implode(',', array_fill(0, count($ids), '%s'));
92 }
93
94 if ($type == self::RESOURCES) {
95 $column = 'resource_id';
96 } elseif ($type == self::REFERRERS) {
97 $column = 'referrer_id';
98 } elseif ($type == self::GEO) {
99 $column = 'visitor_id';
100 }
101
102 $has_null_id = false;
103 foreach ($ids as $id) {
104 if (is_null($id)) {
105 $has_null_id = true;
106 break;
107 }
108 }
109 $null_check = '';
110
111 if ($type == self::REFERRERS && $has_null_id) {
112 $null_check = "OR $column IS NULL";
113 }
114
115 $utc = Timezone::utc_offset();
116 $local_offset = Timezone::local_offset();
117 $query = $wpdb->prepare(
118 "
119 SELECT
120 DATE(CONVERT_TZ(viewed_at, '$utc', '$local_offset')) as date,
121 COUNT(*) as views,
122 COUNT(DISTINCT visitor_id) as visitors
123 FROM $views_table
124 LEFT JOIN $visitors_table ON $views_table.visitor_id = $visitors_table.id
125 WHERE viewed_at BETWEEN %s AND %s
126 AND (%d = 1 OR $column IN ($in) $null_check)
127 AND ('$type' != 'GEO' OR $visitors_table.country_code IS NOT NULL)
128 GROUP BY DATE(CONVERT_TZ(viewed_at, '$utc', '$local_offset'))",
129 $this->formatted_start(),
130 $this->formatted_end(),
131 $skip_in,
132 ...$ids
133 );
134 $rows = $wpdb->get_results($query);
135
136 // This separate query for visitor counts is required
137 // Without it, visitors visiting on separate days are counted twice in the quick stats
138 $visitors_query = $wpdb->prepare(
139 "
140 SELECT
141 COUNT(DISTINCT visitor_id) as visitors
142 FROM $views_table
143 LEFT JOIN $visitors_table ON $views_table.visitor_id = $visitors_table.id
144 WHERE viewed_at BETWEEN %s AND %s
145 AND (%d = 1 OR $column IN ($in) $null_check)
146 AND ('$type' != 'GEO' OR $visitors_table.country_code IS NOT NULL)
147 ",
148 $this->formatted_start(),
149 $this->formatted_end(),
150 $skip_in,
151 ...$ids
152 );
153 $visitors = intval($wpdb->get_var($visitors_query));
154
155 $prev_period_query = $wpdb->prepare(
156 "
157 SELECT
158 COUNT(*) as views,
159 COUNT(DISTINCT visitor_id) as visitors
160 FROM $views_table
161 LEFT JOIN $visitors_table ON $views_table.visitor_id = $visitors_table.id
162 WHERE viewed_at BETWEEN %s AND %s
163 AND (%d = 1 OR $column IN ($in) $null_check)
164 AND ('$type' != 'GEO' OR $visitors_table.country_code IS NOT NULL)
165 ",
166 $this->prev_period_formatted_start(),
167 $this->prev_period_formatted_end(),
168 $skip_in,
169 ...$ids
170 );
171 $prev_period_results = $wpdb->get_row($prev_period_query);
172 $prev_period_views = $prev_period_results->views;
173 $prev_period_visitors = $prev_period_results->visitors;
174
175 $views = 0;
176 $daily_views = [];
177 $daily_visitors = [];
178
179 foreach ($rows as $row) {
180 $views += $row->views;
181 $daily_views[] = [$row->date, intval($row->views)];
182 $daily_visitors[] = [$row->date, intval($row->visitors)];
183 }
184
185 $this->views = $views;
186 $this->prev_period_views = $prev_period_views;
187 $this->visitors = $visitors;
188 $this->prev_period_visitors = $prev_period_visitors;
189 $this->daily_views = $this->fill_in_data_range($daily_views);
190 $this->daily_visitors = $this->fill_in_data_range($daily_visitors);
191 }
192
193 private function fill_in_data_range($partial_data)
194 {
195 $interval = new \DateInterval('P1D');
196 $start = clone $this->start();
197 $end = clone $this->end();
198 $user_timezone = new \DateTimeZone(Timezone::local_offset());
199 $start->setTimezone($user_timezone);
200 $end->setTimezone($user_timezone);
201
202 $date_range = new \DatePeriod($start, $interval, $end);
203 $new_data = [];
204
205 foreach ($date_range as $date) {
206 $views = 0;
207
208 foreach ($partial_data as $data_point) {
209 if ($date == (new \DateTime($data_point[0], $user_timezone))) {
210 $views = intval($data_point[1]);
211 break;
212 }
213 }
214
215 $new_data[] = [$date, $views];
216 }
217
218 return $new_data;
219 }
220 }
221