PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.21
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.21
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 / models / FrmInbox.php

FrmInbox.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.21, at classes/models/FrmInbox.php

538 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * @since 4.05
8 */
9 class FrmInbox extends FrmFormApi {
10
11 protected $cache_key;
12
13 private $option = 'frm_inbox';
14
15 private static $messages = false;
16
17 /**
18 * @var array
19 */
20 private static $banner_messages;
21
22 public function __construct() {
23 $this->set_cache_key();
24
25 if ( false === self::$messages ) {
26 $this->set_messages();
27 }
28 }
29
30 /**
31 * @since 4.05
32 *
33 * @return void
34 */
35 protected function set_cache_key() {
36 $this->cache_key = 'frm_inbox_cache';
37 }
38
39 /**
40 * @since 4.05
41 *
42 * @return string
43 */
44 protected function api_url() {
45 return 'https://formidableforms.com/wp-json/inbox/v1/message/';
46 }
47
48 /**
49 * @since 4.05
50 *
51 * @param array|false $filter
52 */
53 public function get_messages( $filter = false ) {
54 $messages = self::$messages;
55 if ( $filter === 'filter' ) {
56 $this->filter_messages( $messages );
57 }
58 return $messages;
59 }
60
61 /**
62 * @since 4.05
63 *
64 * @return void
65 */
66 public function set_messages() {
67 self::$messages = get_option( $this->option );
68 if ( ! is_array( self::$messages ) ) {
69 self::$messages = array();
70 }
71
72 $this->add_api_messages();
73
74 /**
75 * Messages are in an array.
76 */
77 self::$messages = apply_filters( 'frm_inbox', self::$messages );
78 }
79
80 /**
81 * @since 4.05
82 *
83 * @return void
84 */
85 private function add_api_messages() {
86 $api = $this->get_api_info();
87 if ( empty( $api ) ) {
88 return;
89 }
90
91 foreach ( $api as $message ) {
92 $this->add_message( $message );
93 }
94 }
95
96 /**
97 * @param array|string $message
98 *
99 * @return void
100 */
101 public function add_message( $message ) {
102 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.
105 return;
106 }
107
108 if ( isset( self::$messages[ $message['key'] ] ) && ! isset( $message['force'] ) ) {
109 // Don't replace messages unless required.
110 return;
111 }
112
113 if ( $this->is_expired( $message ) ) {
114 return;
115 }
116
117 if ( isset( self::$messages[ $message['key'] ] ) ) {
118 // Move up and mark as new.
119 unset( self::$messages[ $message['key'] ] );
120 }
121
122 $this->fill_message( $message );
123 self::$messages[ $message['key'] ] = $message;
124
125 $this->update_list();
126
127 $this->clean_messages();
128 }
129
130 /**
131 * @param array $message
132 *
133 * @return void
134 */
135 private function fill_message( &$message ) {
136 $defaults = array(
137 'time' => time(),
138 'message' => '',
139 'subject' => '',
140 'icon' => 'frm_tooltip_icon',
141 'cta' => '',
142 'expires' => false,
143 // Use 'free', 'personal', 'business', 'elite', 'grandfathered'.
144 'who' => 'all',
145 'type' => '',
146 );
147
148 $message = array_merge( $defaults, $message );
149
150 $message['created'] = $message['time'];
151 unset( $message['time'] );
152 }
153
154 /**
155 * @return void
156 */
157 private function clean_messages() {
158 $removed = false;
159 foreach ( self::$messages as $t => $message ) {
160 $read = ! empty( $message['read'] ) && isset( $message['read'][ get_current_user_id() ] ) && $message['read'][ get_current_user_id() ] < strtotime( '-1 month' );
161 $dismissed = ! empty( $message['dismissed'] ) && isset( $message['dismissed'][ get_current_user_id() ] ) && $message['dismissed'][ get_current_user_id() ] < strtotime( '-1 week' );
162 $expired = $this->is_expired( $message );
163 if ( $read || $expired || $dismissed ) {
164 unset( self::$messages[ $t ] );
165 $removed = true;
166 }
167 }
168
169 if ( $removed ) {
170 $this->update_list();
171 }
172 }
173
174 /**
175 * @param array $messages
176 * @param string $type
177 * @return void
178 */
179 public function filter_messages( &$messages, $type = 'unread' ) {
180 $user_id = get_current_user_id();
181 foreach ( $messages as $k => $message ) {
182 $dismissed = isset( $message['dismissed'] ) && isset( $message['dismissed'][ $user_id ] );
183 if ( empty( $k ) || $this->is_expired( $message ) || ( $type === 'dismissed' ) !== $dismissed ) {
184 unset( $messages[ $k ] );
185 } elseif ( ! $this->is_for_user( $message ) ) {
186 unset( $messages[ $k ] );
187 }
188 }
189 $messages = apply_filters( 'frm_filter_inbox', $messages );
190 }
191
192 /**
193 * @param array $message
194 *
195 * @return bool
196 */
197 private function is_expired( $message ) {
198 return ! empty( $message['expires'] ) && $message['expires'] < time();
199 }
200
201 /**
202 * Show different messages for different accounts.
203 *
204 * @param array $message
205 * @return bool
206 */
207 private function is_for_user( $message ) {
208 if ( FrmApiHelper::is_for_user( $message ) ) {
209 return true;
210 }
211
212 $who = (array) $message['who'];
213
214 /**
215 * Allow for other special inbox cases in other add-ons.
216 *
217 * @since 6.8.1
218 *
219 * @param bool $is_for_user
220 * @param array $who
221 * @param array $message
222 */
223 return (bool) apply_filters( 'frm_inbox_message_is_for_user', false, $who, $message );
224 }
225
226 /**
227 * @param string $key
228 *
229 * @return void
230 */
231 public function mark_read( $key ) {
232 if ( ! $key || ! isset( self::$messages[ $key ] ) ) {
233 return;
234 }
235
236 if ( ! isset( self::$messages[ $key ]['read'] ) ) {
237 self::$messages[ $key ]['read'] = array();
238 }
239 self::$messages[ $key ]['read'][ get_current_user_id() ] = time();
240
241 $this->update_list();
242 }
243
244 /**
245 * @since 4.05.02
246 *
247 * @param string $key
248 * @return void
249 */
250 public function mark_unread( $key ) {
251 $is_read = isset( self::$messages[ $key ] ) && isset( self::$messages[ $key ]['read'] ) && isset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
252 if ( $is_read ) {
253 unset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
254 $this->update_list();
255 }
256 }
257
258 /**
259 * @param string $key
260 *
261 * @return void
262 */
263 public function dismiss( $key ) {
264 if ( $key === 'all' ) {
265 $this->dismiss_all();
266 return;
267 }
268
269 if ( ! isset( self::$messages[ $key ] ) ) {
270 return;
271 }
272
273 if ( ! isset( self::$messages[ $key ]['dismissed'] ) ) {
274 self::$messages[ $key ]['dismissed'] = array();
275 }
276 self::$messages[ $key ]['dismissed'][ get_current_user_id() ] = time();
277
278 $this->update_list();
279 }
280
281 /**
282 * @since 4.06
283 *
284 * @return void
285 */
286 private function dismiss_all() {
287 $user_id = get_current_user_id();
288 foreach ( self::$messages as $key => $message ) {
289 if ( ! isset( $message['dismissed'] ) ) {
290 self::$messages[ $key ]['dismissed'] = array();
291 }
292
293 if ( ! isset( $message['dismissed'][ $user_id ] ) ) {
294 self::$messages[ $key ]['dismissed'][ $user_id ] = time();
295 }
296 }
297 $this->update_list();
298 }
299
300 public function unread() {
301 $messages = $this->get_messages( 'filter' );
302 $user_id = get_current_user_id();
303 foreach ( $messages as $t => $message ) {
304 if ( isset( $message['read'] ) && isset( $message['read'][ $user_id ] ) ) {
305 unset( $messages[ $t ] );
306 }
307 }
308 return $messages;
309 }
310
311 /**
312 * @since 6.8.4 The $filtered parameter was added.
313 *
314 * @param bool $filtered
315 * @return string
316 */
317 public function unread_html( $filtered = true ) {
318 $count = count( $this->unread() );
319 if ( ! $count ) {
320 return '';
321 }
322
323 $html = ' <span class="update-plugins frm_inbox_count"><span class="plugin-count">' . absint( $count ) . '</span></span>';
324
325 if ( ! $filtered ) {
326 return $html;
327 }
328
329 /**
330 * @since 4.06.01
331 *
332 * @param string $html
333 */
334 return (string) apply_filters( 'frm_inbox_badge', $html );
335 }
336
337 /**
338 * @since 4.05.02
339 *
340 * @param string $key
341 * @return void
342 */
343 public function remove( $key ) {
344 if ( isset( self::$messages[ $key ] ) ) {
345 unset( self::$messages[ $key ] );
346 $this->update_list();
347 }
348 }
349
350 /**
351 * @return void
352 */
353 private function update_list() {
354 update_option( $this->option, self::$messages, 'no' );
355 }
356
357 /**
358 * Show a banner message if one is available.
359 *
360 * @return bool True if a banner is available and shown.
361 */
362 public static function maybe_show_banner() {
363 if ( empty( self::$banner_messages ) ) {
364 return false;
365 }
366 $message = end( self::$banner_messages );
367 $cta = self::get_prepared_banner_cta( $message['cta'] );
368
369 require FrmAppHelper::plugin_path() . '/classes/views/inbox/banner.php';
370 return true;
371 }
372
373 /**
374 * Make sure that the CTA uses utm_medium=banner.
375 *
376 * @since 6.8.4
377 *
378 * @param string $cta
379 * @return string
380 */
381 private static function get_prepared_banner_cta( $cta ) {
382 $cta = str_replace( 'button-secondary', 'button-primary', $cta );
383 return preg_replace_callback(
384 '/href=("|\')(.*?)("|\')/',
385 /**
386 * Replace a single href attribute in the CTA.
387 *
388 * @param array $matches The regex results for a single match.
389 * @return string
390 */
391 function ( $matches ) {
392 $url = $matches[2];
393 $parts = parse_url( $url );
394
395 if ( '#' === $url ) {
396 return 'href="#"';
397 }
398
399 $query = array();
400 if ( isset( $parts['query'] ) ) {
401 parse_str( $parts['query'], $query );
402 }
403 $query['utm_medium'] = 'banner';
404 $parts['query'] = http_build_query( $query );
405 return 'href="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '?' . $parts['query'] . '"';
406 },
407 $cta
408 );
409 }
410
411 /**
412 * @return void
413 */
414 public static function maybe_disable_screen_options() {
415 self::$banner_messages = self::get_banner_messages();
416 if ( self::$banner_messages ) {
417 // disable screen options tab when displaying banner messages because it gets in the way of the banner.
418 add_filter( 'screen_options_show_screen', '__return_false' );
419 }
420 }
421
422 /**
423 * Get all message with a "banner" message key defined.
424 *
425 * @return array
426 */
427 private static function get_banner_messages() {
428 return self::get_messages_with_key( 'banner' );
429 }
430
431 /**
432 * Get all messages with a "slidein" message key defined.
433 *
434 * @since 6.8.4
435 *
436 * @return array
437 */
438 private static function get_slidein_messages() {
439 return self::get_messages_with_key( 'slidein' );
440 }
441
442 /**
443 * Get all messages with a $key message key defined.
444 *
445 * @since 6.8.4
446 *
447 * @param string $key The key we are checking for (ie. banner or slidein).
448 * @return array
449 */
450 private static function get_messages_with_key( $key ) {
451 $inbox = new self();
452 return array_filter(
453 $inbox->get_messages( 'filter' ),
454 function ( $message ) use ( $key ) {
455 return ! empty( $message[ $key ] );
456 }
457 );
458 }
459
460 /**
461 * Check if there is at least one slidein message.
462 *
463 * @since 6.8.4
464 *
465 * @return bool
466 */
467 public static function has_a_slidein_message() {
468 return (bool) self::get_slidein_messages();
469 }
470
471 /**
472 * Get the array used for frmGlobal.inboxSlideIn
473 *
474 * @since 6.8.4
475 *
476 * @return array|false
477 */
478 public static function get_inbox_slide_in_value_for_js() {
479 $messages = self::get_slidein_messages();
480 if ( ! $messages ) {
481 return false;
482 }
483
484 $message = reset( $messages );
485
486 /**
487 * Extend the keys in the global JS object.
488 * This is used in Pro to include images.
489 *
490 * @since 6.8.4
491 *
492 * @param array $keys
493 */
494 $keys_to_return = apply_filters(
495 'frm_inbox_slidein_js_vars',
496 array( 'key', 'slidein', 'subject', 'cta' )
497 );
498
499 return array_reduce(
500 $keys_to_return,
501 function ( $total, $key ) use ( $message ) {
502 $total[ $key ] = isset( $message[ $key ] ) ? $message[ $key ] : '';
503 return $total;
504 },
505 array()
506 );
507 }
508
509 /**
510 * Clear the inbox cache by deleting the associated option from the database.
511 *
512 * @since 6.17
513 *
514 * @return void
515 */
516 public static function clear_cache() {
517 delete_option( 'frm_inbox' );
518 }
519
520 /**
521 * Check inbox for an "error" type. This is displayed on the form list page if one exists.
522 *
523 * @since 6.19
524 *
525 * @return array|false
526 */
527 public static function check_for_error() {
528 $inbox = new self();
529 $messages = $inbox->get_messages( 'filter' );
530 foreach ( $messages as $message ) {
531 if ( is_array( $message ) && isset( $message['type'] ) && 'error' === $message['type'] ) {
532 return $message;
533 }
534 }
535 return false;
536 }
537 }
538