PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.26.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.26.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / helpers / FrmEmailSummaryHelper.php

FrmEmailSummaryHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.26.1, at classes/helpers/FrmEmailSummaryHelper.php

602 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * In-plugin summary emails helper
4 *
5 * @since 6.7
6 *
7 * @package Formidable
8 */
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 die( 'You are not allowed to call this page directly.' );
12 }
13
14 /**
15 * Class FrmEmailSummaryHelper
16 */
17 class FrmEmailSummaryHelper {
18
19 const MONTHLY = 'monthly';
20
21 const YEARLY = 'yearly';
22
23 /**
24 * Number of days to send the next monthly email.
25 */
26 const MONTHLY_PERIOD = 30;
27
28 /**
29 * Number of days to send the next yearly email.
30 */
31 const YEARLY_PERIOD = 365;
32
33 /**
34 * Number of days before renewal date to send yearly email.
35 */
36 const BEFORE_RENEWAL_PERIOD = 45;
37
38 /**
39 * Number of days before sending the first summary email after upgrade plugin.
40 */
41 const DELAY_AFTER_UPGRADE = 15;
42
43 /**
44 * Summary emails option name.
45 *
46 * @var string
47 */
48 public static $option_name = 'frm_summary_emails_options';
49
50 /**
51 * Checks if summary emails are enabled.
52 *
53 * @return bool
54 */
55 public static function is_enabled() {
56 $frm_settings = FrmAppHelper::get_settings();
57 return ! empty( $frm_settings->summary_emails ) && ! empty( $frm_settings->summary_emails_recipients );
58 }
59
60 /**
61 * Gets summary emails options.
62 *
63 * @return array
64 */
65 private static function get_options() {
66 $options = get_option( self::$option_name );
67
68 if ( ! $options ) {
69 $default_options = array(
70 // Do not send email within 15 days after updating.
71 'last_' . self::MONTHLY => self::get_date_from_today( '-' . self::DELAY_AFTER_UPGRADE . ' days' ),
72 'last_' . self::YEARLY => '',
73 'renewal_date' => '',
74 );
75
76 self::save_options( $default_options );
77 return $default_options;
78 }
79
80 return $options;
81 }
82
83 /**
84 * Saves summary emails options.
85 *
86 * @param array $options Options data.
87 *
88 * @return void
89 */
90 private static function save_options( $options ) {
91 update_option( self::$option_name, $options );
92 }
93
94 /**
95 * Checks if should send summary emails.
96 *
97 * @return array|false Return array of emails should be sent, or `false` if not send any emails.
98 */
99 public static function should_send_emails() {
100 if ( ! self::is_enabled() ) {
101 return false;
102 }
103
104 $emails = array();
105 $current_date = self::get_date_from_today();
106
107 // Check for monthly or yearly email.
108 $last_monthly = self::get_last_sent_date( 'monthly' );
109 $last_yearly = self::get_last_sent_date( 'yearly' );
110 $last_stats = max( $last_monthly, $last_yearly );
111
112 // Do not send any email if it isn't enough 30 days from the last stats email.
113 if ( $last_stats && self::MONTHLY_PERIOD > self::get_date_diff( $current_date, $last_stats ) ) {
114 return $emails;
115 }
116
117 if ( $last_yearly ) {
118 // If this isn't the first yearly email, send the new one after 1 year.
119 if ( $last_yearly && self::YEARLY_PERIOD <= self::get_date_diff( $current_date, $last_yearly ) ) {
120 $emails[] = self::YEARLY;
121 return $emails;
122 }
123 } else {
124 // If no yearly email has been sent, send it if it's less than 45 days until the renewal date.
125 $renewal_date = self::get_renewal_date();
126
127 if ( $renewal_date && self::BEFORE_RENEWAL_PERIOD >= self::get_date_diff( $current_date, $renewal_date ) ) {
128 $emails[] = self::YEARLY;
129 return $emails;
130 }
131 }
132
133 // If it isn't time for yearly email, it's time for monthly email.
134 $emails[] = self::MONTHLY;
135
136 return $emails;
137 }
138
139 /**
140 * Sends monthly email.
141 *
142 * @return void
143 */
144 public static function send_monthly() {
145 $monthly_email = new FrmEmailMonthly();
146
147 if ( $monthly_email->send() ) {
148 self::set_last_sent_date( self::MONTHLY );
149 }
150 }
151
152 /**
153 * Sends yearly email.
154 *
155 * @return void
156 */
157 public static function send_yearly() {
158 $yearly_email = new FrmEmailYearly();
159
160 if ( $yearly_email->send() ) {
161 self::set_last_sent_date( self::YEARLY );
162 }
163 }
164
165 /**
166 * Gets the renewal date and save to options. If it doesn't exist, get the created date of the lowest ID form then plus 1 year.
167 *
168 * @return string
169 */
170 private static function get_renewal_date() {
171 $options = self::get_options();
172
173 // Get cached value from options.
174 if ( ! empty( $options['renewal_date'] ) ) {
175 return $options['renewal_date'];
176 }
177
178 // Return the actual renewal date if it exists.
179 $license_info = FrmAddonsController::get_primary_license_info();
180
181 if ( ! empty( $license_info['expires'] ) ) {
182 $renewal_date = gmdate( 'Y-m-d', $license_info['expires'] );
183
184 $options['renewal_date'] = $renewal_date;
185 self::save_options( $options );
186 return $renewal_date;
187 }
188
189 // If renewal date doesn't exist, get from the first form creation date.
190 $first_form_date = self::get_earliest_form_created_date();
191
192 if ( $first_form_date ) {
193 $renewal_date = gmdate( 'Y-m-d', strtotime( $first_form_date . '+' . self::YEARLY_PERIOD . ' days' ) );
194
195 // If the first form is more than 1 year in the past, set renewal date to the next 45 days.
196 if ( $renewal_date < self::get_date_from_today() ) {
197 $renewal_date = self::get_date_from_today( '+' . self::BEFORE_RENEWAL_PERIOD . ' days' );
198 }
199
200 $options['renewal_date'] = $renewal_date;
201 self::save_options( $options );
202 return $renewal_date;
203 }
204
205 return false;
206 }
207
208 /**
209 * Gets date object.
210 *
211 * @param DateTime|string $date Date string or object.
212 *
213 * @return DateTime|false
214 */
215 private static function get_date_obj( $date ) {
216 if ( $date instanceof DateTime ) {
217 return $date;
218 }
219
220 return date_create( $date );
221 }
222
223 /**
224 * Gets the days different between 2 dates.
225 *
226 * @param DateTime|string $date1 Date 1.
227 * @param DateTime|string $date2 Date 2.
228 *
229 * @return false|int
230 */
231 private static function get_date_diff( $date1, $date2 ) {
232 $date1 = self::get_date_obj( $date1 );
233
234 if ( ! $date1 ) {
235 return false;
236 }
237
238 $date2 = self::get_date_obj( $date2 );
239
240 if ( ! $date2 ) {
241 return false;
242 }
243
244 return date_diff( $date1, $date2 )->days;
245 }
246
247 /**
248 * Gets sent date of the last monthly or yearly email.
249 *
250 * @param string $type Accepts `monthly`, `yearly`.
251 *
252 * @return false|string
253 */
254 public static function get_last_sent_date( $type ) {
255 $options = self::get_options();
256
257 if ( empty( $options[ 'last_' . $type ] ) ) {
258 return false;
259 }
260
261 return $options[ 'last_' . $type ];
262 }
263
264 /**
265 * Sets the last sent date of an email type.
266 *
267 * @param string $type Email type.
268 * @param mixed $value Set custom value. If this is null, set the current date.
269 *
270 * @return void
271 */
272 public static function set_last_sent_date( $type, $value = null ) {
273 $options = self::get_options();
274
275 $options[ 'last_' . $type ] = null === $value ? self::get_date_from_today() : '';
276 self::save_options( $options );
277 }
278
279 /**
280 * Gets the created date of earliest form.
281 *
282 * @return string
283 */
284 private static function get_earliest_form_created_date() {
285 return FrmDb::get_var(
286 'frm_forms',
287 array(),
288 'created_at',
289 array( 'order_by' => 'id ASC' )
290 );
291 }
292
293 /**
294 * Gets payments data.
295 *
296 * @param string $from_date From date.
297 * @param string $to_date To date.
298 *
299 * @return array Contains `count` and `total`.
300 */
301 public static function get_payments_data( $from_date, $to_date ) {
302 $payment = new FrmTransLitePayment();
303 return $payment->get_payments_stats( $from_date, $to_date );
304 }
305
306 /**
307 * Gets entries count in a date range.
308 *
309 * @param string $from_date From date.
310 * @param string $to_date To date.
311 *
312 * @return int
313 */
314 public static function get_entries_count( $from_date, $to_date ) {
315 return FrmDb::get_count(
316 'frm_items',
317 array(
318 // The `=` is added after `>` in the query.
319 'created_at >' => $from_date,
320 'created_at <' => $to_date . ' 23:59:59',
321 'is_draft' => 0,
322 // Do not count repeater entries.
323 'parent_item_id' => 0,
324 )
325 );
326 }
327
328 /**
329 * Gets top forms in a date range.
330 *
331 * @param string $from_date From date.
332 * @param string $to_date To date.
333 * @param int $limit Limit the result. Default is 5.
334 *
335 * @return array Contains `form_id`, `form_name`, and `items_count`.
336 */
337 public static function get_top_forms( $from_date, $to_date, $limit = 5 ) {
338 global $wpdb;
339
340 $result = $wpdb->get_results(
341 $wpdb->prepare(
342 "SELECT fr.id AS form_id, fr.name AS form_name, COUNT(*) as items_count
343 FROM {$wpdb->prefix}frm_items AS it INNER JOIN {$wpdb->prefix}frm_forms AS fr ON it.form_id = fr.id
344 WHERE it.created_at BETWEEN %s AND %s AND it.is_draft = 0 AND parent_form_id = 0
345 GROUP BY form_id ORDER BY items_count DESC LIMIT %d",
346 $from_date,
347 $to_date . ' 23:59:59',
348 intval( $limit )
349 )
350 );
351
352 // Remove slashes from form name.
353 foreach ( $result as &$value ) {
354 $value->form_name = wp_unslash( $value->form_name );
355 }
356
357 return $result;
358 }
359
360 /**
361 * Shows the comparison HTML in the email.
362 *
363 * @param float $diff Percentage of difference.
364 *
365 * @return void
366 */
367 public static function show_comparison( $diff ) {
368 if ( ! $diff ) {
369 return;
370 }
371
372 if ( $diff > 0 ) {
373 $arrow = '&uarr;';
374 $color = '#12b76a';
375 } else {
376 $arrow = '&darr;';
377 $color = '#f04438';
378 }
379
380 $displayed_value = round( $diff * 100 );
381
382 if ( ! $displayed_value ) {
383 // Do not show 0 value.
384 $displayed_value = $diff > 0 ? 1 : -1;
385 }
386
387 printf(
388 '<span style="color: %1$s; font-size: 0.75em; font-weight: 700;">
389 %2$s<span style="display: inline-block; line-height: 1.33;">%3$s</span>
390 </span>',
391 esc_attr( $color ),
392 esc_html( $arrow ),
393 intval( $displayed_value ) . '%'
394 );
395 }
396
397 /**
398 * Gets section CSS in the email.
399 *
400 * @param string $border_pos Border position. Default is `top`. Set to empty if no border.
401 *
402 * @return string
403 */
404 public static function get_section_style( $border_pos = 'top' ) {
405 if ( $border_pos ) {
406 $border = 'border-' . $border_pos . ': 1px solid #eaecf0;';
407 } else {
408 $border = '';
409 }
410 return 'padding: 3em 4.375em;' . $border;
411 }
412
413 /**
414 * Gets h2 CSS in the email.
415 *
416 * @return string
417 */
418 public static function get_heading2_style() {
419 return 'font-size: 1.125em; line-height: 1.33em; margin: 0 0 1.33em;';
420 }
421
422 /**
423 * Gets CSS for button.
424 *
425 * @param bool $display_block Whether to display the button as block.
426 *
427 * @return string
428 */
429 public static function get_button_style( $display_block = false ) {
430 return 'display: ' . ( $display_block ? 'block' : 'inline-block' ) . '; font-size: 0.875em; line-height: 2.4; border-radius: 1.2em; border: 1px solid #d0d5dd; font-weight: 600; text-align: center; margin-top: 2.6em; color: #1d2939; text-decoration: none; padding-left: 1em; padding-right: 1em;';
431 }
432
433 /**
434 * Shows the section heading with icon.
435 *
436 * @param string $icon Icon file name, without file path and extension. Use .png image.
437 * @param string $text Heading text.
438 *
439 * @return void
440 */
441 public static function section_heading_with_icon( $icon, $text ) {
442 ?>
443 <h2 style="<?php echo esc_attr( self::get_heading2_style() ); ?>">
444 <img style="vertical-align: bottom; height: 24px; width: auto;" src="<?php echo esc_url( FrmAppHelper::plugin_url() . '/images/' . $icon . '.png' ); ?>" alt="<?php echo esc_attr( $icon ); ?>" />
445 <span style="display: inline-block; vertical-align: text-bottom;"><?php echo esc_html( $text ); ?></span>
446 </h2>
447 <?php
448 }
449
450 /**
451 * Gets Formidable URL with tracking params.
452 *
453 * @param string $url The URL.
454 * @param array|string $args Custom tracking args if is array, or `utm_content` if is string.
455 *
456 * @return string
457 */
458 public static function get_frm_url( $url, $args = array() ) {
459 if ( is_array( $args ) ) {
460 $args = wp_parse_args(
461 $args,
462 array(
463 'medium' => 'summary-email',
464 'content' => 'link',
465 )
466 );
467 } else {
468 $args = array(
469 'medium' => 'summary-email',
470 'content' => $args,
471 );
472 }
473
474 return FrmAppHelper::admin_upgrade_link( $args, $url );
475 }
476
477 /**
478 * Gets the latest inbox message.
479 *
480 * @return array|false
481 */
482 public static function get_latest_inbox_message() {
483 $inbox = new FrmInbox();
484 $messages = $inbox->get_messages( 'filter' );
485
486 if ( ! $messages || ! is_array( $messages ) ) {
487 return false;
488 }
489
490 $messages = array_reverse( $messages );
491
492 foreach ( $messages as $message ) {
493 if ( 'news' !== $message['type'] ) {
494 continue;
495 }
496
497 return $message;
498 }
499
500 return false;
501 }
502
503 /**
504 * Gets out of date plugin names.
505 *
506 * @return array
507 */
508 public static function get_out_of_date_plugins() {
509 $update_data = FrmAddonsController::check_update( '' );
510
511 if ( ! $update_data || ! is_object( $update_data ) || empty( $update_data->response ) ) {
512 return array();
513 }
514
515 $plugins = array();
516
517 foreach ( $update_data->response as $plugin_data ) {
518 $plugins[] = $plugin_data->display_name;
519 }
520
521 return $plugins;
522 }
523
524 /**
525 * Processes inbox CTA button before showing in email.
526 *
527 * @param string $button_html Button HTML. This usually contains 1 button and 1 dismiss button.
528 *
529 * @return string
530 */
531 public static function process_inbox_cta_button( $button_html ) {
532 // Remove dismiss button.
533 $button_html = preg_replace( '/<a[^>]*class="[^"]*\bfrm_inbox_dismiss\b[^"]*"[^>]*>[^<]*<\/a>/', '', $button_html );
534
535 // Replace link utm.
536 $button_html = str_replace( 'utm_medium=inbox', 'utm_medium=summary-email', $button_html );
537
538 if ( strpos( $button_html, 'style="' ) ) {
539 // Maybe this button contains inline style.
540 return $button_html;
541 }
542
543 // Add inline CSS for specific button types.
544 if ( strpos( $button_html, 'frm-button-primary' ) ) {
545 $button_html = str_replace( '<a', '<a style="' . self::get_button_style() . '"', $button_html );
546 }
547
548 return $button_html;
549 }
550
551 /**
552 * Gets the localized date with the date diff from today.
553 *
554 * @param string $date_diff Date diff string. By default, this is empty, the result will be the current date.
555 *
556 * @return string
557 */
558 public static function get_date_from_today( $date_diff = '' ) {
559 if ( ! $date_diff ) {
560 return FrmAppHelper::get_localized_date( 'Y-m-d', gmdate( 'Y-m-d H:i:s' ) );
561 }
562 return FrmAppHelper::get_localized_date( 'Y-m-d', gmdate( 'Y-m-d H:i:s', strtotime( $date_diff ) ) );
563 }
564
565 /**
566 * Maybe remove recipients from setting from API.
567 *
568 * @since 6.8
569 *
570 * @param string $recipients Recipients.
571 *
572 * @return void
573 */
574 public static function maybe_remove_recipients_from_api( &$recipients ) {
575 $api = new FrmFormApi();
576 $addons = $api->get_api_info();
577
578 if ( empty( $addons['no_emails'] ) ) {
579 return;
580 }
581
582 $skip_emails = is_string( $addons['no_emails'] ) ? explode( ',', $addons['no_emails'] ) : (array) $addons['no_emails'];
583
584 $recipients = array_map( 'trim', explode( ',', $recipients ) );
585 $recipients = array_diff( $recipients, $skip_emails );
586 $recipients = implode( ',', $recipients );
587 }
588
589 /**
590 * Echos string in plain text email.
591 *
592 * @since 6.8
593 *
594 * @param string $string string.
595 *
596 * @return void
597 */
598 public static function plain_text_echo( $string ) {
599 echo wp_strip_all_tags( $string ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
600 }
601 }
602