PluginProbe ʕ •ᴥ•ʔ
Custom Twitter Feeds – A Tweets Widget or X Feed Widget / 2.7.0
Custom Twitter Feeds – A Tweets Widget or X Feed Widget v2.7.0
2.8.0 2.7.0 2.6.1 2.6.0 1.0 1.0.1 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.2 1.2.1 1.2.10 1.2.11 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.4 1.4.1 1.5 1.5.1 1.6 1.6.1 1.7 1.8 1.8.1 1.8.2 1.8.3 1.8.4 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1 2.1.1 2.1.2 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.5.4 2.5.5 trunk
custom-twitter-feeds / inc / Admin / CTF_New_User.php
custom-twitter-feeds / inc / Admin Last commit date
Traits 1 month ago CTF_About_Us.php 1 month ago CTF_Admin_Notices.php 1 month ago CTF_Cache_Handler.php 1 month ago CTF_Global_Settings.php 1 month ago CTF_HTTP_Request.php 1 month ago CTF_New_User.php 1 month ago CTF_Notifications.php 1 month ago CTF_Response.php 1 month ago CTF_Support.php 1 month ago CTF_Upgrader.php 1 month ago CTF_View.php 1 month ago PluginSilentUpgrader.php 1 month ago PluginSilentUpgraderSkin.php 1 month ago SB_Twitter_Cache.php 1 month ago addon-functions.php 1 month ago class-install-skin.php 1 month ago
CTF_New_User.php
560 lines
1 <?php
2 /**
3 * CTF_New_User.
4 *
5 * @since 2.18
6 */
7 namespace TwitterFeed\Admin;
8
9 // Exit if accessed directly
10 use TwitterFeed\Builder\CTF_Db;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 class CTF_New_User extends CTF_Notifications {
17
18 /**
19 * Source of notifications content.
20 *
21 * @since 2.0
22 *
23 * @var string
24 */
25 const SOURCE_URL = 'https://plugin.smashballoon.com/newuser.json';
26
27 /**
28 * @var string
29 */
30 const OPTION_NAME = 'ctf_newuser_notifications';
31
32 /**
33 * Register hooks.
34 *
35 * @since 2.0
36 */
37 public function hooks() {
38 add_action( 'admin_init', array( $this, 'dismiss' ) );
39 add_action( 'wp_ajax_ctf_review_notice_consent_update', array( $this, 'review_notice_consent' ) );
40 }
41
42 public function option_name() {
43 return self::OPTION_NAME;
44 }
45
46 public function source_url() {
47 return self::SOURCE_URL;
48 }
49
50 /**
51 * Verify notification data before it is saved.
52 *
53 * @param array $notifications Array of notifications items to verify.
54 *
55 * @return array
56 *
57 * @since 2.0
58 */
59 public function verify( $notifications ) {
60 $data = array();
61
62 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
63 return $data;
64 }
65
66 $option = $this->get_option();
67
68 foreach ( $notifications as $key => $notification ) {
69
70 // The message should never be empty, if they are, ignore.
71 if ( empty( $notification['content'] ) ) {
72 continue;
73 }
74
75 // Ignore if notification has already been dismissed.
76 if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
77 continue;
78 }
79
80 $data[ $key ] = $notification;
81 }
82
83 return $data;
84 }
85
86 /**
87 * Verify saved notification data for active notifications.
88 *
89 * @since 2.0
90 *
91 * @param array $notifications Array of notifications items to verify.
92 *
93 * @return array
94 */
95 public function verify_active( $notifications ) {
96 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
97 return array();
98 }
99
100 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
101 $current_time = ctf_get_current_time();
102
103 // rating notice logic
104 $ctf_rating_notice_option = get_option( 'ctf_rating_notice', false );
105 $ctf_rating_notice_waiting = get_transient( 'custom_twitter_feeds_rating_notice_waiting' );
106 $should_show_rating_notice = ($ctf_rating_notice_waiting !== 'waiting' && $ctf_rating_notice_option !== 'dismissed');
107
108 // new user discount logic
109 $in_new_user_month_range = true;
110 $should_show_new_user_discount = false;
111 $has_been_one_month_since_rating_dismissal = isset( $ctf_statuses_option['rating_notice_dismissed'] ) ? ((int)$ctf_statuses_option['rating_notice_dismissed'] + ((int)$notifications['review']['wait'] * DAY_IN_SECONDS)) < $current_time + 1: true;
112
113 if ( isset( $ctf_statuses_option['first_install'] ) && $ctf_statuses_option['first_install'] === 'from_update' ) {
114 global $current_user;
115 $user_id = $current_user->ID;
116 $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice' );
117 $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
118 if ( $ignore_new_user_sale_notice_meta !== 'always' ) {
119 $should_show_new_user_discount = true;
120 }
121 } elseif ( $in_new_user_month_range && $has_been_one_month_since_rating_dismissal && $ctf_rating_notice_waiting !== 'waiting' ) {
122 global $current_user;
123 $user_id = $current_user->ID;
124 $ignore_new_user_sale_notice_meta = get_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice' );
125 $ignore_new_user_sale_notice_meta = isset( $ignore_new_user_sale_notice_meta[0] ) ? $ignore_new_user_sale_notice_meta[0] : '';
126
127 if ( $ignore_new_user_sale_notice_meta !== 'always'
128 && isset( $ctf_statuses_option['first_install'] )
129 && $current_time > (int)$ctf_statuses_option['first_install'] + ((int)$notifications['discount']['wait'] * DAY_IN_SECONDS) ) {
130 $should_show_new_user_discount = true;
131 }
132 }
133
134 if ( ctf_is_pro_version() ) {
135 $should_show_new_user_discount = false;
136 }
137
138 if ( isset( $notifications['review'] ) && $should_show_rating_notice ) {
139 return array( $notifications['review'] );
140 } elseif ( isset( $notifications['discount'] ) && $should_show_new_user_discount ) {
141 return array( $notifications['discount'] );
142 }
143
144 return array();
145 }
146
147 /**
148 * Get notification data.
149 *
150 * @since 2.0
151 *
152 * @return array
153 */
154 public function get() {
155 if ( ! $this->has_access() ) {
156 return array();
157 }
158
159 $option = $this->get_option();
160
161 $ctf_options = get_option( 'ctf_options', array() );
162
163 if ( empty( $ctf_options[ CTF_SITE_ACCESS_TOKEN_KEY ] ) ) {
164 $feeds_count = CTF_Db::feeds_count();
165 if ( $feeds_count > 0 ) {
166 $notifications = array(
167 array(
168 'title' => 'Twitter API Changes',
169 'content' => 'Using Custom Twitter Feeds now requires that you connect with Smash Balloon and create a site key. Click the button below to visit our website and verify an email address to get started.',
170 'image' => 'balloon',
171 'type' => array( 'free' ),
172 'id' => 'freeconnect',
173 'recent_install_override' => true,
174 "btns" => array(
175 'primary' => array(
176 'url' => ctf_oauth_url( admin_url( 'admin.php?page=ctf-settings' ) ),
177 'text' => 'Connect',
178 'attr' => array(
179 )
180 )
181 ),
182 'start' => '2022-02-08 00:00:00',
183 'end' => '2030-02-08 00:00:00',
184 )
185 );
186 return $notifications;
187 }
188
189 }
190
191 // Only update if does not exist.
192 if ( empty( $option['update'] ) ) {
193 $this->update();
194 }
195
196 $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : array();
197 $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : array();
198
199 return array_merge( $events, $feed );
200 }
201
202 /**
203 * Add a manual notification event.
204 *
205 * @since 2.0
206 *
207 * @param array $notification Notification data.
208 */
209 public function add( $notification ) {
210 if ( empty( $notification['id'] ) ) {
211 return;
212 }
213
214 $option = $this->get_option();
215
216 if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
217 return;
218 }
219
220 foreach ( $option['events'] as $item ) {
221 if ( $item['id'] === $notification['id'] ) {
222 return;
223 }
224 }
225
226 $notification = $this->verify( array( $notification ) );
227
228 update_option(
229 $this->option_name(),
230 array(
231 'update' => $option['update'],
232 'feed' => $option['feed'],
233 'events' => array_merge( $notification, $option['events'] ),
234 'dismissed' => $option['dismissed'],
235 )
236 );
237 }
238
239 /**
240 * Update notification data from feed.
241 *
242 * @since 2.0
243 */
244 public function update() {
245 $feed = $this->fetch_feed();
246 $option = $this->get_option();
247
248 update_option(
249 $this->option_name(),
250 array(
251 'update' => time(),
252 'feed' => $feed,
253 'events' => $option['events'],
254 'dismissed' => $option['dismissed'],
255 )
256 );
257 }
258
259 /**
260 * Do not enqueue anything extra.
261 *
262 * @since 2.0
263 */
264 public function enqueues() {
265
266 }
267
268 public function review_notice_consent() {
269 //Security Checks
270 check_ajax_referer( 'ctf-admin', 'ctf_nonce' );
271 $cap = ctf_get_manage_options_cap();
272
273 if ( ! current_user_can( $cap ) ) {
274 wp_send_json_error(); // This auto-dies.
275 }
276
277 $consent = isset( $_POST[ 'consent' ] ) ? sanitize_text_field( $_POST[ 'consent' ] ) : '';
278
279 update_option( 'ctf_review_consent', $consent );
280
281 if ( $consent == 'no' ) {
282 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
283 update_option( 'ctf_rating_notice', 'dismissed', false );
284 $ctf_statuses_option['rating_notice_dismissed'] = ctf_get_current_time();
285 update_option( 'ctf_statuses', $ctf_statuses_option, false );
286 }
287 wp_die();
288 }
289
290 /**
291 * Output notifications on Form Overview admin area.
292 *
293 * @since 2.0
294 */
295 public function output() {
296 $notifications = $this->get();
297
298 if ( empty( $notifications ) ) {
299 return;
300 }
301
302 if ( function_exists( 'display_instagram' ) ) {
303 return;
304 }
305
306 if ( function_exists( 'cff_check_for_db_updates' ) ) {
307 return;
308 }
309 // new user notices included in regular settings page notifications so this
310 // checks to see if user is one of those pages
311 if ( ! empty( $_GET['page'] )
312 && strpos( $_GET['page'], 'ctf' ) !== false ) {
313 return;
314 }
315
316 $content_allowed_tags = array(
317 'em' => array(),
318 'strong' => array(),
319 'span' => array(
320 'style' => array(),
321 ),
322 'a' => array(
323 'href' => array(),
324 'target' => array(),
325 'rel' => array(),
326 ),
327 );
328 $image_overlay = '';
329
330 foreach ( $notifications as $notification ) {
331 $img_src = CTF_PLUGIN_URL . 'admin/assets/img/' . sanitize_text_field( $notification['image'] );
332 $type = sanitize_text_field( $notification['id'] );
333 // check if this is a review notice
334 if( $type == 'review' ) {
335 $review_consent = get_option( 'ctf_review_consent' );
336 $ctf_open_feedback_url = 'https://smashballoon.com/feedback/?plugin=twitter-free&utm_campaign=twitter-free&utm_source=notifications&utm_medium=feedback';
337 // step #1 for the review notice
338 if ( ! $review_consent ) {
339 ?>
340 <div class="ctf_notice ctf_review_notice_step_1">
341 <div class="ctf_thumb">
342 <img src="<?php echo esc_url( str_replace( array( 'sbi', 'png' ), array( 'ctf', 'svg' ), $img_src ) ); ?>" alt="notice">
343 </div>
344 <div class="ctf-notice-text">
345 <p class="ctf-notice-text-p"><?php echo __( 'Are you enjoying the Twitter Feed Plugin?', 'custom-twitter-feeds' ); ?></p>
346 </div>
347 <div class="ctf-notice-consent-btns">
348 <?php
349 printf(
350 '<button class="ctf-btn-link" id="ctf_review_consent_yes">%s</button>',
351 __( 'Yes', 'custom-twitter-feeds' )
352 );
353
354 printf(
355 '<a href="%s" target="_blank" rel="nofollow noopener" class="ctf-btn-link" id="ctf_review_consent_no">%s</a>',
356 $ctf_open_feedback_url,
357 __( 'No', 'custom-twitter-feeds' )
358 );
359 ?>
360 </div>
361 </div>
362 <?php
363 }
364 }
365 $close_href = add_query_arg( array( 'ctf_dismiss' => $type ) );
366
367 $title = $this->get_notice_title( $notification );
368 $content = $this->get_notice_content( $notification, $content_allowed_tags );
369
370 $buttons = array();
371 if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
372 foreach ( $notification['btns'] as $btn_type => $btn ) {
373 if ( ! is_array( $btn['url'] ) ) {
374 $buttons[ $btn_type ]['url'] = $this->replace_merge_fields( $btn['url'], $notification );
375 } elseif ( is_array( $btn['url'] ) ) {
376 $buttons[ $btn_type ]['url'] = add_query_arg( $btn['url'] );
377 }
378
379 $buttons[ $btn_type ]['attr'] = '';
380 if ( ! empty( $btn['attr'] ) ) {
381 $buttons[ $btn_type ]['attr'] = ' target="_blank" rel="noopener noreferrer"';
382 }
383
384 $buttons[ $btn_type ]['class'] = '';
385 if ( ! empty( $btn['class'] ) ) {
386 $buttons[ $btn_type ]['class'] = ' ' . $btn['class'];
387 }
388
389 $buttons[ $btn_type ]['text'] = '';
390 if ( ! empty( $btn['text'] ) ) {
391 $buttons[ $btn_type ]['text'] = wp_kses( $btn['text'], $content_allowed_tags );
392 }
393 }
394 }
395 }
396
397 $review_consent = get_option( 'ctf_review_consent' );
398 $review_step2_style = '';
399 if ( $type == 'review' && ! $review_consent ) {
400 $review_step2_style = 'style="display: none;"';
401 }
402 ?>
403
404 <div class="ctf_notice_op ctf_notice ctf_<?php echo esc_attr( $type ); ?>_notice" <?php echo !empty( $review_step2_style ) ? $review_step2_style : ''; ?>>
405 <div class="ctf_thumb">
406 <img src="<?php echo esc_url( str_replace( array( 'sbi', 'png' ), array( 'ctf', 'svg' ), $img_src ) ); ?>" alt="notice">
407 <?php echo $image_overlay; ?>
408 </div>
409 <div class="ctf-notice-text">
410 <div class="ctf-notice-text-inner">
411 <h3 class="ctf-notice-text-header"><?php echo $title; ?></h3>
412 <p class="ctf-notice-text-p"><?php echo $content; ?></p>
413 </div>
414 <div class="ctf-notice-btns-wrap">
415 <p class="ctf-notice-links">
416 <?php
417 foreach ( $buttons as $type => $button ) :
418 $btn_classes = array('ctf-btn');
419 $btn_classes[] = esc_attr( $button['class'] );
420 if ( $type == 'primary' ) {
421 $btn_classes[] = 'ctf-btn-blue';
422 } else {
423 $btn_classes[] = 'ctf-btn-grey';
424 }
425 ?>
426 <a class="<?php echo implode(' ', $btn_classes); ?>" href="<?php echo esc_attr( str_replace( 'sbi_', 'ctf_', $button['url'] ) ); ?>"<?php echo $button['attr']; ?>><?php echo $button['text']; ?></a>
427 <?php endforeach; ?>
428 </p>
429 </div>
430 </div>
431 <div class="ctf-notice-dismiss">
432 <a href="<?php echo esc_url( $close_href ); ?>">
433 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
434 <path d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z" fill="#141B38"></path>
435 </svg>
436 </a>
437 </div>
438 </div>
439 <?php
440 }
441
442 /**
443 * CTF Get Notice Title depending on the notice type
444 *
445 * @since 6.0
446 *
447 * @param array $notification
448 *
449 * @return string $title
450 */
451 public function get_notice_title( $notification ) {
452 $type = $notification['id'];
453 $title = '';
454
455 // Notice title depending on notice type
456 if ( $type == 'review' ) {
457 $title = __( 'Glad to hear you are enjoying it. Would you consider leaving a positive review?', 'custom-twitter-feeds' );
458 } else if ( $type == 'discount' ) {
459 $title = __( 'Exclusive Offer! 60% OFF', 'custom-twitter-feeds' );
460 } else {
461 $title = $this->replace_merge_fields( $notification['title'], $notification );
462 }
463
464 return $title;
465 }
466
467 /**
468 * CTF Get Notice Content depending on the notice type
469 *
470 * @since 6.0
471 *
472 * @param array $notification
473 * @param array $content_allowed_tags
474 *
475 * @return string $content
476 */
477 public function get_notice_content( $notification, $content_allowed_tags ) {
478 $type = $notification['id'];
479 $content = '';
480
481 // Notice content depending on notice type
482 if ( $type == 'review' ) {
483 $content = __( 'It really helps to support the plugin and help others to discover it too!', 'custom-twitter-feeds' );
484 } else if ( $type == 'discount' ) {
485 $content = __( '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 Twitter Feed.', 'custom-twitter-feeds' );
486 } else {
487 if ( ! empty( $notification['content'] ) ) {
488 $content = wp_kses( $this->replace_merge_fields( $notification['content'], $notification ), $content_allowed_tags );
489 }
490 }
491 return $content;
492 }
493
494 /**
495 * Hide messages permanently or some can be dismissed temporarily
496 *
497 * @since 2.0
498 */
499 public function dismiss() {
500 global $current_user;
501 $user_id = $current_user->ID;
502 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
503
504 if ( isset( $_GET['ctf_ignore_rating_notice_nag'] ) ) {
505 if ( (int)$_GET['ctf_ignore_rating_notice_nag'] === 1 ) {
506 update_option( 'ctf_rating_notice', 'dismissed', false );
507 $ctf_statuses_option['rating_notice_dismissed'] = ctf_get_current_time();
508 update_option( 'ctf_statuses', $ctf_statuses_option, false );
509
510 } elseif ( $_GET['ctf_ignore_rating_notice_nag'] === 'later' ) {
511 set_transient( 'custom_twitter_feeds_rating_notice_waiting', 'waiting', 2 * WEEK_IN_SECONDS );
512 update_option( 'ctf_rating_notice', 'pending', false );
513 }
514 }
515
516 if ( isset( $_GET['ctf_ignore_new_user_sale_notice'] ) ) {
517 $response = sanitize_text_field( $_GET['ctf_ignore_new_user_sale_notice'] );
518 if ( $response === 'always' ) {
519 update_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice', 'always' );
520
521 $current_month_number = (int)date('n', ctf_get_current_time() );
522 $not_early_in_the_year = ($current_month_number > 5);
523
524 if ( $not_early_in_the_year ) {
525 update_user_meta( $user_id, 'ctf_ignore_bfcm_sale_notice', date( 'Y', ctf_get_current_time() ) );
526 }
527
528 }
529 }
530
531 if ( isset( $_GET['ctf_ignore_bfcm_sale_notice'] ) ) {
532 $response = sanitize_text_field( $_GET['ctf_ignore_bfcm_sale_notice'] );
533 if ( $response === 'always' ) {
534 update_user_meta( $user_id, 'ctf_ignore_bfcm_sale_notice', 'always' );
535 } elseif ( $response === date( 'Y', ctf_get_current_time() ) ) {
536 update_user_meta( $user_id, 'ctf_ignore_bfcm_sale_notice', date( 'Y', ctf_get_current_time() ) );
537 }
538 update_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice', 'always' );
539 }
540
541 if ( isset( $_GET['ctf_dismiss'] ) ) {
542 if ( $_GET['ctf_dismiss'] === 'review' ) {
543 update_option( 'ctf_rating_notice', 'dismissed', false );
544 $ctf_statuses_option['rating_notice_dismissed'] = ctf_get_current_time();
545 update_option( 'ctf_statuses', $ctf_statuses_option, false );
546 } elseif ( $_GET['ctf_dismiss'] === 'discount' ) {
547 update_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice', 'always' );
548
549 $current_month_number = (int)date('n', ctf_get_current_time() );
550 $not_early_in_the_year = ($current_month_number > 5);
551
552 if ( $not_early_in_the_year ) {
553 update_user_meta( $user_id, 'ctf_ignore_bfcm_sale_notice', date( 'Y', ctf_get_current_time() ) );
554 }
555 }
556 update_user_meta( $user_id, 'ctf_ignore_new_user_sale_notice', 'always' );
557 }
558 }
559 }
560