PluginProbe ʕ •ᴥ•ʔ
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress / 4.1.2
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress v4.1.2
4.8.1 trunk 1.0 1.1 1.12.1 1.2.3 1.2.4 1.2.5 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5 1.5.1 1.5.2 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.5.1 1.6.6 1.6.6.1 1.6.6.2 1.6.6.3 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.9.0 1.9.1 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.8.1 1.9.9 1.9.9.1 1.9.9.2 1.9.9.3 2.0 2.0.1 2.1 2.1.1 2.1.2 2.1.3 2.10 2.11 2.11.1 2.12 2.12.1 2.12.2 2.12.3 2.12.4 2.13 2.14 2.14.1 2.15 2.15.1 2.16 2.16.1 2.17 2.17.1 2.18 2.18.1 2.18.2 2.18.3 2.19 2.19.1 2.19.2 2.19.3 2.2 2.2.1 2.3 2.3.1 2.3.10 2.3.2 2.3.3 2.3.4 2.3.6 2.3.7 2.3.8 2.3.9 2.4 2.4.1 2.4.1.1 2.4.1.2 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5 2.5.1 2.5.2 2.6 2.6.1 2.6.2 2.6.3 2.6.4 2.7 2.7.1 2.7.2 2.8 2.9 2.9.1 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.1 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.7.5 4.7.6 4.7.7
custom-facebook-feed / inc / Admin / CFF_Notifications.php
custom-facebook-feed / inc / Admin Last commit date
Traits 4 years ago CFF_About.php 4 years ago CFF_About_Us.php 4 years ago CFF_Admin.php 4 years ago CFF_Global_Settings.php 4 years ago CFF_Install_Skin.php 4 years ago CFF_New_User.php 4 years ago CFF_Notifications.php 4 years ago CFF_Support.php 4 years ago CFF_Tracking.php 4 years ago CFF_Upgrader.php 4 years ago CFF_oEmbeds.php 4 years ago
CFF_Notifications.php
788 lines
1 <?php
2 /**
3 * CFF_Notifications.
4 *
5 * @since 2.18/3.17
6 */
7 namespace CustomFacebookFeed\Admin;
8
9 use CustomFacebookFeed\CFF_Utils;
10 use CustomFacebookFeed\CFF_Response;
11
12 // Exit if accessed directly
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 class CFF_Notifications {
18
19 /**
20 * Source of notifications content.
21 *
22 * @var string
23 */
24 const SOURCE_URL = 'https://plugin.smashballoon.com/notifications.json';
25
26 /**
27 * @var string
28 */
29 const OPTION_NAME = 'cff_notifications';
30
31 /**
32 * JSON data contains notices for all plugins. This is used
33 * to select messages only meant for this plugin
34 *
35 * @var string
36 */
37 const PLUGIN = 'facebook';
38
39 /**
40 * Option value.
41 *
42 * @since 2.18/3.17
43 *
44 * @var bool|array
45 */
46 public $option = false;
47
48 /**
49 * Initialize class.
50 *
51 * @since 2.18/3.17
52 */
53 public function init() {
54 $this->hooks();
55 }
56
57 /**
58 * Use this function to get the option name to allow
59 * inheritance for the New_User class
60 *
61 * @return string
62 */
63 public function option_name() {
64 return self::OPTION_NAME;
65 }
66
67 /**
68 * Use this function to get the source URL to allow
69 * inheritance for the New_User class
70 *
71 * @return string
72 */
73 public function source_url() {
74 return self::SOURCE_URL;
75 }
76
77 /**
78 * Register hooks.
79 *
80 * @since 2.18/3.17
81 */
82 public function hooks() {
83 add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
84
85 add_action( 'cff_admin_notices', array( $this, 'output' ) );
86
87 // on cron. Once a week?
88 add_action( 'cff_notification_update', array( $this, 'update' ) );
89
90 add_action( 'wp_ajax_cff_dashboard_notification_dismiss', array( $this, 'dismiss' ) );
91
92 add_action( 'cff_header_notices', array( $this, 'header_notices' ) );
93 add_action( 'wp_ajax_cff_dismiss_upgrade_notice', array( $this, 'dismiss_upgrade_notice' ) );
94 }
95
96 /**
97 * Header Notices
98 *
99 * @since 4.0
100 */
101 public function header_notices() {
102 $lite_notice_dismissed = get_transient( 'facebook_feed_dismiss_lite' );
103 if ( $lite_notice_dismissed ) {
104 return;
105 }
106
107 $output = '';
108
109 $upgrade_url = 'https://smashballoondemo.com/?utm_campaign=facebook-free&utm_source=lite-upgrade-bar';
110 $output .= '<div class="cff-header-notice" id="cff-header-upgrade-notice">';
111 $output .= sprintf(
112 '<span class="cff-notice-bar-message">%s <a href="%s" target="_blank" rel="noopener noreferrer">%s</a></span>',
113 __('You\'re using Custom Facebook Feed Lite. To unlock more features consider', 'custom-faceboook-feed'),
114 $upgrade_url,
115 __('upgrading to Pro', 'custom-facebook-feed')
116 );
117
118 $output .= sprintf(
119 '<button type="button" class="cff-dismiss" id="cff-dismiss-header-notice" title="%s" data-page="overview">%s</button>',
120 __('Dismiss this message', 'custom-facebook-feed'),
121 '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.8327 5.34175L14.6577 4.16675L9.99935 8.82508L5.34102 4.16675L4.16602 5.34175L8.82435 10.0001L4.16602 14.6584L5.34102 15.8334L9.99935 11.1751L14.6577 15.8334L15.8327 14.6584L11.1744 10.0001L15.8327 5.34175Z" fill="white"/></svg>'
122 );
123
124 $output .= '</div>';
125
126 echo $output;
127 }
128
129 /**
130 * Dismiss Upgrade Notice
131 *
132 * @since 4.0
133 *
134 * @return CFF_Response
135 */
136 public function dismiss_upgrade_notice() {
137 // Run a security check.
138 check_ajax_referer( 'cff_nonce' , 'cff_nonce');
139
140 $cap = current_user_can( 'manage_custom_facebook_feed_options' ) ? 'manage_custom_facebook_feed_options' : 'manage_options';
141 $cap = apply_filters( 'cff_settings_pages_capability', $cap );
142 if ( ! current_user_can( $cap ) ) {
143 wp_send_json_error(); // This auto-dies.
144 }
145 // set the transient so it will hide for next 7 days
146 set_transient( 'facebook_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS );
147
148 new CFF_Response( true, array() );
149 }
150
151
152 /**
153 * Check if user has access and is enabled.
154 *
155 * @since 2.18/3.17
156 *
157 * @return bool
158 */
159 public function has_access() {
160 $access = false;
161
162 if ( current_user_can( 'manage_custom_facebook_feed_options' ) ) {
163 $access = true;
164 }
165
166 $current_screen = get_current_screen();
167 // if we are one single feed page then return
168 if ( is_object( $current_screen ) && $current_screen->base == "facebook-feed_page_cff-feed-builder" && isset( $_GET['feed_id'] ) ) {
169 $access = false;
170 }
171
172 return apply_filters( 'cff_admin_notifications_has_access', $access );
173 }
174
175 /**
176 * Get option value.
177 *
178 * @since 2.18/3.17
179 *
180 * @param bool $cache Reference property cache if available.
181 *
182 * @return array
183 */
184 public function get_option( $cache = true ) {
185 if ( $this->option && $cache ) {
186 return $this->option;
187 }
188
189 $option = get_option( $this->option_name(), array() );
190
191 $this->option = array(
192 'update' => ! empty( $option['update'] ) ? $option['update'] : 0,
193 'events' => ! empty( $option['events'] ) ? $option['events'] : array(),
194 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : array(),
195 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : array(),
196 );
197
198 return $this->option;
199 }
200
201 /**
202 * Fetch notifications from feed.
203 *
204 * @since 2.18/3.17
205 *
206 * @return array
207 */
208 public function fetch_feed() {
209 $res = wp_remote_get( $this->source_url() );
210
211 if ( is_wp_error( $res ) ) {
212 return array();
213 }
214
215 $body = wp_remote_retrieve_body( $res );
216
217 if ( empty( $body ) ) {
218 return array();
219 }
220
221 $body = str_replace( array( 'sbi_', 'sbi-' ), array( 'cff_', 'cff-' ), $body );
222
223 return $this->verify( json_decode( $body, true ) );
224 }
225
226 /**
227 * Verify notification data before it is saved.
228 *
229 * @since 2.18/3.17
230 *
231 * @param array $notifications Array of notifications items to verify.
232 *
233 * @return array
234 */
235 public function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
236 $data = array();
237
238 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
239 return $data;
240 }
241
242 $option = $this->get_option();
243
244 foreach ( $notifications as $notification ) {
245 // Ignore if max version has been reached
246 if ( ! empty( $notification['maxver'] ) && version_compare( $notification['maxver'], CFFVER ) <= 0 ) {
247 continue;
248 }
249
250 // Ignore if min version has not been reached
251 if ( ! empty( $notification['minver'] ) && version_compare( $notification['minver'], CFFVER ) >= 0 ) {
252 continue;
253 }
254
255 // Ignore if a specific cff_status is empty or false
256 if ( ! empty( $notification['statuscheck'] ) ) {
257 $status_key = sanitize_key( $notification['statuscheck'] );
258 $cff_statuses_option = get_option( 'cff_statuses', array() );
259
260 if ( empty( $cff_statuses_option[ $status_key ] ) ) {
261 continue;
262 }
263 }
264
265 // The message and license should never be empty, if they are, ignore.
266 if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) {
267 continue;
268 }
269
270 // Ignore if license type does not match.
271 $license = CFF_Utils::cff_is_pro_version() ? 'pro' : 'free';
272
273 if ( ! in_array( $license, $notification['type'], true ) ) {
274 continue;
275 }
276
277 // Ignore if expired.
278 if ( ! empty( $notification['end'] ) && cff_get_current_time() > strtotime( $notification['end'] ) ) {
279 continue;
280 }
281
282 // Ignore if notification has already been dismissed.
283 if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
284 continue;
285 }
286
287 // TODO: Ignore if notification existed before installing CFF.
288 // Prevents bombarding the user with notifications after activation.
289 $activated = false;
290 if ( ! empty( $activated )
291 && ! empty( $notification['start'] )
292 && $activated > strtotime( $notification['start'] ) ) {
293 continue;
294 }
295
296 $data[] = $notification;
297 }
298
299 return $data;
300 }
301
302 /**
303 * Verify saved notification data for active notifications.
304 *
305 * @since 2.18/3.17
306 *
307 * @param array $notifications Array of notifications items to verify.
308 *
309 * @return array
310 */
311 public function verify_active( $notifications ) {
312 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
313 return array();
314 }
315
316 // Remove notfications that are not active.
317 foreach ( $notifications as $key => $notification ) {
318 if ( ( ! empty( $notification['start'] ) && cff_get_current_time() < strtotime( $notification['start'] ) )
319 || ( ! empty( $notification['end'] ) && cff_get_current_time() > strtotime( $notification['end'] ) ) ) {
320 unset( $notifications[ $key ] );
321 }
322
323 // Ignore if max version has been reached
324 if ( ! empty( $notification['maxver'] ) && version_compare( $notification['maxver'], CFFVER ) <= 0 ) {
325 unset( $notifications[ $key ] );
326 }
327
328 // Ignore if min version has not been reached
329 if ( ! empty( $notification['minver'] ) && version_compare( $notification['minver'], CFFVER ) >= 0 ) {
330 unset( $notifications[ $key ] );
331 }
332
333 // Ignore if a specific cff_status is empty or false
334 if ( ! empty( $notification['statuscheck'] ) ) {
335 $status_key = sanitize_key( $notification['statuscheck'] );
336 $cff_statuses_option = get_option( 'cff_statuses', array() );
337
338 if ( empty( $cff_statuses_option[ $status_key ] ) ) {
339 unset( $notifications[ $key ] );
340 }
341 }
342 }
343
344 return $notifications;
345 }
346
347 /**
348 * Get notification data.
349 *
350 * @since 2.18/3.17
351 *
352 * @return array
353 */
354 public function get() {
355 if ( ! $this->has_access() ) {
356 return array();
357 }
358
359 $option = $this->get_option();
360
361 // Update notifications using async task.
362 if ( empty( $option['update'] ) || cff_get_current_time() > $option['update'] + DAY_IN_SECONDS ) {
363 $this->update();
364 }
365
366 $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
367 $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
368
369 // If there is a new user notification, add it to the beginning of the notification list
370 $cff_newuser = new CFF_New_User();
371 $newuser_notifications = $cff_newuser->get();
372
373 if ( ! empty( $newuser_notifications ) ) {
374 $events = array_merge( $newuser_notifications, $events );
375 }
376
377 return array_merge( $events, $feed );
378 }
379
380 /**
381 * Get notification count.
382 *
383 * @since 2.18/3.17
384 *
385 * @return int
386 */
387 public function get_count() {
388 return count( $this->get() );
389 }
390
391 /**
392 * Add a manual notification event.
393 *
394 * @since 2.18/3.17
395 *
396 * @param array $notification Notification data.
397 */
398 public function add( $notification ) {
399 if ( empty( $notification['id'] ) ) {
400 return;
401 }
402
403 $option = $this->get_option();
404
405 if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
406 return;
407 }
408
409 foreach ( $option['events'] as $item ) {
410 if ( $item['id'] === $notification['id'] ) {
411 return;
412 }
413 }
414
415 $notification = $this->verify( array( $notification ) );
416
417 update_option(
418 'cff_notifications',
419 array(
420 'update' => $option['update'],
421 'feed' => $option['feed'],
422 'events' => array_merge( $notification, $option['events'] ),
423 'dismissed' => $option['dismissed'],
424 )
425 );
426 }
427
428 /**
429 * Update notification data from feed.
430 *
431 * @since 2.18/3.17
432 */
433 public function update() {
434 $feed = $this->fetch_feed();
435 $option = $this->get_option();
436
437 update_option(
438 'cff_notifications',
439 array(
440 'update' => cff_get_current_time(),
441 'feed' => $feed,
442 'events' => $option['events'],
443 'dismissed' => $option['dismissed'],
444 )
445 );
446 }
447
448 /**
449 * Admin area Form Overview enqueues.
450 *
451 * @since 2.18/3.17
452 */
453 public function enqueues() {
454 if ( ! $this->has_access() ) {
455 return;
456 }
457
458 $notifications = $this->get();
459
460 if ( empty( $notifications ) ) {
461 return;
462 }
463
464 $min = '';
465
466 wp_enqueue_style(
467 'cff-admin-notifications',
468 CFF_PLUGIN_URL . "admin/assets/css/admin-notifications{$min}.css",
469 array(),
470 CFFVER
471 );
472
473 wp_enqueue_script(
474 'cff-admin-notifications',
475 CFF_PLUGIN_URL . "admin/assets/js/admin-notifications{$min}.js",
476 array( 'jquery' ),
477 CFFVER,
478 true
479 );
480 }
481
482 /**
483 * Fields from the remote source contain placeholders to allow
484 * some messages to be used for multiple plugins.
485 *
486 * @param $content string
487 * @param $notification array
488 *
489 * @return string
490 *
491 * @since 2.18/3.17
492 */
493 public function replace_merge_fields( $content, $notification ) {
494 $merge_fields = array(
495 '{plugin}' => 'Custom Facebook Feed',
496 '{amount}' => isset( $notification['amount'] ) ? $notification['amount'] : '',
497 '{platform}' => 'Facebook',
498 '{lowerplatform}' => 'facebook',
499 '{review-url}' => 'https://wordpress.org/support/plugin/custom-facebook-feed/reviews/',
500 '{slug}' => 'custom-facebook-feed',
501 '{campaign}' => 'facebook-free'
502 );
503
504 if ( CFF_Utils::cff_is_pro_version() ) {
505 $merge_fields['{campaign}'] = 'facebook-pro';
506 $merge_fields['{plugin}'] = 'Custom Facebook Feed Pro';
507 }
508
509 foreach ( $merge_fields as $find => $replace ) {
510 $content = str_replace( $find, $replace, $content );
511 }
512
513 return $content;
514 }
515
516 /**
517 * Output notifications on Custom Facebook Feed admin area.
518 *
519 * @since 2.18/3.17
520 */
521 public function output() {
522 $current_screen = get_current_screen();
523 // if we are one single feed page then return
524 if ( $current_screen->base == "facebook-feed_page_cff-feed-builder" && isset( $_GET['feed_id'] ) ) {
525 return;
526 }
527
528 $notifications = $this->get();
529
530 if ( empty( $notifications ) ) {
531 return;
532 }
533
534 $notifications_html = '';
535 $current_class = ' current';
536 $content_allowed_tags = array(
537 'em' => array(),
538 'strong' => array(),
539 'span' => array(
540 'style' => array(),
541 ),
542 'a' => array(
543 'href' => array(),
544 'target' => array(),
545 'rel' => array(),
546 ),
547 );
548
549 foreach ( $notifications as $notification ) {
550 $type = $notification['id'];
551 // Buttons HTML.
552 $buttons_html = '';
553 if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
554 foreach ( $notification['btns'] as $btn_type => $btn ) {
555 if ( $type == 'review' || $type == 'discount' ) {
556 $btn_class = $btn_type === 'primary' ? 'cff-btn-blue' : 'cff-btn-grey';
557 } else {
558 $btn_class = $btn_type === 'primary' ? 'cff-btn-orange' : 'cff-btn-grey';
559 }
560 if ( is_array( $btn['url'] ) ) {
561 $btn['url'] = add_query_arg( $btn['url'] );
562 }
563 if ( ! empty( $btn['attr'] ) ) {
564 $btn['target'] = '_blank';
565 }
566 if ( empty( $btn['class'] ) ) {
567 $btn['class'] = '';
568 }
569 $buttons_html .= sprintf(
570 '<a href="%1$s" class="cff-btn %2$s %3$s"%4$s>%5$s</a>',
571 ! empty( $btn['url'] ) ? esc_url( $this->replace_merge_fields( $btn['url'], $notification ) ) : '',
572 $btn['class'],
573 $btn_class,
574 ! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
575 ! empty( $btn['text'] ) ? sanitize_text_field( $btn['text'] ) : ''
576 );
577 }
578 $buttons_html = ! empty( $buttons_html ) ? '<div class="buttons">' . $buttons_html . '</div>' : '';
579 }
580
581 if ( empty( $notification['image'] ) ) {
582 $image_html = '<div class="bell">';
583
584 $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" width="42" height="48" viewBox="0 0 42 48"><defs><style>.a{fill:#777;}.b{fill:#ca4a1f;}</style></defs><path class="a" d="M23-79a6.005,6.005,0,0,1-6-6h10.06a12.066,12.066,0,0,0,1.791,1.308,6.021,6.021,0,0,1-2.077,3.352A6.008,6.008,0,0,1,23-79Zm1.605-9H5.009a2.955,2.955,0,0,1-2.173-.923A3.088,3.088,0,0,1,2-91a2.919,2.919,0,0,1,.807-2.036c.111-.12.229-.243.351-.371a14.936,14.936,0,0,0,3.126-4.409A23.283,23.283,0,0,0,8.007-107.5a14.846,14.846,0,0,1,.906-5.145,14.5,14.5,0,0,1,2.509-4.324A15.279,15.279,0,0,1,20-122.046V-124a3,3,0,0,1,3-3,3,3,0,0,1,3,3v1.954a15.28,15.28,0,0,1,8.58,5.078,14.5,14.5,0,0,1,2.509,4.324,14.846,14.846,0,0,1,.906,5.145c0,.645.016,1.281.047,1.888A12.036,12.036,0,0,0,35-106a11.921,11.921,0,0,0-8.485,3.515A11.923,11.923,0,0,0,23-94a12,12,0,0,0,1.6,6Z" transform="translate(-2 127)"/><circle class="b" cx="9" cy="9" r="9" transform="translate(24 24)"/></svg>';
585 $image_html .= '</div>';
586 } else {
587 if ( $notification['image'] === 'balloon' ) {
588 $image_html = '<div class="bell">';
589
590 $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1438 1878" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2">';
591 $image_html .= ' <path d="M671.51004 492.9884C539.9423 433.8663 402.90125 345.5722 274.97656 304.47286c45.45163 108.39592 83.81332 223.88017 123.51 338.03105C319.308 702.00293 226.8217 748.19258 138.46278 798.51607c75.1914 74.32371 181.67968 117.34651 266.52444 182.01607-67.96124 83.86195-201.48527 171.01801-234.02107 247.01998 140.6922-17.6268 304.63688-46.21031 435.53794-52.00418 28.76427 144.58328 43.5987 303.09763 84.50756 435.53713 60.92033-175.26574 116.0014-356.37317 188.51594-520.0451 111.90644 46.2857 248.29012 102.72607 357.52902 130.01188-76.64636-107.5347-146.59346-221.76948-214.5166-338.02903 100.51162-72.83876 202.1718-144.52451 299.02538-221.02092-136.89514-12.61229-278.73428-20.28827-422.53618-25.99865-22.85288-148.33212-16.84826-325.51604-52.005-461.53983-53.19327 111.4882-115.96694 213.39155-175.51418 318.52497m65.00513 1228.60735c-18.0795 77.37586 41.4876 109.11326 32.50298 156.01215-58.8141-20.268-103.0576-30.67962-182.01567-19.50203 2.47018-60.37036 56.76662-68.90959 45.50432-143.0108C-208.90184 1619.4318-210.59186 99.02478 626.00572 5.44992c1046.0409-117.00405 1078.86445 1689.2596 110.50945 1716.14582" fill="#e34f0e"/>';
592 $image_html .= ' <path d="M847.02422 174.46342c35.15674 136.02379 29.15212 313.20771 52.0046 461.53578 143.8023 5.71443 285.63982 13.38636 422.53658 26.0027-96.85317 76.4964-198.51497 148.18216-299.02579 221.0189 67.92355 116.26239 137.87024 230.49432 214.51864 338.03024-109.24093-27.28662-245.62461-83.72577-357.53106-130.01269-72.51454 163.67274-127.5956 344.78017-188.51553 520.0459-40.90926-132.4395-55.74329-290.95384-84.50796-435.53712-130.90066 5.79549-294.84493 34.37738-435.53754 52.00418 32.5358-76.00075 166.05902-163.156 234.02026-247.02038-84.84516-64.67037-191.33222-107.69074-266.52363-182.01486 88.35892-50.32349 180.8436-96.51314 260.02295-156.0162-39.69708-114.14683-78.05674-229.63108-123.50878-338.027C402.89923 345.5722 539.9423 433.86629 671.51004 492.98839c59.54684-105.13342 122.3209-207.03677 175.51418-318.52497" fill="#fff"/>';
593 $image_html .= '</svg>';
594 } else if ( $notification['id'] === 'review' || $notification['id'] === 'discount' ) {
595 $image_html = sprintf(
596 '<div class="bell"><img src="%s" alt="notice">',
597 CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field( $notification['image'] )
598 );
599 } else {
600 $image_html = '<div class="thumb">';
601 $img_src = CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field( $notification['image'] );
602 $image_html .= '<img src="'.esc_url( $img_src ).'" alt="notice">';
603
604 if ( isset( $notification['image_overlay'] ) ) {
605 $image_html .= '<div class="img-overlay">'. esc_html( str_replace( '%', '%%', $notification['image_overlay'] ) ).'</div>';
606 }
607 }
608 $image_html .= '</div>';
609
610 }
611
612 // Check if it's review notice then show step #1
613 if ( $type == 'review' ) {
614 $step1_img = CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field( $notification['image'] );
615 $step1_img_html = sprintf('<div class="bell"><img src="%s" alt="notice"></div>', $step1_img);
616
617 $review_consent = get_option( 'cff_review_consent' );
618 $cff_open_feedback_url = 'https://smashballoon.com/feedback/?plugin=facebook-lite';
619 // step #1 for the review notice
620 if ( ! $review_consent ) {
621 $step1_btns = sprintf(
622 '<button class="cff-btn-link" id="cff_review_consent_yes">%s</button>',
623 __( 'Yes', 'custom-facebook-feed' )
624 );
625 $step1_btns .= sprintf(
626 '<a href="%s" target="_blank" class="cff-btn-link" id="cff_review_consent_no">%s</a>',
627 $cff_open_feedback_url,
628 __( 'No', 'custom-facebook-feed' )
629 );
630 $notifications_html .= sprintf(
631 '<div class="cff_review_step1_notice" data-message-id="%3$s">' . $step1_img_html . '
632 <h3 class="title">%1$s</h3>
633 <div class="review-step-1-btns">%2$s</div>
634 </div>',
635 __( 'Are you enjoying the Custom Facebook Feed Plugin?', 'custom-facebook-feed' ),
636 $step1_btns,
637 ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0
638 );
639 }
640 }
641
642 $review_consent = get_option( 'cff_review_consent' );
643 $review_step2_style = '';
644 if ( $type == 'review' && ! $review_consent ) {
645 $review_step2_style = 'style="display: none;"';
646 }
647
648 // Build the notification HTML for review notice
649 if ( $type == 'review' ) {
650 $notifications_html .= sprintf(
651 '<div class="message%5$s %7$s" data-message-id="%4$s" %6$s>' . $image_html . '
652 <h3 class="title">%1$s</h3>
653 <p class="content">%2$s</p>
654 %3$s
655 </div>',
656 __( 'Glad to hear you are enjoying it. Would you consider leaving a positive review?', 'custom-facebook-feed' ),
657 __( 'It really helps to support the plugin and help others to discover it too!', 'custom-facebook-feed' ),
658 $buttons_html,
659 ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
660 $current_class,
661 ( $notification['id'] == 'review' && ! empty( $review_step2_style ) ) ? $review_step2_style : '',
662 ( $type == 'review' ) ? 'rn_step_2' : ''
663 );
664 } else if ( $type == 'discount' ) {
665 // Build the notification HTML for discount notice
666 $notifications_html .= sprintf(
667 '<div class="message%5$s %7$s" data-message-id="%4$s" %6$s>' . $image_html . '
668 <h3 class="title">%1$s</h3>
669 <p class="content">%2$s</p>
670 %3$s
671 </div>',
672 __( 'Exclusive Offer! 60% OFF', 'custom-facebook-feed' ),
673 __( 'We don’t run promotions very often, but for a limited time we’re offering 60% Off our Pro version to all users of our free Facebook Feed.', 'custom-facebook-feed' ),
674 $buttons_html,
675 ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
676 $current_class,
677 ( $notification['id'] == 'review' && ! empty( $review_step2_style ) ) ? $review_step2_style : '',
678 ( $type == 'review' && ! $review_consent ) ? 'rn_step_2' : ''
679 );
680 } else {
681 // Notification HTML for other notices
682 $notifications_html .= sprintf(
683 '<div class="message%5$s" data-message-id="%4$s" %6$s>' . $image_html . '
684 <h3 class="title">%1$s</h3>
685 <p class="content">%2$s</p>
686 %3$s
687 </div>',
688 ! empty( $notification['title'] ) ? $this->replace_merge_fields( sanitize_text_field( $notification['title'] ), $notification ) : '',
689 ! empty( $notification['content'] ) ? wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags ) : '',
690 $buttons_html,
691 ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
692 $current_class,
693 ( $notification['id'] == 'review' && ! empty( $review_step2_style ) ) ? $review_step2_style : ''
694 );
695 }
696
697 // Only first notification is current.
698 $current_class = '';
699 }
700
701 $close_href = add_query_arg( array( 'cff_dismiss' => $type ) );
702 $class = '';
703 if ( $type === 'review' || $type === 'discount' ) {
704 $class = $type === 'review' ? ' cff_review_notice' : ' cff_discount_notice';
705 }
706 ?>
707
708 <div id="cff-notifications" class="<?php echo esc_attr( $class ); ?>">
709 <a
710 class="dismiss"
711 title="<?php echo esc_attr__( 'Dismiss this message', 'custom-facebook-feed' ); ?>"
712 <?php echo ( $type == 'review' || $type == 'discount' ) ? 'href="'. esc_attr( $close_href ) .'"' : '' ?>
713 >
714 <svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
715 <path d="M9.66683 1.27325L8.72683 0.333252L5.00016 4.05992L1.2735 0.333252L0.333496 1.27325L4.06016 4.99992L0.333496 8.72659L1.2735 9.66659L5.00016 5.93992L8.72683 9.66659L9.66683 8.72659L5.94016 4.99992L9.66683 1.27325Z" fill="white"/>
716 </svg>
717 </a>
718
719 <?php if ( count( $notifications ) > 1 ) : ?>
720 <div class="navigation">
721 <a class="prev disabled" title="<?php echo esc_attr__( 'Previous message', 'custom-facebook-feed' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-left" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-left fa-w-10"><path fill="currentColor" d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z" class=""></path></svg></a>
722 <a class="next disabled" title="<?php echo esc_attr__( 'Next message', 'custom-facebook-feed' ); ?>"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-right fa-w-10"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" class=""></path></svg></a>
723 </div>
724 <?php endif; ?>
725
726 <div class="messages">
727 <?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
728 </div>
729 </div>
730 <?php
731 }
732
733 /**
734 * Dismiss notification via AJAX. If it's a new user message, also dismiss it
735 * on all admin pages.
736 *
737 * @since 2.18/3.17
738 */
739 public function dismiss() {
740 // Run a security check.
741 check_ajax_referer( 'cff-admin', 'nonce' );
742
743 // Check for access and required param.
744 if ( ! $this->has_access() || empty( $_POST['id'] ) ) {
745 wp_send_json_error();
746 }
747
748 $id = sanitize_text_field( wp_unslash( $_POST['id'] ) );
749
750 if ( $id === 'review' ) {
751 $cff_statuses_option = get_option( 'cff_statuses', array() );
752
753 update_option( 'cff_rating_notice', 'dismissed', false );
754 $cff_statuses_option['rating_notice_dismissed'] = cff_get_current_time();
755 update_option( 'cff_statuses', $cff_statuses_option, false );
756 } elseif ( $id === 'discount' ) {
757 update_user_meta( get_current_user_id(), 'cff_ignore_new_user_sale_notice', 'always' );
758
759 $current_month_number = (int)date('n', cff_get_current_time() );
760 $not_early_in_the_year = ($current_month_number > 5);
761
762 if ( $not_early_in_the_year ) {
763 update_user_meta( get_current_user_id(), 'cff_ignore_bfcm_sale_notice', date( 'Y', cff_get_current_time() ) );
764 }
765 }
766
767 $option = $this->get_option();
768 $type = is_numeric( $id ) ? 'feed' : 'events';
769
770 $option['dismissed'][] = $id;
771 $option['dismissed'] = array_unique( $option['dismissed'] );
772
773 // Remove notification.
774 if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) {
775 foreach ( $option[ $type ] as $key => $notification ) {
776 if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons
777 unset( $option[ $type ][ $key ] );
778 break;
779 }
780 }
781 }
782
783 update_option( 'cff_notifications', $option );
784
785 wp_send_json_success();
786 }
787 }
788