PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.11.3
Independent Analytics – WordPress Analytics Plugin v2.11.3
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 / Rows / Pages.php
independent-analytics / IAWP / Rows Last commit date
Campaigns.php 1 year ago Cities.php 1 year ago Countries.php 1 year ago Device_Browsers.php 1 year ago Device_OSS.php 1 year ago Device_Types.php 1 year ago Filter.php 1 year ago Forms.php 1 year ago Link_Patterns.php 1 year ago Links.php 1 year ago Pages.php 1 year ago Referrers.php 1 year ago Rows.php 1 year ago
Pages.php
132 lines
1 <?php
2
3 namespace IAWP\Rows;
4
5 use IAWP\Database;
6 use IAWP\Form_Submissions\Form;
7 use IAWP\Illuminate_Builder;
8 use IAWP\Models\Page;
9 use IAWP\Query;
10 use IAWP\Query_Taps;
11 use IAWP\Tables;
12 use IAWPSCOPED\Illuminate\Database\Query\Builder;
13 use IAWPSCOPED\Illuminate\Database\Query\JoinClause;
14 /** @internal */
15 class Pages extends \IAWP\Rows\Rows
16 {
17 private static $has_wp_comments_table = null;
18 public function attach_filters(Builder $query) : void
19 {
20 $query->joinSub($this->query(\true), 'page_rows', function (JoinClause $join) {
21 $join->on('page_rows.id', '=', 'views.resource_id');
22 });
23 }
24 protected function fetch_rows() : array
25 {
26 $rows = $this->query()->get()->all();
27 return \array_map(function (object $row) {
28 return Page::from_row($row);
29 }, $rows);
30 }
31 private function has_wp_comments_table() : bool
32 {
33 if (\is_bool(self::$has_wp_comments_table)) {
34 return self::$has_wp_comments_table;
35 }
36 global $wpdb;
37 self::$has_wp_comments_table = Database::has_table($wpdb->prefix . 'comments');
38 return self::$has_wp_comments_table;
39 }
40 private function query(?bool $skip_pagination = \false) : Builder
41 {
42 if ($skip_pagination) {
43 $this->number_of_rows = null;
44 }
45 $views_table = Query::get_table_name(Query::VIEWS);
46 $sessions_table = Query::get_table_name(Query::SESSIONS);
47 $resources_table = Query::get_table_name(Query::RESOURCES);
48 $orders_table = Query::get_table_name(Query::ORDERS);
49 $database_sort_columns = ['title' => 'cached_title', 'url' => 'cached_url', 'author' => 'cached_author', 'type' => 'cached_type_label', 'date' => 'cached_date', 'category' => 'cached_category'];
50 $sort_column = $this->sort_configuration->column();
51 foreach ($database_sort_columns as $key => $value) {
52 if ($sort_column === $key) {
53 $sort_column = $value;
54 }
55 }
56 $orders_query = Illuminate_Builder::new();
57 $orders_query->select(['sessions.initial_view_id AS view_id'])->selectRaw('IFNULL(COUNT(DISTINCT orders.order_id), 0) AS wc_orders')->selectRaw('IFNULL(ROUND(CAST(SUM(orders.total) AS SIGNED)), 0) AS wc_gross_sales')->selectRaw('IFNULL(ROUND(CAST(SUM(orders.total_refunded) AS SIGNED)), 0) AS wc_refunded_amount')->selectRaw('IFNULL(SUM(orders.total_refunds), 0) AS wc_refunds')->from($orders_table, 'orders')->leftJoin($orders_query->raw($views_table . ' AS views'), function (JoinClause $join) {
58 $join->on('orders.view_id', '=', 'views.id');
59 })->leftJoin($orders_query->raw($sessions_table . ' AS sessions'), function (JoinClause $join) {
60 $join->on('views.session_id', '=', 'sessions.session_id');
61 })->where('orders.is_included_in_analytics', '=', \true)->whereBetween('orders.created_at', $this->get_current_period_iso_range())->groupBy('orders.view_id');
62 $pages_query = Illuminate_Builder::new();
63 $pages_query->select('resources.*')->selectRaw('COUNT(DISTINCT views.id) AS views')->selectRaw('COUNT(DISTINCT sessions.visitor_id) AS visitors')->selectRaw('COUNT(DISTINCT IF(initial_view.resource_id = resources.id, sessions.visitor_id, NULL)) AS landing_page_visitors')->selectRaw('COUNT(DISTINCT sessions.session_id) AS sessions')->selectRaw('COUNT(DISTINCT IF(sessions.final_view_id IS NULL, sessions.session_id, NULL)) AS bounces')->selectRaw('AVG(TIMESTAMPDIFF(SECOND, views.viewed_at, views.next_viewed_at)) AS average_view_duration')->selectRaw('COUNT(DISTINCT IF(resources.id = initial_view.resource_id, sessions.session_id, NULL)) AS entrances')->selectRaw('COUNT(DISTINCT IF((resources.id = final_view.resource_id OR (resources.id = initial_view.resource_id AND sessions.final_view_id IS NULL)), sessions.session_id, NULL)) AS exits')->selectRaw('COUNT(DISTINCT clicks.click_id) AS clicks')->selectRaw('IFNULL(SUM(the_orders.wc_orders), 0) AS wc_orders')->selectRaw('IFNULL(SUM(the_orders.wc_gross_sales), 0) AS wc_gross_sales')->selectRaw('IFNULL(SUM(the_orders.wc_refunded_amount), 0) AS wc_refunded_amount')->selectRaw('IFNULL(SUM(wc_refunds), 0) AS wc_refunds')->selectRaw('IFNULL(SUM(form_submissions.form_submissions), 0) AS form_submissions')->tap(function (Builder $query) {
64 foreach (Form::get_forms() as $form) {
65 $query->selectRaw("SUM(IF(form_submissions.form_id = ?, form_submissions.form_submissions, 0)) AS {$form->submissions_column()}", [$form->id()]);
66 }
67 })->from($views_table, 'views')->leftJoin($pages_query->raw($sessions_table . ' AS sessions'), function (JoinClause $join) {
68 $join->on('views.session_id', '=', 'sessions.session_id');
69 })->leftJoin($pages_query->raw($resources_table . ' AS resources'), function (JoinClause $join) {
70 $join->on('views.resource_id', '=', 'resources.id');
71 })->leftJoin($pages_query->raw($views_table . ' AS initial_view'), function (JoinClause $join) {
72 $join->on('sessions.initial_view_id', '=', 'initial_view.id');
73 })->leftJoin($pages_query->raw($views_table . ' AS final_view'), function (JoinClause $join) {
74 $join->on('sessions.final_view_id', '=', 'final_view.id');
75 })->leftJoin($pages_query->raw(Tables::clicks() . ' AS clicks'), function (JoinClause $join) {
76 $join->on('clicks.view_id', '=', 'views.id');
77 })->leftJoinSub($orders_query, 'the_orders', function (JoinClause $join) {
78 $join->on('the_orders.view_id', '=', 'views.id');
79 })->tap(Query_Taps::tap_authored_content_check(\false))->when($this->has_wp_comments_table(), function (Builder $query) {
80 $query->selectRaw('IFNULL(comments.comments, 0) AS comments');
81 $query->leftJoinSub($this->get_comments_query(), 'comments', 'comments.resource_id', '=', 'resources.id');
82 }, function (Builder $query) {
83 $query->selectRaw('0 AS comments');
84 })->leftJoinSub($this->get_form_submissions_query(), 'form_submissions', function (JoinClause $join) {
85 $join->on('form_submissions.view_id', '=', 'views.id');
86 })->whereBetween('views.viewed_at', $this->get_current_period_iso_range())->when(!$this->appears_to_be_for_real_time_analytics(), function (Builder $query) {
87 $query->whereBetween('sessions.created_at', $this->get_current_period_iso_range());
88 })->when(\count($this->filters) > 0, function (Builder $query) {
89 foreach ($this->filters as $filter) {
90 if (!$this->is_a_calculated_column($filter->column())) {
91 $filter->apply_to_query($query);
92 }
93 }
94 })->groupBy('resources.id')->having('views', '>', 0)->when(!$this->is_using_a_calculated_column(), function (Builder $query) use($sort_column) {
95 $query->when($this->sort_configuration->is_column_nullable(), function (Builder $query) use($sort_column) {
96 $query->orderByRaw("CASE WHEN {$sort_column} IS NULL THEN 1 ELSE 0 END");
97 })->orderBy($sort_column, $this->sort_configuration->direction())->orderBy('cached_title')->when(\is_int($this->number_of_rows), function (Builder $query) {
98 $query->limit($this->number_of_rows);
99 });
100 });
101 $previous_period_query = Illuminate_Builder::new();
102 $previous_period_query->select(['views.resource_id'])->selectRaw('COUNT(*) AS previous_period_views')->selectRaw('COUNT(DISTINCT sessions.visitor_id) AS previous_period_visitors')->from($views_table, 'views')->join($previous_period_query->raw($sessions_table . ' AS sessions'), 'views.session_id', '=', 'sessions.session_id')->whereBetween('views.viewed_at', $this->get_previous_period_iso_range())->whereBetween('sessions.created_at', $this->get_previous_period_iso_range())->groupBy('views.resource_id');
103 $outer_query = Illuminate_Builder::new();
104 $outer_query->selectRaw('pages.*')->selectRaw('IFNULL((views - previous_period_views) / previous_period_views * 100, 0) AS views_growth')->selectRaw('IFNULL((visitors - previous_period_visitors) / previous_period_visitors * 100, 0) AS visitors_growth')->selectRaw('IFNULL(bounces / sessions * 100, 0) AS bounce_rate')->selectRaw('IFNULL((exits / views) * 100, 0) AS exit_percent')->selectRaw('ROUND(CAST(wc_gross_sales - wc_refunded_amount AS SIGNED)) AS wc_net_sales')->selectRaw('IF(visitors = 0, 0, (wc_orders / landing_page_visitors) * 100) AS wc_conversion_rate')->selectRaw('IF(visitors = 0, 0, (wc_gross_sales - wc_refunded_amount) / landing_page_visitors) AS wc_earnings_per_visitor')->selectRaw('IF(wc_orders = 0, 0, ROUND(CAST(wc_gross_sales / wc_orders AS SIGNED))) AS wc_average_order_volume')->selectRaw('IF(visitors = 0, 0, (form_submissions / visitors) * 100) AS form_conversion_rate')->tap(function (Builder $query) {
105 foreach (Form::get_forms() as $form) {
106 $query->selectRaw("IF(visitors = 0, 0, ({$form->submissions_column()} / visitors) * 100) AS {$form->conversion_rate_column()}");
107 }
108 })->when(\count($this->filters) > 0, function (Builder $query) {
109 foreach ($this->filters as $filter) {
110 if ($this->is_a_calculated_column($filter->column())) {
111 $filter->apply_to_query($query);
112 }
113 }
114 })->fromSub($pages_query, 'pages')->leftJoinSub($previous_period_query, 'previous_period_stats', 'pages.id', '=', 'previous_period_stats.resource_id')->when($this->is_using_a_calculated_column(), function (Builder $query) use($sort_column) {
115 $query->when($this->sort_configuration->is_column_nullable(), function (Builder $query) use($sort_column) {
116 $query->orderByRaw("CASE WHEN {$sort_column} IS NULL THEN 1 ELSE 0 END");
117 })->orderBy($sort_column, $this->sort_configuration->direction())->orderBy('cached_title')->when(\is_int($this->number_of_rows), function (Builder $query) {
118 $query->limit($this->number_of_rows);
119 });
120 });
121 return $outer_query;
122 }
123 private function get_comments_query() : Builder
124 {
125 global $wpdb;
126 $comments_table = $wpdb->prefix . 'comments';
127 $resources_table = Query::get_table_name(Query::RESOURCES);
128 $comments_query = Illuminate_Builder::new()->select(['resources.id AS resource_id'])->selectRaw('COUNT(*) AS comments')->from($comments_table, 'comments')->join($resources_table . " AS resources", 'comments.comment_post_ID', '=', 'resources.singular_id')->where('comments.comment_type', '=', 'comment')->where('comments.comment_approved', '=', '1')->whereBetween('comments.comment_date_gmt', $this->get_current_period_iso_range())->groupBy('resources.id');
129 return $comments_query;
130 }
131 }
132