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