PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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
← All changes | classes/models/FrmInbox.php +277 -50 6.4.1 → trunk View file →
@@ -9,18 +9,24 @@
9 9 class FrmInbox extends FrmFormApi {
10 10
11 11 protected $cache_key;
12 12
13 + /**
14 + * @var string
15 + */
13 16 private $option = 'frm_inbox';
14 17
18 + /**
19 + * @var array|false
20 + */
15 21 private static $messages = false;
16 22
17 23 /**
18 - * @param array
24 + * @var array
19 25 */
20 26 private static $banner_messages;
21 27
22 - public function __construct( $for_parent = null ) {
28 + public function __construct() {
23 29 $this->set_cache_key();
24 30
25 31 if ( false === self::$messages ) {
26 32 $this->set_messages();
@@ -48,14 +54,18 @@
48 54 /**
49 55 * @since 4.05
50 56 *
51 57 * @param false|string $filter
58 + *
59 + * @return array
52 60 */
53 61 public function get_messages( $filter = false ) {
54 62 $messages = self::$messages;
63 +
55 64 if ( $filter === 'filter' ) {
56 65 $this->filter_messages( $messages );
57 66 }
67 +
58 68 return $messages;
59 69 }
60 70
61 71 /**
@@ -64,8 +74,9 @@
64 74 * @return void
65 75 */
66 76 public function set_messages() {
67 77 self::$messages = get_option( $this->option );
78 +
68 79 if ( ! is_array( self::$messages ) ) {
69 80 self::$messages = array();
70 81 }
71 82
@@ -83,9 +94,10 @@
83 94 * @return void
84 95 */
85 96 private function add_api_messages() {
86 97 $api = $this->get_api_info();
87 - if ( empty( $api ) ) {
98 +
99 + if ( ! $api ) {
88 100 return;
89 101 }
90 102
91 103 foreach ( $api as $message ) {
@@ -99,10 +111,10 @@
99 111 * @return void
100 112 */
101 113 public function add_message( $message ) {
102 114 if ( ! is_array( $message ) || ! isset( $message['key'] ) ) {
103 - // if the API response is invalid, $message may not be an array.
104 - // if there are no messages from the API, it is returning a "No Entries Found" item with no key, so check for a key as well.
115 + // If the API response is invalid, $message may not be an array.
116 + // If there are no messages from the API, it is returning a "No Entries Found" item with no key, so check for a key as well.
105 117 return;
106 118 }
107 119
108 120 if ( isset( self::$messages[ $message['key'] ] ) && ! isset( $message['force'] ) ) {
@@ -109,9 +121,9 @@
109 121 // Don't replace messages unless required.
110 122 return;
111 123 }
112 124
113 - if ( $this->is_expired( $message ) ) {
125 + if ( ! $this->within_valid_timeframe( $message ) ) {
114 126 return;
115 127 }
116 128
117 129 if ( isset( self::$messages[ $message['key'] ] ) ) {
@@ -139,9 +151,10 @@
139 151 'subject' => '',
140 152 'icon' => 'frm_tooltip_icon',
141 153 'cta' => '',
142 154 'expires' => false,
143 - 'who' => 'all', // use 'free', 'personal', 'business', 'elite', 'grandfathered'
155 + // Use 'free', 'personal', 'business', 'elite', 'grandfathered'.
156 + 'who' => 'all',
144 157 'type' => '',
145 158 );
146 159
147 160 $message = array_merge( $defaults, $message );
@@ -154,16 +167,19 @@
154 167 * @return void
155 168 */
156 169 private function clean_messages() {
157 170 $removed = false;
171 +
158 172 foreach ( self::$messages as $t => $message ) {
159 - $read = isset( $message['read'] ) && ! empty( $message['read'] ) && isset( $message['read'][ get_current_user_id() ] ) && $message['read'][ get_current_user_id() ] < strtotime( '-1 month' );
160 - $dismissed = isset( $message['dismissed'] ) && ! empty( $message['dismissed'] ) && isset( $message['dismissed'][ get_current_user_id() ] ) && $message['dismissed'][ get_current_user_id() ] < strtotime( '-1 week' );
161 - $expired = $this->is_expired( $message );
162 - if ( $read || $expired || $dismissed ) {
163 - unset( self::$messages[ $t ] );
164 - $removed = true;
173 + $read = ! empty( $message['read'] ) && isset( $message['read'][ get_current_user_id() ] ) && $message['read'][ get_current_user_id() ] < strtotime( '-1 month' );
174 + $dismissed = ! empty( $message['dismissed'] ) && isset( $message['dismissed'][ get_current_user_id() ] ) && $message['dismissed'][ get_current_user_id() ] < strtotime( '-1 week' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
175 +
176 + if ( ! $read && ! $dismissed && $this->within_valid_timeframe( $message ) ) {
177 + continue;
165 178 }
179 +
180 + unset( self::$messages[ $t ] );
181 + $removed = true;
166 182 }
167 183
168 184 if ( $removed ) {
169 185 $this->update_list();
@@ -170,30 +186,62 @@
170 186 }
171 187 }
172 188
173 189 /**
190 + * @param array $messages
191 + * @param string $type
192 + *
174 193 * @return void
175 194 */
176 - private function filter_messages( &$messages ) {
195 + public function filter_messages( &$messages, $type = 'unread' ) {
177 196 $user_id = get_current_user_id();
197 +
178 198 foreach ( $messages as $k => $message ) {
179 199 $dismissed = isset( $message['dismissed'] ) && isset( $message['dismissed'][ $user_id ] );
180 - if ( empty( $k ) || $this->is_expired( $message ) || $dismissed ) {
200 +
201 + if ( ! $k || ! $this->within_valid_timeframe( $message ) || ( $type === 'dismissed' ) !== $dismissed ) {
181 202 unset( $messages[ $k ] );
182 203 } elseif ( ! $this->is_for_user( $message ) ) {
183 204 unset( $messages[ $k ] );
184 205 }
185 206 }
207 +
186 208 $messages = apply_filters( 'frm_filter_inbox', $messages );
187 209 }
188 210
189 211 /**
212 + * Check if a message has started and is not expired.
213 + *
214 + * @since 6.25
215 + *
190 216 * @param array $message
191 217 *
192 218 * @return bool
193 219 */
220 + private function within_valid_timeframe( $message ) {
221 + return $this->has_started( $message ) && ! $this->is_expired( $message );
222 + }
223 +
224 + /**
225 + * Check if a message has actually started, so we can prevent showing something that is queued up early.
226 + *
227 + * @since 6.25
228 + *
229 + * @param array $message
230 + *
231 + * @return bool
232 + */
233 + private function has_started( $message ) {
234 + return ! empty( $message['starts'] ) ? $message['starts'] <= time() : true;
235 + }
236 +
237 + /**
238 + * @param array $message
239 + *
240 + * @return bool
241 + */
194 242 private function is_expired( $message ) {
195 - return isset( $message['expires'] ) && ! empty( $message['expires'] ) && $message['expires'] < time();
243 + return ! empty( $message['expires'] ) && $message['expires'] < time();
196 244 }
197 245
198 246 /**
199 247 * Show different messages for different accounts.
@@ -198,27 +246,28 @@
198 246 /**
199 247 * Show different messages for different accounts.
200 248 *
201 249 * @param array $message
250 + *
202 251 * @return bool
203 252 */
204 253 private function is_for_user( $message ) {
205 - if ( ! isset( $message['who'] ) || $message['who'] === 'all' ) {
254 + if ( FrmApiHelper::is_for_user( $message ) ) {
206 255 return true;
207 256 }
257 +
208 258 $who = (array) $message['who'];
209 - if ( in_array( 'all', $who, true ) || in_array( 'everyone', $who, true ) ) {
210 - return true;
211 - }
212 - return in_array( $this->get_user_type(), $who, true );
213 - }
214 259
215 - private function get_user_type() {
216 - if ( ! FrmAppHelper::pro_is_installed() ) {
217 - return 'free';
218 - }
219 -
220 - return FrmAddonsController::license_type();
260 + /**
261 + * Allow for other special inbox cases in other add-ons.
262 + *
263 + * @since 6.8.1
264 + *
265 + * @param bool $is_for_user
266 + * @param array $who
267 + * @param array $message
268 + */
269 + return (bool) apply_filters( 'frm_inbox_message_is_for_user', false, $who, $message );
221 270 }
222 271
223 272 /**
224 273 * @param string $key
@@ -238,20 +287,23 @@
238 287 $this->update_list();
239 288 }
240 289
241 290 /**
291 + * @since 4.05.02
292 + *
242 293 * @param string $key
243 294 *
244 - * @since 4.05.02
245 - *
246 295 * @return void
247 296 */
248 297 public function mark_unread( $key ) {
249 298 $is_read = isset( self::$messages[ $key ] ) && isset( self::$messages[ $key ]['read'] ) && isset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
250 - if ( $is_read ) {
251 - unset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
252 - $this->update_list();
299 +
300 + if ( ! $is_read ) {
301 + return;
253 302 }
303 +
304 + unset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
305 + $this->update_list();
254 306 }
255 307
256 308 /**
257 309 * @param string $key
@@ -282,8 +334,9 @@
282 334 * @return void
283 335 */
284 336 private function dismiss_all() {
285 337 $user_id = get_current_user_id();
338 +
286 339 foreach ( self::$messages as $key => $message ) {
287 340 if ( ! isset( $message['dismissed'] ) ) {
288 341 self::$messages[ $key ]['dismissed'] = array();
289 342 }
@@ -294,31 +347,50 @@
294 347 }
295 348 $this->update_list();
296 349 }
297 350
351 + /**
352 + * @return array
353 + */
298 354 public function unread() {
299 355 $messages = $this->get_messages( 'filter' );
300 356 $user_id = get_current_user_id();
357 +
301 358 foreach ( $messages as $t => $message ) {
302 359 if ( isset( $message['read'] ) && isset( $message['read'][ $user_id ] ) ) {
303 360 unset( $messages[ $t ] );
304 361 }
305 362 }
363 +
306 364 return $messages;
307 365 }
308 366
309 - public function unread_html() {
310 - $html = '';
367 + /**
368 + * @since 6.8.4 The $filtered parameter was added.
369 + *
370 + * @param bool $filtered
371 + *
372 + * @return string
373 + */
374 + public function unread_html( $filtered = true ) {
311 375 $count = count( $this->unread() );
312 - if ( $count ) {
313 - $html = ' <span class="update-plugins frm_inbox_count"><span class="plugin-count">' . absint( $count ) . '</span></span>';
314 376
315 - /**
316 - * @since 4.06.01
317 - */
318 - $html = apply_filters( 'frm_inbox_badge', $html );
377 + if ( ! $count ) {
378 + return '';
319 379 }
320 - return $html;
380 +
381 + $html = ' <span class="update-plugins frm_inbox_count"><span class="plugin-count">' . absint( $count ) . '</span></span>';
382 +
383 + if ( ! $filtered ) {
384 + return $html;
385 + }
386 +
387 + /**
388 + * @since 4.06.01
389 + *
390 + * @param string $html
391 + */
392 + return (string) apply_filters( 'frm_inbox_badge', $html );
321 393 }
322 394
323 395 /**
324 396 * @since 4.05.02
@@ -327,12 +399,14 @@
327 399 *
328 400 * @return void
329 401 */
330 402 public function remove( $key ) {
331 - if ( isset( self::$messages[ $key ] ) ) {
332 - unset( self::$messages[ $key ] );
333 - $this->update_list();
403 + if ( ! isset( self::$messages[ $key ] ) ) {
404 + return;
334 405 }
406 +
407 + unset( self::$messages[ $key ] );
408 + $this->update_list();
335 409 }
336 410
337 411 /**
338 412 * @return void
@@ -337,9 +411,9 @@
337 411 /**
338 412 * @return void
339 413 */
340 414 private function update_list() {
341 - update_option( $this->option, self::$messages, 'no' );
415 + update_option( $this->option, self::$messages, false );
342 416 }
343 417
344 418 /**
345 419 * Show a banner message if one is available.
@@ -346,36 +420,189 @@
346 420 *
347 421 * @return bool True if a banner is available and shown.
348 422 */
349 423 public static function maybe_show_banner() {
350 - if ( empty( self::$banner_messages ) ) {
424 + if ( ! self::$banner_messages ) {
351 425 return false;
352 426 }
427 +
353 428 $message = end( self::$banner_messages );
429 + $cta = self::get_prepared_banner_cta( $message['cta'] );
430 +
354 431 require FrmAppHelper::plugin_path() . '/classes/views/inbox/banner.php';
355 432 return true;
356 433 }
357 434
358 435 /**
436 + * Make sure that the CTA uses utm_medium=banner.
437 + *
438 + * @since 6.8.4
439 + *
440 + * @param string $cta
441 + *
442 + * @return string
443 + */
444 + private static function get_prepared_banner_cta( $cta ) {
445 + $cta = str_replace( 'button-secondary', 'button-primary', $cta );
446 + return preg_replace_callback(
447 + '/href=("|\')(.*?)("|\')/',
448 + /**
449 + * Replace a single href attribute in the CTA.
450 + *
451 + * @param array $matches The regex results for a single match.
452 + *
453 + * @return string
454 + */
455 + function ( $matches ) {
456 + $url = $matches[2];
457 +
458 + if ( '#' === $url ) {
459 + return 'href="#"';
460 + }
461 +
462 + $parts = parse_url( $url );
463 + $query = array();
464 +
465 + if ( isset( $parts['query'] ) ) {
466 + parse_str( $parts['query'], $query );
467 + }
468 +
469 + $query['utm_medium'] = 'banner';
470 + $parts['query'] = http_build_query( $query );
471 + return 'href="' . esc_url( $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '?' . $parts['query'] ) . '"';
472 + },
473 + $cta
474 + );
475 + }
476 +
477 + /**
359 478 * @return void
360 479 */
361 480 public static function maybe_disable_screen_options() {
362 481 self::$banner_messages = self::get_banner_messages();
482 +
363 483 if ( self::$banner_messages ) {
364 - // disable screen options tab when displaying banner messages because it gets in the way of the banner.
484 + // Disable screen options tab when displaying banner messages because it gets in the way of the banner.
365 485 add_filter( 'screen_options_show_screen', '__return_false' );
366 486 }
367 487 }
368 488
369 489 /**
490 + * Get all message with a "banner" message key defined.
491 + *
370 492 * @return array
371 493 */
372 494 private static function get_banner_messages() {
495 + return self::get_messages_with_key( 'banner' );
496 + }
497 +
498 + /**
499 + * Get all messages with a "slidein" message key defined.
500 + *
501 + * @since 6.8.4
502 + *
503 + * @return array
504 + */
505 + private static function get_slidein_messages() {
506 + return self::get_messages_with_key( 'slidein' );
507 + }
508 +
509 + /**
510 + * Get all messages with a $key message key defined.
511 + *
512 + * @since 6.8.4
513 + *
514 + * @param string $key The key we are checking for (ie. banner or slidein).
515 + *
516 + * @return array
517 + */
518 + private static function get_messages_with_key( $key ) {
373 519 $inbox = new self();
374 520 return array_filter(
375 521 $inbox->get_messages( 'filter' ),
376 - function( $message ) {
377 - return ! empty( $message['banner'] );
522 + function ( $message ) use ( $key ) {
523 + return ! empty( $message[ $key ] );
378 524 }
379 525 );
526 + }
527 +
528 + /**
529 + * Check if there is at least one slidein message.
530 + *
531 + * @since 6.8.4
532 + *
533 + * @return bool
534 + */
535 + public static function has_a_slidein_message() {
536 + return (bool) self::get_slidein_messages();
537 + }
538 +
539 + /**
540 + * Get the array used for frmGlobal.inboxSlideIn
541 + *
542 + * @since 6.8.4
543 + *
544 + * @return array|false
545 + */
546 + public static function get_inbox_slide_in_value_for_js() {
547 + $messages = self::get_slidein_messages();
548 +
549 + if ( ! $messages ) {
550 + return false;
551 + }
552 +
553 + $message = reset( $messages );
554 +
555 + /**
556 + * Extend the keys in the global JS object.
557 + * This is used in Pro to include images.
558 + *
559 + * @since 6.8.4
560 + *
561 + * @param array $keys
562 + */
563 + $keys_to_return = apply_filters(
564 + 'frm_inbox_slidein_js_vars',
565 + array( 'key', 'slidein', 'subject', 'cta' )
566 + );
567 +
568 + return array_reduce(
569 + $keys_to_return,
570 + function ( $total, $key ) use ( $message ) {
571 + $total[ $key ] = $message[ $key ] ?? '';
572 + return $total;
573 + },
574 + array()
575 + );
576 + }
577 +
578 + /**
579 + * Clear the inbox cache by deleting the associated option from the database.
580 + *
581 + * @since 6.17
582 + *
583 + * @return void
584 + */
585 + public static function clear_cache() {
586 + delete_option( 'frm_inbox' );
587 + }
588 +
589 + /**
590 + * Check inbox for an "error" type. This is displayed on the form list page if one exists.
591 + *
592 + * @since 6.19
593 + *
594 + * @return array|false
595 + */
596 + public static function check_for_error() {
597 + $inbox = new self();
598 + $messages = $inbox->get_messages( 'filter' );
599 +
600 + foreach ( $messages as $message ) {
601 + if ( is_array( $message ) && isset( $message['type'] ) && 'error' === $message['type'] ) {
602 + return $message;
603 + }
604 + }
605 +
606 + return false;
380 607 }
381 608 }