PluginProbe ʕ •ᴥ•ʔ
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress / 4.12.0
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress v4.12.0
4.12.0 4.10.0 4.9.0 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
Blocks 2 weeks ago Traits 2 weeks ago CFF_About_Us.php 2 weeks ago CFF_Admin.php 2 weeks ago CFF_Admin_Notices.php 2 weeks ago CFF_Callout.php 2 weeks ago CFF_Global_Settings.php 2 weeks ago CFF_Install_Skin.php 2 weeks ago CFF_New_User.php 2 weeks ago CFF_Notifications.php 2 weeks ago CFF_Onboarding_Wizard.php 2 weeks ago CFF_Support.php 2 weeks ago CFF_Support_Tool.php 2 weeks ago CFF_Upgrader.php 2 weeks ago CFF_oEmbeds.php 2 weeks ago index.php 2 weeks ago
CFF_Notifications.php
853 lines
1 <?php
2
3 /**
4 * CFF_Notifications.
5 *
6 * @since 2.18/3.17
7 */
8
9 namespace CustomFacebookFeed\Admin;
10
11 use CustomFacebookFeed\CFF_Utils;
12 use CustomFacebookFeed\CFF_Response;
13
14 // Exit if accessed directly
15 if (! defined('ABSPATH')) {
16 exit;
17 }
18
19 class CFF_Notifications
20 {
21 /**
22 * Source of notifications content.
23 *
24 * @var string
25 */
26 const SOURCE_URL = 'https://plugin.smashballoon.com/notifications.json';
27
28 /**
29 * @var string
30 */
31 const OPTION_NAME = 'cff_notifications';
32
33 /**
34 * JSON data contains notices for all plugins. This is used
35 * to select messages only meant for this plugin
36 *
37 * @var string
38 */
39 const PLUGIN = 'facebook';
40
41 /**
42 * Option value.
43 *
44 * @since 2.18/3.17
45 *
46 * @var bool|array
47 */
48 public $option = false;
49
50 /**
51 * Initialize class.
52 *
53 * @since 2.18/3.17
54 */
55 public function init()
56 {
57 $this->hooks();
58 }
59
60 /**
61 * Use this function to get the option name to allow
62 * inheritance for the New_User class
63 *
64 * @return string
65 */
66 public function option_name()
67 {
68 return self::OPTION_NAME;
69 }
70
71 /**
72 * Use this function to get the source URL to allow
73 * inheritance for the New_User class
74 *
75 * @return string
76 */
77 public function source_url()
78 {
79 return self::SOURCE_URL;
80 }
81
82 /**
83 * Register hooks.
84 *
85 * @since 2.18/3.17
86 */
87 public function hooks()
88 {
89 add_action('admin_enqueue_scripts', array( $this, 'enqueues' ));
90
91 add_action('cff_admin_notices', array( $this, 'output' ));
92
93 // on cron. Once a week?
94 add_action('cff_notification_update', array( $this, 'update' ));
95
96 add_action('wp_ajax_cff_dashboard_notification_dismiss', array( $this, 'dismiss' ));
97
98 add_action('cff_header_notices', array( $this, 'header_notices' ));
99 add_action('wp_ajax_cff_dismiss_upgrade_notice', array( $this, 'dismiss_upgrade_notice' ));
100 }
101
102 /**
103 * Header Notices
104 *
105 * @since 4.0
106 */
107 public function header_notices()
108 {
109 $lite_notice_dismissed = get_transient('facebook_feed_dismiss_lite');
110 if ($lite_notice_dismissed) {
111 return;
112 }
113
114 $output = '';
115
116 $upgrade_url = 'https://smashballoon.com/custom-facebook-feed/facebook-lite-upgrade/?utm_campaign=facebook-free&utm_source=lite-upgrade-bar&utm_medium=upgrade-bar&utm_content=upgradingToPro';
117 $output .= '<div class="cff-header-notice" id="cff-header-upgrade-notice">';
118 $output .= sprintf(
119 '<span class="cff-notice-bar-message">%s <a href="%s" target="_blank" rel="noopener noreferrer">%s</a></span>',
120 __('You\'re using Custom Facebook Feed Lite. To unlock more features consider', 'custom-faceboook-feed'),
121 $upgrade_url,
122 __('upgrading to Pro', 'custom-facebook-feed')
123 );
124
125 $output .= sprintf(
126 '<button type="button" class="cff-dismiss" id="cff-dismiss-header-notice" title="%s" data-page="overview">%s</button>',
127 __('Dismiss this message', 'custom-facebook-feed'),
128 '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><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>'
129 );
130
131 $output .= '</div>';
132
133 echo $output;
134 }
135
136 /**
137 * Dismiss Upgrade Notice
138 *
139 * @since 4.0
140 *
141 * @return CFF_Response
142 */
143 public function dismiss_upgrade_notice()
144 {
145 // Run a security check.
146 check_ajax_referer('cff_nonce', 'cff_nonce');
147
148 $cap = current_user_can('manage_custom_facebook_feed_options') ? 'manage_custom_facebook_feed_options' : 'manage_options';
149 $cap = apply_filters('cff_settings_pages_capability', $cap);
150 if (! current_user_can($cap)) {
151 wp_send_json_error(); // This auto-dies.
152 }
153 // set the transient so it will hide for next 7 days
154 set_transient('facebook_feed_dismiss_lite', 'dismiss', 1 * WEEK_IN_SECONDS);
155
156 $response = new CFF_Response(true, array());
157 $response->send();
158 }
159
160
161 /**
162 * Check if user has access and is enabled.
163 *
164 * @since 2.18/3.17
165 *
166 * @return bool
167 */
168 public function has_access()
169 {
170 $access = false;
171
172 if (current_user_can('manage_custom_facebook_feed_options')) {
173 $access = true;
174 }
175
176 $current_screen = get_current_screen();
177 // if we are one single feed page then return
178 if (is_object($current_screen) && $current_screen->base == "facebook-feed_page_cff-feed-builder" && isset($_GET['feed_id'])) {
179 $access = false;
180 }
181
182 return apply_filters('cff_admin_notifications_has_access', $access);
183 }
184
185 /**
186 * Get option value.
187 *
188 * @since 2.18/3.17
189 *
190 * @param bool $cache Reference property cache if available.
191 *
192 * @return array
193 */
194 public function get_option($cache = true)
195 {
196 if ($this->option && $cache) {
197 return $this->option;
198 }
199
200 $option = get_option($this->option_name(), array());
201
202 $this->option = array(
203 'update' => ! empty($option['update']) ? $option['update'] : 0,
204 'events' => ! empty($option['events']) ? $option['events'] : array(),
205 'feed' => ! empty($option['feed']) ? $option['feed'] : array(),
206 'dismissed' => ! empty($option['dismissed']) ? $option['dismissed'] : array(),
207 );
208
209 return $this->option;
210 }
211
212 /**
213 * Fetch notifications from feed.
214 *
215 * @since 2.18/3.17
216 *
217 * @return array
218 */
219 public function fetch_feed()
220 {
221 $res = wp_safe_remote_get($this->source_url());
222
223 if (is_wp_error($res)) {
224 return array();
225 }
226
227 $body = wp_remote_retrieve_body($res);
228
229 if (empty($body)) {
230 return array();
231 }
232
233 $body = str_replace(array( 'sbi_', 'sbi-' ), array( 'cff_', 'cff-' ), $body);
234
235 return $this->verify(json_decode($body, true));
236 }
237
238 /**
239 * Verify notification data before it is saved.
240 *
241 * @since 2.18/3.17
242 *
243 * @param array $notifications Array of notifications items to verify.
244 *
245 * @return array
246 */
247 public function verify($notifications) // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
248 {
249 $data = array();
250
251 if (! is_array($notifications) || empty($notifications)) {
252 return $data;
253 }
254
255 $option = $this->get_option();
256
257 foreach ($notifications as $notification) {
258 // Ignore if not a targeted plugin
259 if (! empty($notification['plugin']) && is_array($notification['plugin']) && ! in_array(self::PLUGIN, $notification['plugin'], true)) {
260 continue;
261 }
262
263 // Ignore if max wp version detected
264 if (! empty($notification['maxwpver']) && version_compare(get_bloginfo('version'), $notification['maxwpver'], '>')) {
265 continue;
266 }
267
268 // Ignore if max version has been reached
269 if (! empty($notification['maxver']) && version_compare($notification['maxver'], CFFVER) <= 0) {
270 continue;
271 }
272
273 // Ignore if min version has not been reached
274 if (! empty($notification['minver']) && version_compare($notification['minver'], CFFVER) >= 0) {
275 continue;
276 }
277
278 // Ignore if a specific cff_status is empty or false
279 if (! empty($notification['statuscheck'])) {
280 $status_key = sanitize_key($notification['statuscheck']);
281 $cff_statuses_option = get_option('cff_statuses', array());
282
283 if (empty($cff_statuses_option[ $status_key ])) {
284 continue;
285 }
286 }
287
288 // The message and license should never be empty, if they are, ignore.
289 if (empty($notification['content']) || empty($notification['type'])) {
290 continue;
291 }
292
293 // Ignore if license type does not match.
294 $license = CFF_Utils::cff_is_pro_version() ? 'pro' : 'free';
295
296 if (! in_array($license, $notification['type'], true)) {
297 continue;
298 }
299
300 // Ignore if expired.
301 if (! empty($notification['end']) && cff_get_current_time() > strtotime($notification['end'])) {
302 continue;
303 }
304
305 // Ignore if notification has already been dismissed.
306 if (! empty($option['dismissed']) && in_array($notification['id'], $option['dismissed'])) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
307 continue;
308 }
309
310 // TODO: Ignore if notification existed before installing CFF.
311 // Prevents bombarding the user with notifications after activation.
312 $activated = false;
313 if (
314 ! empty($activated)
315 && ! empty($notification['start'])
316 && $activated > strtotime($notification['start'])
317 ) {
318 continue;
319 }
320
321 $data[] = $notification;
322 }
323
324 return $data;
325 }
326
327 /**
328 * Verify saved notification data for active notifications.
329 *
330 * @since 2.18/3.17
331 *
332 * @param array $notifications Array of notifications items to verify.
333 *
334 * @return array
335 */
336 public function verify_active($notifications)
337 {
338 if (! is_array($notifications) || empty($notifications)) {
339 return array();
340 }
341
342 // Remove notfications that are not active.
343 foreach ($notifications as $key => $notification) {
344 if (
345 ( ! empty($notification['start']) && cff_get_current_time() < strtotime($notification['start']) )
346 || ( ! empty($notification['end']) && cff_get_current_time() > strtotime($notification['end']) )
347 ) {
348 unset($notifications[ $key ]);
349 }
350
351 if (empty($notification['recent_install_override']) && $this->recently_installed()) {
352 unset($notifications[ $key ]);
353 }
354
355 // Ignore if max wp version detected
356 if (! empty($notification['maxwpver']) && version_compare(get_bloginfo('version'), $notification['maxwpver'], '>')) {
357 unset($notifications[ $key ]);
358 }
359
360 // Ignore if max version has been reached
361 if (! empty($notification['maxver']) && version_compare($notification['maxver'], CFFVER) <= 0) {
362 unset($notifications[ $key ]);
363 }
364
365 // Ignore if min version has not been reached
366 if (! empty($notification['minver']) && version_compare($notification['minver'], CFFVER) >= 0) {
367 unset($notifications[ $key ]);
368 }
369
370 // Ignore if a specific cff_status is empty or false
371 if (! empty($notification['statuscheck'])) {
372 $status_key = sanitize_key($notification['statuscheck']);
373 $cff_statuses_option = get_option('cff_statuses', array());
374
375 if (empty($cff_statuses_option[ $status_key ])) {
376 unset($notifications[ $key ]);
377 }
378 }
379 }
380
381 return $notifications;
382 }
383
384 /**
385 * @return bool
386 *
387 * @since 1.4.5/1.4.2
388 */
389 public function recently_installed()
390 {
391 $cff_statuses_option = get_option('cff_statuses', array());
392
393 if (! isset($cff_statuses_option['first_install'])) {
394 return false;
395 }
396
397 // Plugin was installed less than a week ago
398 if ((int) $cff_statuses_option['first_install'] > time() - WEEK_IN_SECONDS) {
399 return true;
400 }
401
402 return false;
403 }
404
405 /**
406 * Get notification data.
407 *
408 * @since 2.18/3.17
409 *
410 * @return array
411 */
412 public function get()
413 {
414 if (! $this->has_access()) {
415 return array();
416 }
417
418 $option = $this->get_option();
419
420 // Update notifications using async task.
421 if (empty($option['update']) || cff_get_current_time() > $option['update'] + DAY_IN_SECONDS) {
422 $this->update();
423 }
424
425 $events = ! empty($option['events']) ? $this->verify_active($option['events']) : array();
426 $feed = ! empty($option['feed']) ? $this->verify_active($option['feed']) : array();
427
428 // If there is a new user notification, add it to the beginning of the notification list
429 $cff_newuser = new CFF_New_User();
430 $newuser_notifications = $cff_newuser->get();
431
432 if (! empty($newuser_notifications)) {
433 $events = array_merge($newuser_notifications, $events);
434 }
435
436 return array_merge($events, $feed);
437 }
438
439 /**
440 * Get notification count.
441 *
442 * @since 2.18/3.17
443 *
444 * @return int
445 */
446 public function get_count()
447 {
448 return count($this->get());
449 }
450
451 /**
452 * Add a manual notification event.
453 *
454 * @since 2.18/3.17
455 *
456 * @param array $notification Notification data.
457 */
458 public function add($notification)
459 {
460 if (empty($notification['id'])) {
461 return;
462 }
463
464 $option = $this->get_option();
465
466 if (in_array($notification['id'], $option['dismissed'])) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
467 return;
468 }
469
470 foreach ($option['events'] as $item) {
471 if ($item['id'] === $notification['id']) {
472 return;
473 }
474 }
475
476 $notification = $this->verify(array( $notification ));
477
478 update_option(
479 'cff_notifications',
480 array(
481 'update' => $option['update'],
482 'feed' => $option['feed'],
483 'events' => array_merge($notification, $option['events']),
484 'dismissed' => $option['dismissed'],
485 )
486 );
487 }
488
489 /**
490 * Update notification data from feed.
491 *
492 * @since 2.18/3.17
493 */
494 public function update()
495 {
496 $feed = $this->fetch_feed();
497 $option = $this->get_option();
498
499 update_option(
500 'cff_notifications',
501 array(
502 'update' => cff_get_current_time(),
503 'feed' => $feed,
504 'events' => $option['events'],
505 'dismissed' => $option['dismissed'],
506 )
507 );
508 }
509
510 /**
511 * Admin area Form Overview enqueues.
512 *
513 * @since 2.18/3.17
514 */
515 public function enqueues()
516 {
517 if (! $this->has_access()) {
518 return;
519 }
520
521 $notifications = $this->get();
522
523 if (empty($notifications)) {
524 return;
525 }
526
527 $min = '';
528
529 wp_enqueue_style(
530 'cff-admin-notifications',
531 CFF_PLUGIN_URL . "admin/assets/css/admin-notifications{$min}.css",
532 array(),
533 CFFVER
534 );
535
536 wp_enqueue_script(
537 'cff-admin-notifications',
538 CFF_PLUGIN_URL . "admin/assets/js/admin-notifications{$min}.js",
539 array( 'jquery' ),
540 CFFVER,
541 true
542 );
543 }
544
545 /**
546 * Fields from the remote source contain placeholders to allow
547 * some messages to be used for multiple plugins.
548 *
549 * @param $content string
550 * @param $notification array
551 *
552 * @return string
553 *
554 * @since 2.18/3.17
555 */
556 public function replace_merge_fields($content, $notification)
557 {
558 $merge_fields = array(
559 '{plugin}' => 'Custom Facebook Feed',
560 '{amount}' => isset($notification['amount']) ? $notification['amount'] : '',
561 '{platform}' => 'Facebook',
562 '{lowerplatform}' => 'facebook',
563 '{review-url}' => 'https://wordpress.org/support/plugin/custom-facebook-feed/reviews/',
564 '{slug}' => 'custom-facebook-feed',
565 '{campaign}' => 'facebook-free'
566 );
567
568 if (CFF_Utils::cff_is_pro_version()) {
569 $merge_fields['{campaign}'] = 'facebook-pro';
570 $merge_fields['{plugin}'] = 'Custom Facebook Feed Pro';
571 }
572
573 foreach ($merge_fields as $find => $replace) {
574 $content = str_replace($find, $replace, $content);
575 }
576
577 return $content;
578 }
579
580 /**
581 * Output notifications on Custom Facebook Feed admin area.
582 *
583 * @since 2.18/3.17
584 */
585 public function output()
586 {
587 // if we are one single feed page then return
588 if (isset($_GET['feed_id'])) {
589 return;
590 }
591
592 $notifications = $this->get();
593
594 if (empty($notifications)) {
595 return;
596 }
597
598 $notifications_html = '';
599 $current_class = ' current';
600 $content_allowed_tags = array(
601 'em' => array(),
602 'strong' => array(),
603 'span' => array(
604 'style' => array(),
605 ),
606 'a' => array(
607 'href' => array(),
608 'target' => array(),
609 'rel' => array(),
610 ),
611 );
612
613 foreach ($notifications as $notification) {
614 $type = $notification['id'];
615 // Buttons HTML.
616 $buttons_html = '';
617 if (! empty($notification['btns']) && is_array($notification['btns'])) {
618 foreach ($notification['btns'] as $btn_type => $btn) {
619 if ($type == 'review' || $type == 'discount') {
620 $btn_class = $btn_type === 'primary' ? 'cff-btn-blue' : 'cff-btn-grey';
621 } else {
622 $btn_class = $btn_type === 'primary' ? 'cff-btn-orange' : 'cff-btn-grey';
623 }
624 if (is_array($btn['url'])) {
625 $btn['url'] = add_query_arg($btn['url']);
626 }
627 if (! empty($btn['attr'])) {
628 $btn['target'] = '_blank';
629 }
630 if (empty($btn['class'])) {
631 $btn['class'] = '';
632 }
633 $buttons_html .= sprintf(
634 '<a href="%1$s" class="cff-btn %2$s %3$s %6$s"%4$s>%5$s</a>',
635 ! empty($btn['url']) ? esc_url($this->replace_merge_fields($btn['url'], $notification)) : '',
636 $btn['class'],
637 $btn_class,
638 ! empty($btn['target']) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
639 ! empty($btn['text']) ? sanitize_text_field($btn['text']) : '',
640 !empty($notification['id']) && $notification['id'] === 'review' ? ' cff_notice_dismiss' : ''
641 );
642 }
643 $buttons_html = ! empty($buttons_html) ? '<div class="buttons">' . $buttons_html . '</div>' : '';
644 }
645
646 if (empty($notification['image'])) {
647 $image_html = '<div class="bell">';
648
649 $image_html .= '<svg xmlns="http://www.w3.org/2000/svg" width="42" height="48" viewBox="0 0 42 48" aria-hidden="true" focusable="false"><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>';
650 $image_html .= '</div>';
651 } else {
652 if ($notification['image'] === 'balloon') {
653 $image_html = '<div class="bell">';
654
655 $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" aria-hidden="true" focusable="false">';
656 $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="#FE544F"/>';
657 $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"/>';
658 $image_html .= '</svg>';
659 } elseif ($notification['id'] === 'review' || $notification['id'] === 'discount') {
660 $image_html = sprintf(
661 '<div class="bell"><img src="%s" alt="notice">',
662 CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field($notification['image'])
663 );
664 } else {
665 $image_html = '<div class="thumb">';
666 $img_src = CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field($notification['image']);
667 $image_html .= '<img src="' . esc_url($img_src) . '" alt="notice">';
668
669 if (isset($notification['image_overlay'])) {
670 $image_html .= '<div class="img-overlay">' . esc_html(str_replace('%', '%%', $notification['image_overlay'])) . '</div>';
671 }
672 }
673 $image_html .= '</div>';
674 }
675
676 // Check if it's review notice then show step #1
677 if ($type == 'review') {
678 $step1_img = CFF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field($notification['image']);
679 $step1_img_html = sprintf('<div class="bell"><img src="%s" alt="notice"></div>', $step1_img);
680
681 $review_consent = get_option('cff_review_consent');
682 $cff_open_feedback_url = 'https://smashballoon.com/feedback/?plugin=facebook-lite&utm_campaign=facebook-free&utm_source=notifications&utm_medium=feedback';
683 // step #1 for the review notice
684 if (! $review_consent) {
685 $step1_btns = sprintf(
686 '<button class="cff-btn-link" id="cff_review_consent_yes">%s</button>',
687 __('Yes', 'custom-facebook-feed')
688 );
689 $step1_btns .= sprintf(
690 '<a href="%s" target="_blank" class="cff-btn-link" id="cff_review_consent_no">%s</a>',
691 $cff_open_feedback_url,
692 __('No', 'custom-facebook-feed')
693 );
694 $notifications_html .= sprintf(
695 '<div class="cff_review_step1_notice" data-message-id="%3$s">' . $step1_img_html . '
696 <h3 class="title">%1$s</h3>
697 <div class="review-step-1-btns">%2$s</div>
698 </div>',
699 __('Are you enjoying the Custom Facebook Feed Plugin?', 'custom-facebook-feed'),
700 $step1_btns,
701 ! empty($notification['id']) ? esc_attr(sanitize_text_field($notification['id'])) : 0
702 );
703 }
704 }
705
706 $review_consent = get_option('cff_review_consent');
707 $review_step2_style = '';
708 if ($type == 'review' && ! $review_consent) {
709 $review_step2_style = 'style="display: none;"';
710 }
711
712 // Build the notification HTML for review notice
713 if ($type == 'review') {
714 $notifications_html .= sprintf(
715 '<div class="message%5$s %7$s" data-message-id="%4$s" %6$s>' . $image_html . '
716 <h3 class="title">%1$s</h3>
717 <p class="content">%2$s</p>
718 %3$s
719 </div>',
720 __('Glad to hear you are enjoying it. Would you consider leaving a positive review?', 'custom-facebook-feed'),
721 __('It really helps to support the plugin and help others to discover it too!', 'custom-facebook-feed'),
722 $buttons_html,
723 ! empty($notification['id']) ? esc_attr(sanitize_text_field($notification['id'])) : 0,
724 $current_class,
725 ( $notification['id'] == 'review' && ! empty($review_step2_style) ) ? $review_step2_style : '',
726 ( $type == 'review' ) ? 'rn_step_2' : ''
727 );
728 } elseif ($type == 'discount') {
729 // Build the notification HTML for discount notice
730 $notifications_html .= sprintf(
731 '<div class="message%5$s %7$s" data-message-id="%4$s" %6$s>' . $image_html . '
732 <h3 class="title">%1$s</h3>
733 <p class="content">%2$s</p>
734 %3$s
735 </div>',
736 __('Exclusive Offer! 60% OFF', 'custom-facebook-feed'),
737 __('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'),
738 $buttons_html,
739 ! empty($notification['id']) ? esc_attr(sanitize_text_field($notification['id'])) : 0,
740 $current_class,
741 ( $notification['id'] == 'review' && ! empty($review_step2_style) ) ? $review_step2_style : '',
742 ( $type == 'review' && ! $review_consent ) ? 'rn_step_2' : ''
743 );
744 } else {
745 // Notification HTML for other notices
746 $notifications_html .= sprintf(
747 '<div class="message%5$s" data-message-id="%4$s" %6$s>' . $image_html . '
748 <h3 class="title">%1$s</h3>
749 <p class="content">%2$s</p>
750 %3$s
751 </div>',
752 ! empty($notification['title']) ? $this->replace_merge_fields(sanitize_text_field($notification['title']), $notification) : '',
753 ! empty($notification['content']) ? wp_kses($this->replace_merge_fields($notification['content'], $notification), $content_allowed_tags) : '',
754 $buttons_html,
755 ! empty($notification['id']) ? esc_attr(sanitize_text_field($notification['id'])) : 0,
756 $current_class,
757 ( $notification['id'] == 'review' && ! empty($review_step2_style) ) ? $review_step2_style : ''
758 );
759 }
760
761 // Only first notification is current.
762 $current_class = '';
763 }
764
765 $close_href = add_query_arg(array( 'cff_dismiss' => $type ));
766 $class = '';
767 if ($type === 'review' || $type === 'discount') {
768 $class = $type === 'review' ? ' cff_review_notice' : ' cff_discount_notice';
769 }
770 ?>
771
772 <div id="cff-notifications" class="<?php echo esc_attr($class); ?>">
773 <a
774 class="dismiss"
775 title="<?php echo esc_attr__('Dismiss this message', 'custom-facebook-feed'); ?>"
776 <?php echo ( $type == 'review' || $type == 'discount' ) ? 'href="' . esc_attr($close_href) . '"' : '' ?>
777 >
778 <svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
779 <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"/>
780 </svg>
781 </a>
782
783 <?php if (count($notifications) > 1) : ?>
784 <div class="navigation">
785 <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>
786 <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>
787 </div>
788 <?php endif; ?>
789
790 <div class="messages">
791 <?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
792 </div>
793 </div>
794 <?php
795 }
796
797 /**
798 * Dismiss notification via AJAX. If it's a new user message, also dismiss it
799 * on all admin pages.
800 *
801 * @since 2.18/3.17
802 */
803 public function dismiss()
804 {
805 // Run a security check.
806 check_ajax_referer('cff-admin', 'nonce');
807
808 // Check for access and required param.
809 if (! $this->has_access() || empty($_POST['id'])) {
810 wp_send_json_error();
811 }
812
813 $id = sanitize_text_field(wp_unslash($_POST['id']));
814
815 if ($id === 'review') {
816 $cff_statuses_option = get_option('cff_statuses', array());
817
818 update_option('cff_rating_notice', 'dismissed', false);
819 $cff_statuses_option['rating_notice_dismissed'] = cff_get_current_time();
820 update_option('cff_statuses', $cff_statuses_option, false);
821 } elseif ($id === 'discount') {
822 update_user_meta(get_current_user_id(), 'cff_ignore_new_user_sale_notice', 'always');
823
824 $current_month_number = (int)date('n', cff_get_current_time());
825 $not_early_in_the_year = ($current_month_number > 5);
826
827 if ($not_early_in_the_year) {
828 update_user_meta(get_current_user_id(), 'cff_ignore_bfcm_sale_notice', date('Y', cff_get_current_time()));
829 }
830 }
831
832 $option = $this->get_option();
833 $type = is_numeric($id) ? 'feed' : 'events';
834
835 $option['dismissed'][] = $id;
836 $option['dismissed'] = array_unique($option['dismissed']);
837
838 // Remove notification.
839 if (is_array($option[ $type ]) && ! empty($option[ $type ])) {
840 foreach ($option[ $type ] as $key => $notification) {
841 if ($notification['id'] == $id) { // phpcs:ignore WordPress.PHP.StrictComparisons
842 unset($option[ $type ][ $key ]);
843 break;
844 }
845 }
846 }
847
848 update_option('cff_notifications', $option);
849
850 wp_send_json_success();
851 }
852 }
853