PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.2
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.2
3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / class-evf-email-entries-report.php
everest-forms / includes Last commit date
Helpers 1 year ago Integrations 1 month ago RestApi 2 weeks ago abilities 1 month ago abstracts 2 weeks ago admin 2 weeks ago blocks 1 year ago elementor 2 years ago export 2 months ago fields 1 month ago interfaces 8 years ago libraries 2 years ago log-handlers 1 year ago shortcodes 1 month ago stats 5 months ago templates 3 months ago traits 1 month ago class-everest-forms.php 2 weeks ago class-evf-addon-upsell.php 1 month ago class-evf-ajax.php 1 month ago class-evf-autoloader.php 8 years ago class-evf-background-process-import-entries.php 2 years ago class-evf-background-updater.php 8 years ago class-evf-cache-helper.php 2 months ago class-evf-cron.php 2 years ago class-evf-deprecated-action-hooks.php 6 years ago class-evf-deprecated-filter-hooks.php 5 years ago class-evf-email-entries-report.php 3 months ago class-evf-emails.php 1 month ago class-evf-fields.php 1 month ago class-evf-form-handler.php 1 month ago class-evf-form-task.php 1 month ago class-evf-forms-features.php 1 month ago class-evf-frontend-scripts.php 1 month ago class-evf-install.php 2 months ago class-evf-integrations.php 3 months ago class-evf-log-levels.php 8 years ago class-evf-logger.php 5 years ago class-evf-post-types.php 1 year ago class-evf-privacy.php 6 years ago class-evf-report-cron.php 2 months ago class-evf-reporting.php 2 months ago class-evf-session-handler.php 7 years ago class-evf-shortcodes.php 1 year ago class-evf-smart-tags.php 10 months ago class-evf-template-loader.php 1 year ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 1 month ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 5 months ago evf-formatting-functions.php 4 years ago evf-notice-functions.php 4 years ago evf-template-functions.php 4 years ago evf-template-hooks.php 8 years ago evf-update-functions.php 5 years ago
class-evf-email-entries-report.php
470 lines
1 <?php
2 /**
3 * EVF Email Entries Report
4 *
5 * @package EverestForms\Classes
6 * @since 2.0.9
7 */
8
9 defined( 'ABSPATH' ) || exit;
10
11 /**
12 * EVF_Email_Entries_Report Class.
13 */
14 class EVF_Email_Entries_Report {
15
16 /**
17 * @var string
18 */
19 private $frequency;
20
21 /**
22 * @var string
23 */
24 private $period_start;
25
26 /**
27 * @var string
28 */
29 private $period_end;
30
31 /**
32 * @var string
33 */
34 private $prev_period_start;
35
36 /**
37 * @var string
38 */
39 private $prev_period_end;
40
41 /**
42 * @var string
43 */
44 private $prev_prev_period_start;
45
46 /**
47 * @var string
48 */
49 private $prev_prev_period_end;
50
51 /**
52 * @var array
53 */
54 private $form_ids;
55
56 /**
57 * @var bool
58 */
59 private $is_test;
60
61 /**
62 * Cached entries data to avoid repeated DB queries.
63 *
64 * @var array|null
65 */
66 private $entries_cache = null;
67
68 /**
69 * Constructor.
70 *
71 * @param string $frequency Daily|Weekly|Monthly.
72 * @param array|null $form_ids Specific form IDs, or null to read from saved settings.
73 * @param bool $is_test Whether this is a test send.
74 */
75 public function __construct( $frequency, $form_ids = null, $is_test = false ) {
76 $this->frequency = $frequency;
77 $this->is_test = $is_test;
78
79 if ( is_null( $form_ids ) ) {
80 $saved = get_option( 'everest_forms_reporting_form_lists', array() );
81 $this->form_ids = is_array( $saved ) ? array_filter( array_map( 'absint', $saved ) ) : array();
82 } else {
83 $this->form_ids = is_array( $form_ids ) ? array_filter( array_map( 'absint', $form_ids ) ) : array();
84 }
85
86 $this->set_period_dates();
87 }
88
89 /**
90 * Set current and previous period date boundaries.
91 *
92 * @since 2.0.9
93 */
94 private function set_period_dates() {
95 switch ( $this->frequency ) {
96 case 'Daily':
97 $current_start_ts = strtotime( 'yesterday midnight' );
98 $current_end_ts = strtotime( 'today midnight' ) - 1;
99 $prev_start_ts = $current_start_ts - DAY_IN_SECONDS;
100 $prev_end_ts = $current_start_ts - 1;
101 break;
102
103 case 'Monthly':
104 $current_start_ts = strtotime( 'first day of last month midnight' );
105 $current_end_ts = $current_start_ts + (int) gmdate( 't', $current_start_ts ) * DAY_IN_SECONDS - 1;
106 $prev_start_ts = strtotime( '-1 month', $current_start_ts );
107 $prev_end_ts = $current_start_ts - 1;
108 break;
109
110 case 'Weekly':
111 default:
112 $current_end_ts = strtotime( 'today midnight' ) - 1;
113 $current_start_ts = $current_end_ts - ( 7 * DAY_IN_SECONDS ) + 1;
114 $prev_end_ts = $current_start_ts - 1;
115 $prev_start_ts = $prev_end_ts - ( 7 * DAY_IN_SECONDS ) + 1;
116 break;
117 }
118
119 $period_length = $prev_end_ts - $prev_start_ts;
120
121 $this->period_start = gmdate( 'Y-m-d H:i:s', $current_start_ts );
122 $this->period_end = gmdate( 'Y-m-d H:i:s', $current_end_ts );
123 $this->prev_period_start = gmdate( 'Y-m-d H:i:s', $prev_start_ts );
124 $this->prev_period_end = gmdate( 'Y-m-d H:i:s', $prev_end_ts );
125 $this->prev_prev_period_start = gmdate( 'Y-m-d H:i:s', $prev_start_ts - $period_length - 1 );
126 $this->prev_prev_period_end = gmdate( 'Y-m-d H:i:s', $prev_start_ts - 1 );
127 }
128
129 /**
130 * Period label.
131 *
132 * @since 2.0.9
133 * @return string
134 */
135 public function get_period_label() {
136 $date_format = get_option( 'date_format', 'F j, Y' );
137
138 switch ( $this->frequency ) {
139 case 'Daily':
140 return sprintf(
141 __( ' %s', 'everest-forms' ),
142 date_i18n( $date_format, strtotime( $this->period_start ) )
143 );
144
145 case 'Monthly':
146 return sprintf(
147 __( ' %s', 'everest-forms' ),
148 date_i18n( 'F Y', strtotime( $this->period_start ) )
149 );
150
151 case 'Weekly':
152 default:
153 return sprintf(
154 /* translators: 1: Start date, 2: End date */
155 __( '%1$s – %2$s', 'everest-forms' ),
156 date_i18n( $date_format, strtotime( $this->period_start ) ),
157 date_i18n( $date_format, strtotime( $this->period_end ) )
158 );
159 }
160 }
161
162 /**
163 * Resolve the form IDs to include in the report.
164 *
165 * @since 2.0.9
166 * @return int[]
167 */
168 private function resolve_form_ids() {
169 $all_published = array_map(
170 'intval',
171 (array) get_posts(
172 array(
173 'post_type' => 'everest_form',
174 'post_status' => 'publish',
175 'posts_per_page' => -1,
176 'fields' => 'ids',
177 )
178 )
179 );
180
181 if ( empty( $this->form_ids ) ) {
182 return $all_published;
183 }
184
185 return array_values(
186 array_intersect( $this->form_ids, $all_published )
187 );
188 }
189
190 /**
191 * Count entries for a form within a date range, excluding trash and draft.
192 *
193 * @since 2.0.9
194 *
195 * @param int $form_id
196 * @param string $date_start
197 * @param string $date_end
198 * @return int
199 */
200 private function count_entries( $form_id, $date_start, $date_end ) {
201 global $wpdb;
202
203 return (int) $wpdb->get_var(
204 $wpdb->prepare(
205 "SELECT COUNT(*)
206 FROM {$wpdb->prefix}evf_entries
207 WHERE form_id = %d
208 AND status != %s
209 AND status != %s
210 AND date_created >= %s
211 AND date_created <= %s",
212 $form_id,
213 'trash',
214 'draft',
215 $date_start,
216 $date_end
217 )
218 );
219 }
220
221 /**
222 * Count unread entries for a form within a date range.
223 *
224 * @since 2.0.9
225 *
226 * @param int $form_id
227 * @param string $date_start
228 * @param string $date_end
229 * @return int
230 */
231 private function count_unread_entries( $form_id, $date_start, $date_end ) {
232 global $wpdb;
233
234 return (int) $wpdb->get_var(
235 $wpdb->prepare(
236 "SELECT COUNT(*)
237 FROM {$wpdb->prefix}evf_entries
238 WHERE form_id = %d
239 AND status != %s
240 AND viewed = 0
241 AND date_created >= %s
242 AND date_created <= %s",
243 $form_id,
244 'trash',
245 $date_start,
246 $date_end
247 )
248 );
249 }
250
251 /**
252 * Get entry counts per form. Results are cached within the request.
253 *
254 * @since 2.0.9
255 * @return array
256 */
257 public function get_entries_data() {
258 if ( ! is_null( $this->entries_cache ) ) {
259 return $this->entries_cache;
260 }
261
262 $results = array();
263
264 foreach ( $this->resolve_form_ids() as $form_id ) {
265 if ( ! $form_id ) {
266 continue;
267 }
268
269 $current = $this->count_entries( $form_id, $this->period_start, $this->period_end );
270 $previous = $this->count_entries( $form_id, $this->prev_period_start, $this->prev_period_end );
271 $previous_prev = $this->count_entries( $form_id, $this->prev_prev_period_start, $this->prev_prev_period_end );
272 $unread = $this->count_unread_entries( $form_id, $this->period_start, $this->period_end );
273
274 $change = null;
275 if ( $previous > 0 ) {
276 $change = round( ( ( $current - $previous ) / $previous ) * 100, 1 );
277 }
278
279 $results[ $form_id ] = array(
280 'form_id' => $form_id,
281 'form_name' => get_the_title( $form_id ),
282 'current' => $current,
283 'previous' => $previous,
284 'previous_prev' => $previous_prev,
285 'unread' => $unread,
286 'change' => $change,
287 'view_url' => admin_url( 'admin.php?page=evf-entries&form_id=' . $form_id ),
288 );
289 }
290
291 uasort(
292 $results,
293 function ( $a, $b ) {
294 return $b['current'] <=> $a['current'];
295 }
296 );
297
298 $this->entries_cache = $results;
299
300 return $this->entries_cache;
301 }
302
303 /**
304 * Build summary totals from entries data.
305 *
306 * @since 2.0.9
307 * @param array $entries_data
308 * @return array
309 */
310 public function get_summary( $entries_data ) {
311 $total_entries = array_sum( array_column( $entries_data, 'current' ) );
312 $total_prev = array_sum( array_column( $entries_data, 'previous' ) );
313
314 return array(
315 'total_entries' => $total_entries,
316 'total_prev' => $total_prev,
317 'overall_change' => $total_prev > 0 ? round( ( ( $total_entries - $total_prev ) / $total_prev ) * 100, 1 ) : null,
318 'total_unread' => array_sum( array_column( $entries_data, 'unread' ) ),
319 'total_forms' => count( $entries_data ),
320 'active_forms' => count(
321 array_filter(
322 $entries_data,
323 function ( $f ) {
324 return $f['current'] > 0;
325 }
326 )
327 ),
328 );
329 }
330
331 /**
332 * Build highlight messages from entries data.
333 *
334 * @since 2.0.9
335 * @param array $entries_data
336 * @return array
337 */
338 public function get_highlights( $entries_data ) {
339 $highlights = array();
340
341 if ( empty( $entries_data ) ) {
342 return $highlights;
343 }
344
345 $top = null;
346 foreach ( $entries_data as $form ) {
347 if ( $form['current'] > 0 && ( null === $top || $form['current'] > $top['current'] ) ) {
348 $top = $form;
349 }
350 }
351 if ( $top ) {
352 $highlights['top_form'] = sprintf(
353 __( '<strong>%1$s</strong> received the most entries this period with <strong>%2$s</strong>.', 'everest-forms' ),
354 esc_html( $top['form_name'] ),
355 sprintf( _n( '%d submission', '%d submissions', $top['current'], 'everest-forms' ), $top['current'] )
356 );
357 }
358
359 $improved = null;
360 foreach ( $entries_data as $form ) {
361 if ( ! is_null( $form['change'] ) && $form['change'] > 0 && ( null === $improved || $form['change'] > $improved['change'] ) ) {
362 $improved = $form;
363 }
364 }
365 if ( $improved ) {
366 $highlights['most_improved'] = sprintf(
367 __( '<strong>%1$s</strong> grew the most, up <strong>%2$s%%</strong> compared to last period.', 'everest-forms' ),
368 esc_html( $improved['form_name'] ),
369 $improved['change']
370 );
371 }
372
373 $total_unread = array_sum( array_column( $entries_data, 'unread' ) );
374 if ( $total_unread > 0 ) {
375 $highlights['unread_alert'] = sprintf(
376 __( 'You have <strong>%s</strong> across your forms that need attention.', 'everest-forms' ),
377 sprintf( _n( '%d unread entry', '%d unread entries', $total_unread, 'everest-forms' ), $total_unread )
378 );
379 }
380
381 $inactive_forms = array_filter(
382 $entries_data,
383 function ( $f ) {
384 return 0 === $f['current'];
385 }
386 );
387 $inactive_count = count( $inactive_forms );
388 if ( $inactive_count > 0 ) {
389 $highlights['inactive_alert'] = sprintf(
390 __( '<strong>%1$s</strong> received no entries this period: %2$s.', 'everest-forms' ),
391 sprintf( _n( '%d form', '%d forms', $inactive_count, 'everest-forms' ), $inactive_count ),
392 esc_html(
393 implode(
394 ', ',
395 array_map(
396 function ( $f ) {
397 return $f['form_name'];
398 },
399 $inactive_forms
400 )
401 )
402 )
403 );
404 }
405
406 return $highlights;
407 }
408
409 /**
410 * Build footer data.
411 *
412 * @since 2.0.9
413 * @return array
414 */
415 public function get_footer_data() {
416 return array(
417 'site_name' => get_bloginfo( 'name' ),
418 'site_url' => home_url(),
419 'settings_url' => admin_url( 'admin.php?page=evf-settings&tab=advanced&section=entry_reports' ),
420 'entries_url' => admin_url( 'admin.php?page=evf-entries' ),
421 'unsubscribe_url' => add_query_arg(
422 array(
423 'evf_disable_reports' => 1,
424 'nonce' => wp_create_nonce( 'evf_disable_reports' ),
425 ),
426 home_url()
427 ),
428 'generated_at' => date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ),
429 'plugin_version' => defined( 'EVF_VERSION' ) ? EVF_VERSION : '',
430 );
431 }
432
433 /**
434 * Render the HTML email.
435 *
436 * @since 2.0.9
437 * @return string
438 */
439 public function render_html() {
440 $entries_data = $this->get_entries_data();
441 $summary = $this->get_summary( $entries_data );
442 $highlights = $this->get_highlights( $entries_data );
443 $footer = $this->get_footer_data();
444 $period_label = $this->get_period_label();
445 $is_test = $this->is_test;
446
447 ob_start();
448 include EVF_ABSPATH . 'includes/templates/entries-report.php';
449 return ob_get_clean();
450 }
451
452 /**
453 * Render the plain-text fallback email.
454 *
455 * @since 2.0.9
456 * @return string
457 */
458 public function render_plain_text() {
459 $entries_data = $this->get_entries_data();
460 $summary = $this->get_summary( $entries_data );
461 $highlights = $this->get_highlights( $entries_data );
462 $footer = $this->get_footer_data();
463 $period_label = $this->get_period_label();
464
465 ob_start();
466 include EVF_ABSPATH . 'includes/templates/entries-report-plain.php';
467 return ob_get_clean();
468 }
469 }
470