PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.7.3
Independent Analytics – WordPress Analytics Plugin v2.7.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 / Email_Reports / Email_Reports.php
independent-analytics / IAWP / Email_Reports Last commit date
Email_Chart.php 2 years ago Email_Reports.php 2 years ago Interval.php 2 years ago Interval_Factory.php 2 years ago
Email_Reports.php
207 lines
1 <?php
2
3 namespace IAWP\Email_Reports;
4
5 use DateTime;
6 use IAWP\Email_Reports\Intervals\Monthly;
7 use IAWP\Rows\Campaigns;
8 use IAWP\Rows\Countries;
9 use IAWP\Rows\Device_Types;
10 use IAWP\Rows\Pages;
11 use IAWP\Rows\Referrers;
12 use IAWP\Sort_Configuration;
13 use IAWP\Statistics\Page_Statistics;
14 use IAWP\Statistics\Statistic;
15 use IAWP\Utils\URL;
16 use IAWPSCOPED\Proper\Timezone;
17 /** @internal */
18 class Email_Reports
19 {
20 private $interval;
21 public function __construct()
22 {
23 $this->interval = \IAWP\Email_Reports\Interval_Factory::from_option();
24 \add_filter('cron_schedules', [$this, 'add_monthly_cron_schedule']);
25 $monitored_options = ['iawp_email_report_interval', 'iawp_email_report_time', 'iawp_email_report_email_addresses'];
26 foreach ($monitored_options as $option) {
27 \add_action('update_option_' . $option, [$this, 'schedule'], 10, 0);
28 \add_action('add_option_' . $option, [$this, 'schedule'], 10, 0);
29 }
30 // Maybe reschedule when starting day of the week is changed
31 \add_action('update_option_iawp_dow', [$this, 'maybe_reschedule'], 10, 0);
32 \add_action('add_option_iawp_dow', [$this, 'maybe_reschedule'], 10, 0);
33 \add_action('iawp_send_email_report', [$this, 'send_email_report']);
34 }
35 public function schedule()
36 {
37 // Necessary to update the interval as the option backing it may have changed
38 $this->interval = \IAWP\Email_Reports\Interval_Factory::from_option();
39 $this->unschedule();
40 if (empty(\IAWPSCOPED\iawp()->get_option('iawp_email_report_email_addresses', []))) {
41 return;
42 }
43 \wp_schedule_event($this->interval->next_interval_start()->getTimestamp(), $this->interval->id(), 'iawp_send_email_report');
44 }
45 public function unschedule()
46 {
47 $timestamp = \wp_next_scheduled('iawp_send_email_report');
48 \wp_unschedule_event($timestamp, 'iawp_send_email_report');
49 }
50 /**
51 * For testing purposes, get the
52 *
53 * @return DateTime
54 */
55 public function next_event_scheduled_at() : ?DateTime
56 {
57 if (!\wp_next_scheduled('iawp_send_email_report')) {
58 return null;
59 }
60 $date = new DateTime();
61 $date->setTimezone(Timezone::site_timezone());
62 $date->setTimestamp(\wp_next_scheduled('iawp_send_email_report'));
63 return $date;
64 }
65 public function next_email_at_for_humans() : string
66 {
67 if (!\wp_next_scheduled('iawp_send_email_report')) {
68 return \esc_html__('There is no email scheduled.', 'independent-analytics');
69 }
70 $date = $this->interval->next_interval_start();
71 $day = $date->format(\get_option('date_format'));
72 $time = $date->format(\get_option('time_format'));
73 return \sprintf(\__('Next email scheduled for %s at %s.', 'independent-analytics'), '<span>' . $day . '</span>', '<span>' . $time . '</span>');
74 }
75 public function maybe_reschedule()
76 {
77 if (!\wp_next_scheduled('iawp_send_email_report')) {
78 return;
79 }
80 if (\IAWPSCOPED\iawp()->get_option('iawp_email_report_interval', 'monthly') != 'weekly') {
81 return;
82 }
83 $this->schedule();
84 }
85 public function send_email_report(bool $is_test_email = \false)
86 {
87 // This code was added to fix an issue with monthly email reports. When you set up a monthly
88 // email report, the first email will always be correct because we pick the exact timestamp
89 // we want to send it. The issue is with the recurring interval. It's backed by MONTH_IN_SECONDS
90 // which is a fixed constant. Months have a varying number of seconds so this caused slight
91 // differences in when subsequent monthly email reports were sent. The code below fixes this by
92 // rescheduling monthly email reports as they're sent. That allows us to pinpoint the exact
93 // correct next time to run it, while still falling back to the inaccurate monthly interval
94 // should a given email never send for some reason.
95 if ($this->interval->id() === 'monthly') {
96 $this->schedule();
97 }
98 $to = \IAWPSCOPED\iawp()->get_option('iawp_email_report_email_addresses', []);
99 if (empty($to)) {
100 return;
101 }
102 $body = $this->get_email_body();
103 $headers[] = 'From: ' . \get_bloginfo('name') . ' <' . \get_bloginfo('admin_email') . '>';
104 $headers[] = 'Content-Type: text/html; charset=UTF-8';
105 return \wp_mail($to, $this->subject_line($is_test_email), $body, $headers);
106 }
107 public function get_email_body($colors = '')
108 {
109 $statistics = new Page_Statistics($this->interval->date_range());
110 $quick_stats = \array_values(\array_filter($statistics->get_statistics(), function (Statistic $statistics) {
111 return $statistics->is_visible() && $statistics->is_group_plugin_enabled();
112 }));
113 $chart = new \IAWP\Email_Reports\Email_Chart($statistics);
114 $colors = $colors == '' ? \IAWPSCOPED\iawp()->get_option('iawp_email_report_colors', ['#5123a0', '#fafafa', '#3a1e6b', '#fafafa', '#5123a0', '#a985e6', '#ece9f2', '#f7f5fa', '#ece9f2', '#dedae6']) : \explode(',', $colors);
115 return \IAWPSCOPED\iawp_blade()->run('email.email', [
116 'site_title' => \get_bloginfo('name'),
117 'site_url' => (new URL(\get_site_url()))->get_domain(),
118 'date' => $this->interval->report_time_period_for_humans(),
119 // The value that needs to change
120 'stats' => $quick_stats,
121 'top_ten' => $this->get_top_ten(),
122 'chart_views' => $chart->views,
123 'chart_title' => $this->interval->chart_title(),
124 'most_views' => $chart->most_views,
125 'y_labels' => $chart->y_labels,
126 'x_labels' => $chart->x_labels,
127 'colors' => $colors,
128 ]);
129 }
130 public function add_monthly_cron_schedule($schedules)
131 {
132 $schedules['monthly'] = ['interval' => \MONTH_IN_SECONDS, 'display' => \esc_html__('Once a Month', 'independent-analytics')];
133 return $schedules;
134 }
135 private function subject_line(bool $is_test_email) : string
136 {
137 $parts = [];
138 if ($is_test_email) {
139 $parts[] = \__('[Test]', 'independent-analytics');
140 }
141 $parts[] = \__('Analytics Report for', 'independent-analytics');
142 $parts[] = \get_bloginfo('name');
143 $parts[] = '[' . $this->interval->report_time_period_for_humans() . ']';
144 return \esc_html(\implode(' ', $parts));
145 }
146 private function get_top_ten() : array
147 {
148 $date_range = $this->interval->date_range();
149 $queries = ['pages' => 'title', 'referrers' => 'referrer', 'countries' => 'country', 'devices' => 'device_type', 'campaigns' => 'title', 'landing_pages' => 'title', 'exit_pages' => 'title'];
150 $top_ten = [];
151 $sort_configuration = new Sort_Configuration('views', 'desc');
152 $title = '';
153 foreach ($queries as $type => $title) {
154 if ($type === 'pages') {
155 $query = new Pages($date_range, 10, null, $sort_configuration);
156 $title = \esc_html__('Pages', 'independent-analytics');
157 } elseif ($type === 'referrers') {
158 $query = new Referrers($date_range, 10, null, $sort_configuration);
159 $title = \esc_html__('Referrers', 'independent-analytics');
160 } elseif ($type === 'countries') {
161 $query = new Countries($date_range, 10, null, $sort_configuration);
162 $title = \esc_html__('Countries', 'independent-analytics');
163 } elseif ($type === 'devices') {
164 $query = new Device_Types($date_range, 10, null, $sort_configuration);
165 $title = \esc_html__('Devices', 'independent-analytics');
166 } elseif ($type === 'campaigns') {
167 $query = new Campaigns($date_range, 10, null, $sort_configuration);
168 $title = \esc_html__('Campaigns', 'independent-analytics');
169 } elseif ($type === 'landing_pages') {
170 $query = new Pages($date_range, 10, null, new Sort_Configuration('entrances', 'desc'));
171 $title = \esc_html__('Landing Pages', 'independent-analytics');
172 } elseif ($type === 'exit_pages') {
173 $query = new Pages($date_range, 10, null, new Sort_Configuration('exits', 'desc'));
174 $title = \esc_html__('Exit Pages', 'independent-analytics');
175 } else {
176 continue;
177 }
178 $rows = \array_map(function ($row, $index) use($type) {
179 if ($type == 'referrers') {
180 $edited_title = $row->referrer();
181 } elseif ($type == 'countries') {
182 $edited_title = $row->country();
183 } elseif ($type == 'devices') {
184 $edited_title = $row->device_type();
185 } elseif ($type == 'campaigns') {
186 $edited_title = $row->utm_campaign();
187 } else {
188 $edited_title = $row->title();
189 }
190 $edited_title = \mb_strlen($edited_title) > 30 ? \mb_substr($edited_title, 0, 30) . '...' : $edited_title;
191 $metric = 'views';
192 if ($type == 'landing_pages') {
193 $metric = 'entrances';
194 } elseif ($type == 'exit_pages') {
195 $metric = 'exits';
196 }
197 return ['title' => $edited_title, 'views' => $row->{$metric}()];
198 }, $query->rows(), \array_keys($query->rows()));
199 if (\count($rows) == 0) {
200 continue;
201 }
202 $top_ten[$type] = ['title' => $title, 'rows' => $rows];
203 }
204 return $top_ten;
205 }
206 }
207