PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.13
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.13
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Admin / Reports / ReportEmail.php

ReportEmail.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.13, at includes/Admin/Reports/ReportEmail.php

342 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace NotificationX\Admin\Reports;
3
4 use NotificationX\Admin\Settings;
5 use NotificationX\Core\Helper as NotificationX_Helper;
6 use NotificationX\GetInstance;
7
8 /**
9 * This class is responsible for sending weekly email with reports
10 * @method static ReportEmail get_instance($args = null)
11 *
12 * @since 1.4.4
13 */
14 class ReportEmail {
15 /**
16 * Instance of Admin
17 *
18 * @var Admin
19 */
20 use GetInstance;
21
22 /**
23 * Get a single Instance of Analytics
24 * @var Report_Email
25 */
26 public $settings = null;
27
28 private static $current_timestamp = null;
29 private static $current_date = null;
30
31 /**
32 * Initially Invoked by Default.
33 */
34 public function __construct() {
35 $this->settings = Settings::get_instance()->get('settings');
36 if( !Settings::get_instance()->get('settings.enable_analytics', true) || Settings::get_instance()->get('settings.disable_reporting')) {
37 $this->mail_report_deactivation( 'daily_email_reporting' );
38 $this->mail_report_deactivation( 'weekly_email_reporting' );
39 $this->mail_report_deactivation( 'monthly_email_reporting' );
40 return;
41 }
42
43 add_filter( 'cron_schedules', array( $this, 'schedules_cron' ) );
44 add_action('admin_init', array( $this, 'mail_report_activation' ));
45 add_action('weekly_email_reporting', array( $this, 'send_email_weekly' ));
46 }
47
48 public function reporting( $request ){
49 if( ! boolval($request->get_param('disable_reporting')) ) {
50 if( $request->has_param('reporting_email') ) {
51 $email = $request->get_param( 'reporting_email' );
52 }
53 $email = $this->receiver_email_address( $email );
54
55 if( ! empty( $email ) ) {
56 $is_send = $this->send_email_weekly( $request->get_param('reporting_frequency'), true, $email );
57 if( $is_send && ! is_wp_error( $is_send ) ) {
58 return [ 'message' => __( 'Successfully Sent an Email', 'notificationx' ) ];
59 } else if ( is_wp_error( $is_send ) ) {
60 return $is_send;
61 } else {
62 new \WP_Error('nx_unknown_reason', __( 'Email cannot be sent for some reason.', 'notificationx' ) );
63 }
64 }
65 new \WP_Error('nx_unknown_reason', __( 'Invalid email address.', 'notificationx' ) );
66 } else {
67 return new \WP_Error('nx_disabled_reporting', __( 'You have to enable Reporting first.', 'notificationx' ) );
68 }
69 }
70
71 private static function timestamps( $date = false ){
72 if( is_null( self::$current_timestamp ) ) {
73 self::$current_timestamp = current_time('timestamp');
74 }
75 if( $date ) {
76 if( is_null( self::$current_date ) ) {
77 self::$current_date = current_time('Y-m-d');
78 }
79 return self::$current_date;
80 }
81 return self::$current_timestamp;
82 }
83
84 public function create_date($count = '-7days'){
85 return gmdate('Y-m-d', strtotime($count, self::timestamps()));
86 }
87
88 public function get_stats( $start_date, $end_date = null ){
89 global $wpdb;
90
91 $extra_query = $wpdb->prepare( 'BETWEEN %s AND %s', $start_date, $end_date );
92
93 if ( is_null( $end_date ) ) {
94 $extra_query = $wpdb->prepare( ' = %s', $start_date );
95 }
96
97 $query = "SELECT MAIN.`nx_id`, MAIN.`title`, MAIN.`type`, STATS.`views`, STATS.`clicks`, STATS.`CTR` FROM ( SELECT P.`nx_id`, title, type FROM {$wpdb->prefix}nx_posts as P LEFT JOIN {$wpdb->prefix}nx_stats as S ON P.`nx_id` = S.`nx_id` GROUP BY P.nx_id ) AS MAIN INNER JOIN ( SELECT *, (clicks/views)*100 as ctr FROM ( SELECT SUM(views) as views, SUM(clicks) as clicks, nx_id FROM {$wpdb->prefix}nx_stats WHERE created_at $extra_query GROUP BY nx_id ) as VCID ) as STATS
98 ON MAIN.`nx_id` = STATS.`nx_id`";
99
100 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- False positive: the query is prepared via $this->wpdb->prepare(), which this sniff does not recognise, and only $wpdb->prefix table names are interpolated. Audited 2026-07-16.
101 return $wpdb->get_results( $query );
102 }
103 /**
104 * Calculate Total NotificationX Views
105 * @return int
106 */
107 public function get_data( $frequency = 'nx_weekly'){
108 if( $frequency == 'nx_daily' ) {
109 $start_date = $this->create_date('last day');
110 $end_date = null;
111 $previous_start_date = $this->create_date('last day last day');
112 $previous_end_date = null;
113 }
114
115 if( $frequency == 'nx_weekly' ) {
116 $start_date = $this->create_date('-7days');
117 $end_date = $this->create_date('last day');
118 $previous_start_date = $this->create_date('-14days');
119 $previous_end_date = $this->create_date('-7days');
120 }
121 if( $frequency == 'nx_monthly' ) {
122 $previous_start_date = $this->create_date('first day of last month last month');
123 $previous_end_date = $this->create_date('last day of last month last month');
124 $start_date = $this->create_date('first day of last month');
125 $end_date = $this->create_date('last day of last month');
126 }
127
128 $current_data = $this->get_stats( $start_date, $end_date );
129 $previous_data = $this->get_stats( $previous_start_date, $previous_end_date );
130
131 $from_date = $previous_start_date;
132 $to_date = $frequency == 'nx_daily' ? $start_date : $end_date;
133
134 $data = [
135 'from_date' => $from_date,
136 'to_date' => $to_date,
137 'current_data' => $current_data,
138 'previous_data' => $previous_data,
139 ];
140
141 return $this->generate_data( $data );
142 }
143
144 private function percentage( $_last, $_current ){
145 return $_last > 0 ? number_format( ( ( $_current - $_last ) / $_last ) * 100, 2 ) : 0;
146 }
147
148 private function previous_data( &$_single_data, &$_data = null ){
149 if( empty( $_single_data ) ) {
150 return [
151 'last_views' => 0,
152 'percentage_views' => 0,
153 'last_clicks' => 0,
154 'percentage_clicks' => 0,
155 'last_ctr' => 0,
156 'percentage_ctr' => 0,
157 ];
158 }
159 $_new_data = [];
160 array_walk( $_single_data, function( $item , $key ) use( &$_data, &$_new_data ) {
161 switch( $key ) {
162 case 'views':
163 $_new_data['last_views'] = $item;
164 $_new_data['percentage_views'] = $this->percentage( $item, $_data['views'] );
165 break;
166 case 'clicks':
167 $_new_data['last_clicks'] = $item;
168 $_new_data['percentage_clicks'] = $this->percentage( $item, $_data['clicks'] );
169 break;
170 case 'ctr':
171 $_new_data['last_ctr'] = $item;
172 $_new_data['percentage_ctr'] = $this->percentage( $item, $_data['ctr'] );
173 break;
174 }
175 });
176
177 return $_new_data;
178 }
179
180 public function generate_data( &$data ){
181 if( empty( $data ) ) {
182 return [];
183 }
184
185 // previous -> || (isset( $data['previous_data'] ) && empty( $data['previous_data'] )
186 if( (isset( $data['current_data'] ) && empty( $data['current_data'] ) ) ) {
187 return [];
188 }
189
190 $current_data = [];
191 $previous_data = [];
192 array_walk( $data['previous_data'], function( $single ) use ( &$previous_data ){
193 $previous_data[ $single->nx_id ] = ( array ) $single;
194 });
195 array_walk( $data['current_data'], function( $single ) use ( &$current_data, &$previous_data, $data ){
196 $_single_data = ( array ) $single;
197 $_single_data['source'] = NotificationX_Helper::get_type_title( $single->type );
198 $_single_data['type'] = NotificationX_Helper::get_type_title( $single->type );
199 $_single_data['from_date'] = $data['from_date'];
200 $_single_data['to_date'] = $data['to_date'];
201 $_previous_data = [];
202 if( isset( $previous_data[ $single->nx_id ] ) ) {
203 $_previous_data = $this->previous_data( $previous_data[ $single->nx_id ], $_single_data );
204 } else {
205 $_previous_data = $this->previous_data( $_previous_data, $_single_data );
206 }
207 $current_data[ $single->nx_id ] = array_merge( $_single_data, $_previous_data );
208 });
209
210 return $current_data;
211 }
212 /**
213 * Adds a custom cron schedule for Weekly.
214 *
215 * @param array $schedules An array of non-default cron schedules.
216 * @return array Filtered array of non-default cron schedules.
217 */
218 function schedules_cron( $schedules = array() ) {
219 $schedules['nx_weekly'] = array(
220 'interval' => 604800,
221 'display' => __( 'Once Weekly', 'notificationx' )
222 );
223 $schedules['nx_daily'] = array(
224 'interval' => 86400,
225 'display' => __( 'Once Daily', 'notificationx' )
226 );
227 $schedules['nx_monthly'] = array(
228 'interval' => strtotime( 'first day of next month 9AM' ),
229 'display' => __( 'Once Monthly', 'notificationx' )
230 );
231 return $schedules;
232 }
233
234 /**
235 * Set Email Receiver mail address
236 * By Default, Admin Email Address
237 * Admin can set Custom email from NotificationX Advanced Settings Panel
238 * @return email||String
239 */
240 public function receiver_email_address( $email = '' ) {
241 if( empty( $email ) ) {
242 $email = Settings::get_instance()->get('settings.reporting_email' );
243 if( empty( $email ) ) {
244 $email = get_option( 'admin_email' );
245 }
246 }
247 if( strpos( $email, ',' ) !== false ) {
248 $email = str_replace( ' ', '', $email );
249 $email = explode(',', $email );
250 } else {
251 $email = trim( $email );
252 }
253 return $email;
254 }
255
256 /**
257 * Set Email Subject
258 * By Default, subject will be "Weekly Reporting for NotificationX"
259 * Admin can set Custom Subject from NotificationX Advanced Settings Panel
260 * @return subject||String
261 */
262 public function email_subject() {
263 $site_name = get_bloginfo( 'name' );
264 /* translators: %s: site name */
265 $subject = sprintf( __( 'Weekly Engagement Summary of “%s”', 'notificationx' ), $site_name );
266 if( isset( $this->settings['reporting_subject'] ) && ! empty( $this->settings['reporting_subject'] ) ) {
267 $subject = stripcslashes( $this->settings['reporting_subject'] );
268 }
269 return $subject;
270 }
271
272 public function reporting_frequency(){
273 $frequency = Settings::get_instance()->get('settings.reporting_frequency', 'nx_weekly');
274 return $frequency;
275 }
276
277 /**
278 * Enable Cron Function
279 * Hook: admin_init
280 */
281 function mail_report_activation() {
282 $day = "monday";
283 if( isset( $this->settings['reporting_day'] ) ) {
284 $day = $this->settings['reporting_day'];
285 }
286
287 $frequency = $this->reporting_frequency();
288 if( $frequency === 'nx_weekly' ) {
289 $datetime = strtotime( "next $day 9AM", current_time('timestamp') );
290 $triggered = Settings::get_instance()->get("reporting.mail_sent.$frequency", false);
291 if ( $triggered == 1 ) {
292 $this->mail_report_deactivation( 'weekly_email_reporting' );
293 }
294 if( ! $triggered ) {
295 $datetime = strtotime( "+1hour", current_time('timestamp') );
296 }
297 $this->mail_report_deactivation( 'daily_email_reporting' );
298 $this->mail_report_deactivation( 'monthly_email_reporting' );
299 if ( ! wp_next_scheduled ( 'weekly_email_reporting' ) ) {
300 wp_schedule_event( $datetime, $frequency, 'weekly_email_reporting' );
301 }
302 }
303
304 }
305
306 /**
307 * Execute Cron Function
308 * Hook: admin_init
309 */
310 public function send_email_weekly( $frequency = 'nx_weekly', $test = false, $email = null ) {
311 $data = $this->get_data( $frequency );
312 if( empty( $data ) ) {
313 return new \WP_Error('nx_no_reporting_data', __('No data found.', 'notificationx'));
314 }
315 if( isset( $this->settings['enable_analytics'] ) && ! $this->settings['enable_analytics'] ) {
316 return new \WP_Error('nx_disabled_analytics', __('Analytics disabled. No data found.', 'notificationx'));
317 }
318 $to = is_null( $email ) ? $this->receiver_email_address() : $email;
319 if( empty( $to ) ) {
320 return new \WP_Error('nx_reporting_email', __('No email found.', 'notificationx'));
321 }
322
323 $subject = $this->email_subject();
324 $template = new EmailTemplate();
325 $message = $template->template_body( $data, $frequency );
326 $headers = array( 'Content-Type: text/html; charset=UTF-8', "From: NotificationX <support@wpdeveloper.com>" );
327 if( ! $test ) {
328 $triggered = Settings::get_instance()->get("reporting.mail_sent.$frequency");
329 $triggered = ! $triggered ? 0 : $triggered++;
330 Settings::get_instance()->set("reporting.mail_sent.$frequency", $triggered);
331 }
332 return wp_mail( $to, $subject, $message, $headers );
333 }
334
335 /**
336 * Disable Cron Function
337 * Hook: plugin_deactivation
338 */
339 public function mail_report_deactivation( $clear_hook = 'weekly_email_reporting' ) {
340 wp_clear_scheduled_hook( $clear_hook );
341 }
342 }