RealTime.php
115 lines
| 1 | <?php |
| 2 | |
| 3 | namespace IAWP\RealTime; |
| 4 | |
| 5 | use IAWPSCOPED\Carbon\CarbonImmutable; |
| 6 | use IAWP\Click_Tracking\Click_Processing_Job; |
| 7 | use IAWP\Date_Range\Exact_Date_Range; |
| 8 | use IAWP\Examiner_Config; |
| 9 | use IAWP\Icon_Directory_Factory; |
| 10 | use IAWP\Map_Data; |
| 11 | use IAWP\Rows\Countries; |
| 12 | use IAWP\Tables\Groups\Group; |
| 13 | use IAWP\Tables\Table_Campaigns; |
| 14 | use IAWP\Tables\Table_Devices; |
| 15 | use IAWP\Tables\Table_Geo; |
| 16 | use IAWP\Tables\Table_Pages; |
| 17 | use IAWP\Tables\Table_Referrers; |
| 18 | use IAWP\Utils\Singleton; |
| 19 | use IAWP\Utils\Timezone; |
| 20 | use IAWPSCOPED\Illuminate\Support\Collection; |
| 21 | /** @internal */ |
| 22 | class RealTime |
| 23 | { |
| 24 | use Singleton; |
| 25 | private ?CarbonImmutable $starting_at; |
| 26 | private ?Examiner_Config $examiner_config; |
| 27 | public function __construct(?CarbonImmutable $starting_at = null, ?Examiner_Config $examiner_config = null) |
| 28 | { |
| 29 | $this->starting_at = $starting_at ?? CarbonImmutable::now(Timezone::utc_timezone()); |
| 30 | $this->starting_at = $this->starting_at->ceilSeconds(10); |
| 31 | $this->examiner_config = $examiner_config; |
| 32 | } |
| 33 | public function get_real_time_analytics() : array |
| 34 | { |
| 35 | // Clicks need to be processed before showing real-time data |
| 36 | (new Click_Processing_Job())->handle(); |
| 37 | $five_minutes_ago = $this->starting_at->subMinutes(5)->subSeconds(10); |
| 38 | $range = new Exact_Date_Range($five_minutes_ago->toDateTime(), $this->starting_at->toDateTime(), \false); |
| 39 | $recent_traffic = new \IAWP\RealTime\RecentTraffic($range, $this->examiner_config); |
| 40 | $visitors = $recent_traffic->visitor_count(); |
| 41 | $chart_data = ['short_labels' => $recent_traffic->short_labels(), 'long_labels' => $recent_traffic->long_labels(), 'timestamps' => $recent_traffic->timestamps(), 'views' => $recent_traffic->views(), 'orders' => $recent_traffic->orders(), 'clicks' => $recent_traffic->clicks(), 'form_submissions' => $recent_traffic->form_submissions()]; |
| 42 | $geo_table = new Table_Geo(); |
| 43 | $countries = new Countries($range, $geo_table->sanitize_sort_parameters('visitors')); |
| 44 | if ($this->examiner_config) { |
| 45 | if ($geo_table->id() === $this->examiner_config->type()) { |
| 46 | $countries->limit_to($this->examiner_config->id()); |
| 47 | } elseif ($geo_table->id() !== $this->examiner_config->type()) { |
| 48 | $countries->for_examiner($this->examiner_config); |
| 49 | } |
| 50 | } |
| 51 | $map_data = new Map_Data($countries->rows()); |
| 52 | $minimum_items_per_list = 10; |
| 53 | $lists = []; |
| 54 | $tables = [new Table_Pages($this->get_group_preference('views')), new Table_Referrers($this->get_group_preference('referrers')), new Table_Devices($this->get_group_preference('devices')), new Table_Campaigns($this->get_group_preference('campaigns', 'utm_campaign')), new Table_Geo($this->get_group_preference('geo'))]; |
| 55 | foreach ($tables as $table) { |
| 56 | $group = $table->group(); |
| 57 | $rows_class = $group->rows_class(); |
| 58 | $rows = new $rows_class($range, $table->sanitize_sort_parameters('visitors')); |
| 59 | $list_items = []; |
| 60 | if ($this->examiner_config) { |
| 61 | if ($table->id() === $this->examiner_config->type()) { |
| 62 | $rows->limit_to($this->examiner_config->id()); |
| 63 | } elseif ($table->id() !== $this->examiner_config->type()) { |
| 64 | $rows->for_examiner($this->examiner_config); |
| 65 | } |
| 66 | } |
| 67 | foreach ($rows->rows() as $index => $row) { |
| 68 | $title_column = $group->title_column(); |
| 69 | $icon = null; |
| 70 | if ($table->id() === 'geo') { |
| 71 | // Can this be on a row insteade |
| 72 | $icon = Icon_Directory_Factory::flags()->find($row->country_code()); |
| 73 | } |
| 74 | $list_items[] = ['id' => $row->id(), 'position' => $index + 1, 'group' => $group->singular(), 'title' => $row->{$title_column}(), 'visitors' => $row->visitors(), 'icon' => $icon]; |
| 75 | } |
| 76 | $groups = Collection::make($table->groups()->groups())->filter(function (Group $group) { |
| 77 | if ($group->id() === 'campaign') { |
| 78 | return \false; |
| 79 | } |
| 80 | return \true; |
| 81 | })->map(function (Group $group) { |
| 82 | return [$group->id(), $group->singular()]; |
| 83 | })->all(); |
| 84 | $lists[$table->id()] = ['id' => $table->id(), 'title' => $table->name(), 'group_id' => $group->id(), 'group_title' => $group->singular(), 'groups' => $groups, 'count' => \number_format_i18n(\count($list_items)), 'column' => \__('Visitors', 'independent-analytics'), 'entries' => $this->fill_rows_with_blanks($list_items, $minimum_items_per_list), 'icon' => \IAWPSCOPED\iawp_render('icons.' . $table->id()), 'empty' => \__('No data found', 'independent-analytics')]; |
| 85 | } |
| 86 | return ['visitors' => $visitors, 'starting_at' => $this->starting_at->format('Uv'), 'country_data' => $map_data->get_country_data(), 'chart_data' => $chart_data, 'lists' => $lists]; |
| 87 | } |
| 88 | public function get_group_preference(string $table_id, ?string $default = null) : ?string |
| 89 | { |
| 90 | $groups = \get_user_meta(\get_current_user_id(), 'iawp_real_time_groups', \true); |
| 91 | if (!\is_array($groups) || !\array_key_exists($table_id, $groups)) { |
| 92 | return $default; |
| 93 | } |
| 94 | return $groups[$table_id]; |
| 95 | } |
| 96 | public function render_real_time_analytics() |
| 97 | { |
| 98 | echo \IAWPSCOPED\iawp_render('real-time', $this->get_real_time_analytics()); |
| 99 | } |
| 100 | private function fill_rows_with_blanks(array $rows, $items_per_list) : array |
| 101 | { |
| 102 | $number_of_rows = \count($rows); |
| 103 | $blanks_to_add = $items_per_list - $number_of_rows; |
| 104 | // Nothing to add |
| 105 | if ($blanks_to_add < 1) { |
| 106 | return $rows; |
| 107 | } |
| 108 | for ($i = 0; $i < $blanks_to_add; $i++) { |
| 109 | $position = $number_of_rows + $i + 1; |
| 110 | $rows[] = ['id' => 'blank-' . $position, 'title' => '', 'position' => $position, 'visitors' => '', 'blank' => \true]; |
| 111 | } |
| 112 | return $rows; |
| 113 | } |
| 114 | } |
| 115 |