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

521 lines 11.4 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( $for_parent = null ) {
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 ( ! isset( $message['who'] ) || $message['who'] === 'all' ) {
209 return true;
210 }
211 $who = (array) $message['who'];
212 if ( in_array( 'all', $who, true ) || in_array( 'everyone', $who, true ) ) {
213 return true;
214 }
215 if ( in_array( $this->get_user_type(), $who, true ) ) {
216 return true;
217 }
218 /**
219 * Allow for other special inbox cases in other add-ons.
220 *
221 * @since 6.8.1
222 *
223 * @param bool $is_for_user
224 * @param array $who
225 * @param array $message
226 */
227 return (bool) apply_filters( 'frm_inbox_message_is_for_user', false, $who, $message );
228 }
229
230 private function get_user_type() {
231 if ( ! FrmAppHelper::pro_is_installed() ) {
232 return 'free';
233 }
234
235 return FrmAddonsController::license_type();
236 }
237
238 /**
239 * @param string $key
240 *
241 * @return void
242 */
243 public function mark_read( $key ) {
244 if ( ! $key || ! isset( self::$messages[ $key ] ) ) {
245 return;
246 }
247
248 if ( ! isset( self::$messages[ $key ]['read'] ) ) {
249 self::$messages[ $key ]['read'] = array();
250 }
251 self::$messages[ $key ]['read'][ get_current_user_id() ] = time();
252
253 $this->update_list();
254 }
255
256 /**
257 * @since 4.05.02
258 *
259 * @param string $key
260 * @return void
261 */
262 public function mark_unread( $key ) {
263 $is_read = isset( self::$messages[ $key ] ) && isset( self::$messages[ $key ]['read'] ) && isset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
264 if ( $is_read ) {
265 unset( self::$messages[ $key ]['read'][ get_current_user_id() ] );
266 $this->update_list();
267 }
268 }
269
270 /**
271 * @param string $key
272 *
273 * @return void
274 */
275 public function dismiss( $key ) {
276 if ( $key === 'all' ) {
277 $this->dismiss_all();
278 return;
279 }
280
281 if ( ! isset( self::$messages[ $key ] ) ) {
282 return;
283 }
284
285 if ( ! isset( self::$messages[ $key ]['dismissed'] ) ) {
286 self::$messages[ $key ]['dismissed'] = array();
287 }
288 self::$messages[ $key ]['dismissed'][ get_current_user_id() ] = time();
289
290 $this->update_list();
291 }
292
293 /**
294 * @since 4.06
295 *
296 * @return void
297 */
298 private function dismiss_all() {
299 $user_id = get_current_user_id();
300 foreach ( self::$messages as $key => $message ) {
301 if ( ! isset( $message['dismissed'] ) ) {
302 self::$messages[ $key ]['dismissed'] = array();
303 }
304
305 if ( ! isset( $message['dismissed'][ $user_id ] ) ) {
306 self::$messages[ $key ]['dismissed'][ $user_id ] = time();
307 }
308 }
309 $this->update_list();
310 }
311
312 public function unread() {
313 $messages = $this->get_messages( 'filter' );
314 $user_id = get_current_user_id();
315 foreach ( $messages as $t => $message ) {
316 if ( isset( $message['read'] ) && isset( $message['read'][ $user_id ] ) ) {
317 unset( $messages[ $t ] );
318 }
319 }
320 return $messages;
321 }
322
323 /**
324 * @since 6.8.4 The $filtered parameter was added.
325 *
326 * @param bool $filtered
327 * @return string
328 */
329 public function unread_html( $filtered = true ) {
330 $count = count( $this->unread() );
331 if ( ! $count ) {
332 return '';
333 }
334
335 $html = ' <span class="update-plugins frm_inbox_count"><span class="plugin-count">' . absint( $count ) . '</span></span>';
336
337 if ( ! $filtered ) {
338 return $html;
339 }
340
341 /**
342 * @since 4.06.01
343 *
344 * @param string $html
345 */
346 return (string) apply_filters( 'frm_inbox_badge', $html );
347 }
348
349 /**
350 * @since 4.05.02
351 *
352 * @param string $key
353 * @return void
354 */
355 public function remove( $key ) {
356 if ( isset( self::$messages[ $key ] ) ) {
357 unset( self::$messages[ $key ] );
358 $this->update_list();
359 }
360 }
361
362 /**
363 * @return void
364 */
365 private function update_list() {
366 update_option( $this->option, self::$messages, 'no' );
367 }
368
369 /**
370 * Show a banner message if one is available.
371 *
372 * @return bool True if a banner is available and shown.
373 */
374 public static function maybe_show_banner() {
375 if ( empty( self::$banner_messages ) ) {
376 return false;
377 }
378 $message = end( self::$banner_messages );
379 $cta = self::get_prepared_banner_cta( $message['cta'] );
380
381 require FrmAppHelper::plugin_path() . '/classes/views/inbox/banner.php';
382 return true;
383 }
384
385 /**
386 * Make sure that the CTA uses utm_medium=banner.
387 *
388 * @since 6.8.4
389 *
390 * @param string $cta
391 * @return string
392 */
393 private static function get_prepared_banner_cta( $cta ) {
394 $cta = str_replace( 'button-secondary', 'button-primary', $cta );
395 return preg_replace_callback(
396 '/href=("|\')(.*?)("|\')/',
397 /**
398 * Replace a single href attribute in the CTA.
399 *
400 * @param array $matches The regex results for a single match.
401 * @return string
402 */
403 function ( $matches ) {
404 $url = $matches[2];
405 $parts = parse_url( $url );
406
407 if ( '#' === $url ) {
408 return 'href="#"';
409 }
410
411 $query = array();
412 if ( isset( $parts['query'] ) ) {
413 parse_str( $parts['query'], $query );
414 }
415 $query['utm_medium'] = 'banner';
416 $parts['query'] = http_build_query( $query );
417 return 'href="' . $parts['scheme'] . '://' . $parts['host'] . $parts['path'] . '?' . $parts['query'] . '"';
418 },
419 $cta
420 );
421 }
422
423 /**
424 * @return void
425 */
426 public static function maybe_disable_screen_options() {
427 self::$banner_messages = self::get_banner_messages();
428 if ( self::$banner_messages ) {
429 // disable screen options tab when displaying banner messages because it gets in the way of the banner.
430 add_filter( 'screen_options_show_screen', '__return_false' );
431 }
432 }
433
434 /**
435 * Get all message with a "banner" message key defined.
436 *
437 * @return array
438 */
439 private static function get_banner_messages() {
440 return self::get_messages_with_key( 'banner' );
441 }
442
443 /**
444 * Get all messages with a "slidein" message key defined.
445 *
446 * @since 6.8.4
447 *
448 * @return array
449 */
450 private static function get_slidein_messages() {
451 return self::get_messages_with_key( 'slidein' );
452 }
453
454 /**
455 * Get all messages with a $key message key defined.
456 *
457 * @since 6.8.4
458 *
459 * @param string $key The key we are checking for (ie. banner or slidein).
460 * @return array
461 */
462 private static function get_messages_with_key( $key ) {
463 $inbox = new self();
464 return array_filter(
465 $inbox->get_messages( 'filter' ),
466 function ( $message ) use ( $key ) {
467 return ! empty( $message[ $key ] );
468 }
469 );
470 }
471
472 /**
473 * Check if there is at least one slidein message.
474 *
475 * @since 6.8.4
476 *
477 * @return bool
478 */
479 public static function has_a_slidein_message() {
480 return (bool) self::get_slidein_messages();
481 }
482
483 /**
484 * Get the array used for frmGlobal.inboxSlideIn
485 *
486 * @since 6.8.4
487 *
488 * @return array|false
489 */
490 public static function get_inbox_slide_in_value_for_js() {
491 $messages = self::get_slidein_messages();
492 if ( ! $messages ) {
493 return false;
494 }
495
496 $message = reset( $messages );
497
498 /**
499 * Extend the keys in the global JS object.
500 * This is used in Pro to include images.
501 *
502 * @since 6.8.4
503 *
504 * @param array $keys
505 */
506 $keys_to_return = apply_filters(
507 'frm_inbox_slidein_js_vars',
508 array( 'key', 'slidein', 'subject', 'cta' )
509 );
510
511 return array_reduce(
512 $keys_to_return,
513 function ( $total, $key ) use ( $message ) {
514 $total[ $key ] = isset( $message[ $key ] ) ? $message[ $key ] : '';
515 return $total;
516 },
517 array()
518 );
519 }
520 }
521