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

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