PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.33.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.33.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.33.1, at classes/helpers/FrmEmailSummaryHelper.php

589 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 return $options;
70 }
71
72 $default_options = array(
73 // Do not send email within 15 days after updating.
74 'last_' . self::MONTHLY => self::get_date_from_today( '-' . self::DELAY_AFTER_UPGRADE . ' days' ),
75 'last_' . self::YEARLY => '',
76 'renewal_date' => '',
77 );
78
79 self::save_options( $default_options );
80 return $default_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 $options['renewal_date'] = $renewal_date;
184 self::save_options( $options );
185 return $renewal_date;
186 }
187
188 // If renewal date doesn't exist, get from the first form creation date.
189 $first_form_date = self::get_earliest_form_created_date();
190
191 if ( $first_form_date ) {
192 $renewal_date = gmdate( 'Y-m-d', strtotime( $first_form_date . '+' . self::YEARLY_PERIOD . ' days' ) );
193
194 // If the first form is more than 1 year in the past, set renewal date to the next 45 days.
195 if ( $renewal_date < self::get_date_from_today() ) {
196 $renewal_date = self::get_date_from_today( '+' . self::BEFORE_RENEWAL_PERIOD . ' days' );
197 }
198
199 $options['renewal_date'] = $renewal_date;
200 self::save_options( $options );
201 return $renewal_date;
202 }
203
204 return false;
205 }
206
207 /**
208 * Gets date object.
209 *
210 * @param DateTime|string $date Date string or object.
211 *
212 * @return DateTime|false
213 */
214 private static function get_date_obj( $date ) {
215 return $date instanceof DateTime ? $date : date_create( $date );
216 }
217
218 /**
219 * Gets the days different between 2 dates.
220 *
221 * @param DateTime|string $date1 Date 1.
222 * @param DateTime|string $date2 Date 2.
223 *
224 * @return false|int
225 */
226 private static function get_date_diff( $date1, $date2 ) {
227 $date1 = self::get_date_obj( $date1 );
228
229 if ( ! $date1 ) {
230 return false;
231 }
232
233 $date2 = self::get_date_obj( $date2 );
234
235 return $date2 ? date_diff( $date1, $date2 )->days : false;
236 }
237
238 /**
239 * Gets sent date of the last monthly or yearly email.
240 *
241 * @param string $type Accepts `monthly`, `yearly`.
242 *
243 * @return false|string
244 */
245 public static function get_last_sent_date( $type ) {
246 $options = self::get_options();
247
248 if ( empty( $options[ 'last_' . $type ] ) ) {
249 return false;
250 }
251
252 return $options[ 'last_' . $type ];
253 }
254
255 /**
256 * Sets the last sent date of an email type.
257 *
258 * @param string $type Email type.
259 * @param mixed $value Set custom value. If this is null, set the current date.
260 *
261 * @return void
262 */
263 public static function set_last_sent_date( $type, $value = null ) {
264 $options = self::get_options();
265
266 $options[ 'last_' . $type ] = null === $value ? self::get_date_from_today() : '';
267 self::save_options( $options );
268 }
269
270 /**
271 * Gets the created date of earliest form.
272 *
273 * @return string
274 */
275 private static function get_earliest_form_created_date() {
276 return FrmDb::get_var(
277 'frm_forms',
278 array(),
279 'created_at',
280 array( 'order_by' => 'id ASC' )
281 );
282 }
283
284 /**
285 * Gets payments data.
286 *
287 * @param string $from_date From date.
288 * @param string $to_date To date.
289 *
290 * @return array Contains `count` and `total`.
291 */
292 public static function get_payments_data( $from_date, $to_date ) {
293 $payment = new FrmTransLitePayment();
294 return $payment->get_payments_stats( $from_date, $to_date );
295 }
296
297 /**
298 * Gets entries count in a date range.
299 *
300 * @param string $from_date From date.
301 * @param string $to_date To date.
302 *
303 * @return int
304 */
305 public static function get_entries_count( $from_date, $to_date ) {
306 return FrmDb::get_count(
307 'frm_items',
308 array(
309 // The `=` is added after `>` in the query.
310 'created_at >' => $from_date,
311 'created_at <' => $to_date . ' 23:59:59',
312 'is_draft' => 0,
313 // Do not count repeater entries.
314 'parent_item_id' => 0,
315 )
316 );
317 }
318
319 /**
320 * Gets top forms in a date range.
321 *
322 * @param string $from_date From date.
323 * @param string $to_date To date.
324 * @param int $limit Limit the result. Default is 5.
325 *
326 * @return array Contains `form_id`, `form_name`, and `items_count`.
327 */
328 public static function get_top_forms( $from_date, $to_date, $limit = 5 ) {
329 global $wpdb;
330
331 $result = $wpdb->get_results(
332 $wpdb->prepare(
333 "SELECT fr.id AS form_id, fr.name AS form_name, COUNT(*) as items_count
334 FROM {$wpdb->prefix}frm_items AS it INNER JOIN {$wpdb->prefix}frm_forms AS fr ON it.form_id = fr.id
335 WHERE it.created_at BETWEEN %s AND %s AND it.is_draft = 0 AND parent_form_id = 0
336 GROUP BY form_id ORDER BY items_count DESC LIMIT %d",
337 $from_date,
338 $to_date . ' 23:59:59',
339 intval( $limit )
340 )
341 );
342
343 // Remove slashes from form name.
344 foreach ( $result as &$value ) {
345 $value->form_name = wp_unslash( $value->form_name );
346 }
347
348 return $result;
349 }
350
351 /**
352 * Shows the comparison HTML in the email.
353 *
354 * @param float $diff Percentage of difference.
355 *
356 * @return void
357 */
358 public static function show_comparison( $diff ) {
359 if ( ! $diff ) {
360 return;
361 }
362
363 if ( $diff > 0 ) {
364 $arrow = '&uarr;';
365 $color = '#12b76a';
366 } else {
367 $arrow = '&darr;';
368 $color = '#f04438';
369 }
370
371 $displayed_value = round( $diff * 100 );
372
373 if ( ! $displayed_value ) {
374 // Do not show 0 value.
375 $displayed_value = $diff > 0 ? 1 : -1;
376 }
377
378 printf(
379 '<span style="color: %1$s; font-size: 0.75em; font-weight: 700;">
380 %2$s<span style="display: inline-block; line-height: 1.33;">%3$s</span>
381 </span>',
382 esc_attr( $color ),
383 esc_html( $arrow ),
384 intval( $displayed_value ) . '%'
385 );
386 }
387
388 /**
389 * Gets section CSS in the email.
390 *
391 * @param string $border_pos Border position. Default is `top`. Set to empty if no border.
392 *
393 * @return string
394 */
395 public static function get_section_style( $border_pos = 'top' ) {
396 $border = $border_pos ? 'border-' . $border_pos . ': 1px solid #eaecf0;' : '';
397 return 'padding: 3em 4.375em;' . $border;
398 }
399
400 /**
401 * Gets h2 CSS in the email.
402 *
403 * @return string
404 */
405 public static function get_heading2_style() {
406 return 'font-size: 1.125em; line-height: 1.33em; margin: 0 0 1.33em;';
407 }
408
409 /**
410 * Gets CSS for button.
411 *
412 * @param bool $display_block Whether to display the button as block.
413 *
414 * @return string
415 */
416 public static function get_button_style( $display_block = false ) {
417 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;'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
418 }
419
420 /**
421 * Shows the section heading with icon.
422 *
423 * @param string $icon Icon file name, without file path and extension. Use .png image.
424 * @param string $text Heading text.
425 *
426 * @return void
427 */
428 public static function section_heading_with_icon( $icon, $text ) {
429 ?>
430 <h2 style="<?php echo esc_attr( self::get_heading2_style() ); ?>">
431 <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 ); ?>" /><?php // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong ?>
432 <span style="display: inline-block; vertical-align: text-bottom;"><?php echo esc_html( $text ); ?></span>
433 </h2>
434 <?php
435 }
436
437 /**
438 * Gets Formidable URL with tracking params.
439 *
440 * @param string $url The URL.
441 * @param array|string $args Custom tracking args if is array, or `utm_content` if is string.
442 *
443 * @return string
444 */
445 public static function get_frm_url( $url, $args = array() ) {
446 if ( is_array( $args ) ) {
447 $args = wp_parse_args(
448 $args,
449 array(
450 'medium' => 'summary-email',
451 'content' => 'link',
452 )
453 );
454 } else {
455 $args = array(
456 'medium' => 'summary-email',
457 'content' => $args,
458 );
459 }
460
461 return FrmAppHelper::admin_upgrade_link( $args, $url );
462 }
463
464 /**
465 * Gets the latest inbox message.
466 *
467 * @return array|false
468 */
469 public static function get_latest_inbox_message() {
470 $inbox = new FrmInbox();
471 $messages = $inbox->get_messages( 'filter' );
472
473 if ( ! $messages || ! is_array( $messages ) ) {
474 return false;
475 }
476
477 $messages = array_reverse( $messages );
478
479 foreach ( $messages as $message ) {
480 if ( 'news' !== $message['type'] ) {
481 continue;
482 }
483
484 return $message;
485 }
486
487 return false;
488 }
489
490 /**
491 * Gets out of date plugin names.
492 *
493 * @return array
494 */
495 public static function get_out_of_date_plugins() {
496 $update_data = FrmAddonsController::check_update( '' );
497
498 if ( ! $update_data || ! is_object( $update_data ) || empty( $update_data->response ) ) {
499 return array();
500 }
501
502 $plugins = array();
503
504 foreach ( $update_data->response as $plugin_data ) {
505 $plugins[] = $plugin_data->display_name;
506 }
507
508 return $plugins;
509 }
510
511 /**
512 * Processes inbox CTA button before showing in email.
513 *
514 * @param string $button_html Button HTML. This usually contains 1 button and 1 dismiss button.
515 *
516 * @return string
517 */
518 public static function process_inbox_cta_button( $button_html ) {
519 // Remove dismiss button.
520 $button_html = preg_replace( '/<a[^>]*class="[^"]*\bfrm_inbox_dismiss\b[^"]*"[^>]*>[^<]*<\/a>/', '', $button_html );
521
522 // Replace link utm.
523 $button_html = str_replace( 'utm_medium=inbox', 'utm_medium=summary-email', $button_html );
524
525 if ( str_contains( $button_html, 'style="' ) ) {
526 // Maybe this button contains inline style.
527 return $button_html;
528 }
529
530 // Add inline CSS for specific button types.
531 if ( str_contains( $button_html, 'frm-button-primary' ) ) {
532 return str_replace( '<a', '<a style="' . self::get_button_style() . '"', $button_html );
533 }
534
535 return $button_html;
536 }
537
538 /**
539 * Gets the localized date with the date diff from today.
540 *
541 * @param string $date_diff Date diff string. By default, this is empty, the result will be the current date.
542 *
543 * @return string
544 */
545 public static function get_date_from_today( $date_diff = '' ) {
546 if ( ! $date_diff ) {
547 return FrmAppHelper::get_localized_date( 'Y-m-d', gmdate( 'Y-m-d H:i:s' ) );
548 }
549 return FrmAppHelper::get_localized_date( 'Y-m-d', gmdate( 'Y-m-d H:i:s', strtotime( $date_diff ) ) );
550 }
551
552 /**
553 * Maybe remove recipients from setting from API.
554 *
555 * @since 6.8
556 *
557 * @param string $recipients Recipients.
558 *
559 * @return void
560 */
561 public static function maybe_remove_recipients_from_api( &$recipients ) {
562 $api = new FrmFormApi();
563 $addons = $api->get_api_info();
564
565 if ( empty( $addons['no_emails'] ) ) {
566 return;
567 }
568
569 $skip_emails = is_string( $addons['no_emails'] ) ? explode( ',', $addons['no_emails'] ) : (array) $addons['no_emails'];
570
571 $recipients = array_map( 'trim', explode( ',', $recipients ) );
572 $recipients = array_diff( $recipients, $skip_emails );
573 $recipients = implode( ',', $recipients );
574 }
575
576 /**
577 * Echos string in plain text email.
578 *
579 * @since 6.8
580 *
581 * @param string $string string.
582 *
583 * @return void
584 */
585 public static function plain_text_echo( $string ) {
586 echo wp_strip_all_tags( $string ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
587 }
588 }
589