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 / custom-twitter-feed.php
custom-twitter-feeds Last commit date
admin 1 month ago css 1 month ago img 1 month ago inc 1 month ago js 1 month ago languages 1 month ago templates 1 month ago vendor 1 month ago views 1 month ago README.md 1 month ago README.txt 1 month ago changelog.txt 1 month ago custom-twitter-feed.php 1 month ago uninstall.php 1 month ago
custom-twitter-feed.php
1160 lines
1 <?php
2
3 use TwitterFeed\Builder\CTF_Feed_Builder;
4 /*
5 Plugin Name: Custom Twitter Feeds
6 Plugin URI: https://smashballoon.com/custom-twitter-feeds
7 Description: Customizable X Feeds, formerly known as Twitter feeds, for your website
8 Version: 2.7.0
9 Author: Smash Balloon
10 Author URI: https://smashballoon.com/
11 Text Domain: custom-twitter-feeds
12 */
13 /*
14 Copyright 2025 Smash Balloon LLC (email : hey@smashballoon.com)
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 if ( ! defined( 'CTF_URL' ) ) {
29 // Use smash Twitter if API V2 credentials are not defined.
30 $ctf_options = get_option('ctf_options', array());
31 define( 'CTF_DOING_SMASH_TWITTER', empty($ctf_options['consumer_key']) && empty($ctf_options['consumer_secret']));
32
33 define( 'CTF_URL', plugin_dir_path( __FILE__ ) );
34 define( 'CTF_VERSION', '2.7.0' );
35 define( 'CTF_TITLE', 'Custom Twitter Feeds' );
36 define( 'CTF_JS_URL', plugins_url( '/js/ctf-scripts.min.js?ver=' . CTF_VERSION , __FILE__ ) );
37 define( 'CTF_PRODUCT_NAME', 'Custom Twitter Feeds' );
38 }
39
40 if ( ! defined( 'CTF_SITE_ACCESS_TOKEN_KEY' ) ) {
41 define( 'CTF_SITE_ACCESS_TOKEN_KEY', 'site_access_token_free' );
42 }
43 if ( ! defined( 'SMASH_TWITTER_URL' ) ) {
44 define( 'SMASH_TWITTER_URL', 'https://ctf.smashballoon.com/api/' );
45 }
46 if ( ! defined( 'SMASH_TWITTER_TIMELINE_PATH' ) ) {
47 define( 'SMASH_TWITTER_TIMELINE_PATH', '1.1/timeline' );
48 }
49
50 if ( ! defined( 'SMASH_TWITTER_URL_EXTRA_GET_PARAMS' ) ) {
51 define( 'SMASH_TWITTER_URL_EXTRA_GET_PARAMS', '' );
52 }
53
54 if ( ! defined( 'OAUTH_PROCESSOR_URL' ) ) {
55 define( 'OAUTH_PROCESSOR_URL', 'https://connect.smashballoon.com/auth/tw/' );
56 }
57
58 if ( ! defined( 'CTF_PLUGIN_NAME' ) ) {
59 define( 'CTF_PLUGIN_NAME', 'Custom Twitter Feeds' );
60 }
61 if ( ! defined( 'CTF_SMASH_USAGE_TRACKING_API_URL' ) ) {
62 define( 'CTF_SMASH_USAGE_TRACKING_API_URL', 'https://usage.smashballoon.com/api' );
63 }
64
65 // Plugin Folder Path.
66 if ( ! defined( 'CTF_PLUGIN_DIR' ) ) {
67 define( 'CTF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
68 }
69 // Plugin Folder URL.
70 if ( ! defined( 'CTF_PLUGIN_URL' ) ) {
71 define( 'CTF_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
72 }
73 // Db version.
74 if ( ! defined( 'CTF_DBVERSION' ) ) {
75 define( 'CTF_DBVERSION', '1.5' );
76 }
77 if ( ! defined( 'CTF_FEED_LOCATOR' ) ) {
78 define( 'CTF_FEED_LOCATOR', 'ctf_feed_locator' );
79 }
80
81 if ( ! defined( 'CTF_BUILDER_DIR' ) ) {
82 define( 'CTF_BUILDER_DIR', CTF_PLUGIN_DIR . 'admin/builder/' );
83 }
84 if ( ! defined( 'CTF_BUILDER_URL' ) ) {
85 define( 'CTF_BUILDER_URL', CTF_PLUGIN_URL . 'admin/builder/' );
86 }
87 if ( ! defined( 'CTF_UPLOADS_NAME' ) ) {
88 define( 'CTF_UPLOADS_NAME', 'sb-twitter-feed-images' );
89 }
90
91 if ( ! defined( 'CTF_PLUGIN_NAME' ) ) {
92 define( 'CTF_PLUGIN_NAME', 'Custom Twitter Feed Free' );
93 }
94 if ( ! defined( 'CTF_FEEDS_POSTS_TABLE' ) ) {
95 define( 'CTF_FEEDS_POSTS_TABLE', 'ctf_feeds_posts' );
96 }
97 if ( ! defined( 'CTF_POSTS_TABLE' ) ) {
98 define( 'CTF_POSTS_TABLE', 'ctf_posts' );
99 }
100 if ( ! defined( 'CTF_LICENSE_URL' ) ) {
101 define( 'CTF_LICENSE_URL', 'https://smashballoon.com/' );
102 }
103
104 if ( ! defined( 'CTF_PLUGIN_BASENAME' ) ) {
105 define( 'CTF_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
106 }
107
108 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
109
110 if ( version_compare( phpversion(), '7.4', '<' ) ) {
111 if( !function_exists( 'ctf_check_php_notice' ) ){
112 function ctf_check_php_notice(){ ?>
113 <div class="notice notice-error">
114 <div>
115 <p><strong><?php echo esc_html__('Important:','custom-twitter-feeds') ?> </strong><?php echo esc_html__('Your website is using an outdated version of PHP. The Custom Twitter Feeds plugin requires PHP version 7.4 or higher and so has been temporarily deactivated.','custom-twitter-feeds') ?></p>
116
117 <p>
118 <?php
119 echo esc_html__('To continue using the plugin','custom-twitter-feeds') . ', ';
120
121 echo __('you can either manually reinstall the previous version of the plugin ','custom-twitter-feeds' );
122
123 echo esc_html__('or contact your host to request that they upgrade your PHP version to 7.4 or higher.','custom-twitter-feeds');
124 ?>
125 </p>
126 </div>
127 </div>
128 <?php
129 }
130 }
131 add_action( 'admin_notices', 'ctf_check_php_notice' );
132 return; //Stop until PHP version is fixed
133 }
134
135 require_once( CTF_URL . '/inc/widget.php' );
136
137 require_once( CTF_URL . '/inc/admin-hooks.php' );
138
139 function ctf_plugin_init() {
140 require_once trailingslashit( CTF_PLUGIN_DIR ) . 'inc/blocks/class-ctf-blocks.php';
141
142 $ctf_blocks = new CTF_Blocks();
143
144 if ( $ctf_blocks->allow_load() ) {
145 $ctf_blocks->load();
146 }
147
148 require trailingslashit( CTF_PLUGIN_DIR ) . 'vendor/autoload.php';
149 include_once trailingslashit( CTF_PLUGIN_DIR ) . '/inc/ctf-functions.php';
150
151 // Initialize modern feed block after autoloader is available (CTF_Modern_Feed_Block extends vendor SB_Feed_Block).
152 require_once trailingslashit( CTF_PLUGIN_DIR ) . 'inc/blocks/CTF_Modern_Feed_Block.php';
153 $modern_block = new \TwitterFeed\Admin\Blocks\CTF_Modern_Feed_Block();
154 $modern_block->register_hooks();
155
156 // Initialize the deactivation feedback survey.
157 if ( class_exists( '\Smashballoon\TwitterFeed\Vendor\Smashballoon\Framework\Packages\Feedback\FeedbackManager' ) ) {
158 \Smashballoon\TwitterFeed\Vendor\Smashballoon\Framework\Packages\Feedback\FeedbackManager::init(
159 [
160 'plugin_slug' => 'custom-twitter-feeds',
161 'plugin_name' => 'Smash Balloon Custom Twitter Feeds',
162 'plugin_version' => CTF_VERSION,
163 'plugin_file' => CTF_PLUGIN_DIR . 'custom-twitter-feed.php',
164 'support_url' => 'https://smashballoon.com/support/?utm_campaign=twitter-free&utm_source=plugin&utm_medium=support',
165 'enable_help_widget' => true,
166 'help_url' => 'https://smashballoon.com/docs/twitter/',
167 ]
168 );
169 }
170
171 if ( is_admin() ) {
172 if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0
173 && version_compare( get_bloginfo('version'), '4.6' , '>' ) ) {
174 $ctf_notifications = new TwitterFeed\Admin\CTF_Notifications();
175 $ctf_notifications->init();
176
177 $ctf_new_user = new TwitterFeed\Admin\CTF_New_User();
178 $ctf_new_user->init();
179
180 $ctf_global_settings = new TwitterFeed\Admin\CTF_Global_Settings();
181 $ctf_admin_notices = new TwitterFeed\Admin\CTF_Admin_Notices();
182 $ctf_tooltip_wizard = new TwitterFeed\Builder\CTF_Tooltip_Wizard();
183 $ctf_support = new TwitterFeed\Admin\CTF_Support();
184 $ctf_admin_notices = new TwitterFeed\Admin\CTF_Admin_Notices();
185 $ctf_about_us = new TwitterFeed\Admin\CTF_About_Us();
186
187
188 require_once trailingslashit( CTF_PLUGIN_DIR ) . 'inc/Admin/addon-functions.php';
189 }
190 }
191 require_once trailingslashit( CTF_PLUGIN_DIR ) . 'inc/Admin/CTF_Upgrader.php';
192 $ctf_upgrader = new TwitterFeed\Admin\CTF_Upgrader();
193 $ctf_upgrader->hooks();
194
195
196 $cron_update_manager = new \TwitterFeed\SmashTwitter\CronUpdaterManager();
197 $cron_update_manager->hooks();
198
199 $error_reporter = new \TwitterFeed\SmashTwitter\Services\ErrorReporterService();
200 $error_reporter->init_hooks();
201
202 $GLOBALS['ctf_smash_usage_tracking'] = new \TwitterFeed\UsageTracking\SmashUsageTracking();
203
204 // Initialize Elementor integration.
205 \TwitterFeed\Integrations\Elementor\CTF_Elementor_Base::register();
206
207 // Initialize recommended blocks in Gutenberg sidebar.
208 $recommended_blocks = new \Smashballoon\TwitterFeed\Vendor\Smashballoon\Framework\Packages\Blocks\RecommendedBlocks();
209 $recommended_blocks->setup();
210 }
211 add_action( 'plugins_loaded', 'ctf_plugin_init' );
212
213 include_once trailingslashit( CTF_PLUGIN_DIR ) . '/inc/Builder/CTF_Feed_Builder.php';
214
215
216 function ctf_update_settings() {
217 $existing_deprecated_options = get_option( 'ctf_configure' );
218 $existing_options = get_option( 'ctf_options' );
219
220 update_option( 'ctf_version', CTF_VERSION );
221
222 if ( ! empty( $existing_deprecated_options ) && empty( $existing_options ) ) {
223 $merged_options = $existing_deprecated_options;
224 $merged_options = array_merge( $merged_options, get_option( 'ctf_customize', array() ) );
225 $merged_options = array_merge( $merged_options, get_option( 'ctf_style', array() ) );
226
227 update_option( 'ctf_options', $merged_options );
228 }
229 }
230
231 function ctf_check_for_db_updates() {
232
233 $db_ver = get_option( 'ctf_db_version', 0 );
234
235 if ( (float) $db_ver < 1.0 ) {
236 global $wp_roles;
237 $wp_roles->add_cap( 'administrator', 'manage_twitter_feed_options' );
238
239 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
240
241 if ( ! isset( $ctf_statuses_option['first_install'] ) ) {
242
243 $options_set = get_option( 'ctf_options', false );
244
245 if ( $options_set ) {
246 $ctf_statuses_option['first_install'] = 'from_update';
247 } else {
248 $ctf_statuses_option['first_install'] = time();
249 }
250
251 $ctf_rating_notice_option = get_option( 'ctf_rating_notice', false );
252
253 if ( $ctf_rating_notice_option === 'dismissed' ) {
254 $ctf_statuses_option['rating_notice_dismissed'] = time();
255 }
256
257 $ctf_rating_notice_waiting = get_transient( 'custom_twitter_feeds_rating_notice_waiting' );
258
259 if ( $ctf_rating_notice_waiting === false
260 && $ctf_rating_notice_option === false ) {
261 $time = 2 * WEEK_IN_SECONDS;
262 set_transient( 'custom_twitter_feeds_rating_notice_waiting', 'waiting', $time );
263 update_option( 'ctf_rating_notice', 'pending', false );
264 }
265
266 update_option( 'ctf_statuses', $ctf_statuses_option, false );
267
268 }
269
270 update_option( 'ctf_db_version', CTF_DBVERSION );
271 }
272
273 if ( version_compare( $db_ver, '1.0.1', '<' ) ) {
274 TwitterFeed\CTF_Feed_Locator::create_table();
275 update_option( 'ctf_db_version', CTF_DBVERSION );
276 }
277
278 // For v2.0
279 if ( version_compare( $db_ver, '1.4', '<' ) ) {
280 update_option( 'ctf_db_version', CTF_DBVERSION );
281 \TwitterFeed\Builder\CTF_Db::create_tables();
282 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
283 $ctf_options = get_option( 'ctf_options', array() );
284
285 if ( ! isset( $ctf_statuses_option['first_install'] ) ) {
286
287 $options_set = get_option( 'ctf_options', false );
288
289 if ( $options_set ) {
290 $ctf_statuses_option['first_install'] = 'from_update';
291 } else {
292 $ctf_statuses_option['first_install'] = time();
293 }
294
295 $ctf_rating_notice_option = get_option( 'ctf_rating_notice', false );
296
297 if ( $ctf_rating_notice_option === 'dismissed' ) {
298 $ctf_statuses_option['rating_notice_dismissed'] = time();
299 }
300
301 $ctf_rating_notice_waiting = get_transient( 'custom_twitter_feeds_rating_notice_waiting' );
302
303 if ( $ctf_rating_notice_waiting === false
304 && $ctf_rating_notice_option === false ) {
305 $time = 2 * WEEK_IN_SECONDS;
306 set_transient( 'custom_twitter_feeds_rating_notice_waiting', 'waiting', $time );
307 update_option( 'ctf_rating_notice', 'pending', false );
308 }
309 }
310
311 //Legacy feeds
312 $options_support_legacy = false;
313
314 if ( isset( $ctf_options['access_token'] ) && ! empty( $ctf_options['access_token'] ) ) {
315 $options_support_legacy = true;
316 $base_settings = \TwitterFeed\CTF_Settings::legacy_shortcode_atts( array(), $ctf_options );
317 update_option( 'ctf_legacy_feed_settings', ctf_json_encode( $base_settings ), false );
318 }
319 // how many legacy feeds?
320 $args = array(
321 'html_location' => array( 'header', 'footer', 'sidebar', 'content', 'unknown' ),
322 'group_by' => 'shortcode_atts',
323 'page' => 1,
324 );
325
326 $feeds_data = \TwitterFeed\CTF_Feed_Locator::legacy_twitter_feed_locator_query( $args );
327 $num_legacy = count( $feeds_data );
328 $ctf_statuses_option['support_legacy_shortcode'] = $options_support_legacy;
329 if ( $num_legacy > 0 ) {
330 if ( $num_legacy > 1 ) {
331 $ctf_statuses_option['legacy_onboarding'] = array(
332 'active' => true,
333 'type' => 'multiple',
334 );
335 $ctf_statuses_option['support_legacy_shortcode'] = true;
336 } else {
337 $ctf_statuses_option['legacy_onboarding'] = array(
338 'active' => true,
339 'type' => 'single',
340 );
341
342 $shortcode_atts = ! empty( $feeds_data[0] ) && $feeds_data[0]['shortcode_atts'] != '[""]' ? json_decode( $feeds_data[0]['shortcode_atts'], true ) : array();
343 $shortcode_atts = is_array( $shortcode_atts ) ? $shortcode_atts : array();
344
345 $ctf_statuses_option['support_legacy_shortcode'] = $shortcode_atts;
346
347 $shortcode_atts['from_update'] = true;
348
349 $db = ctf_get_database_settings();
350 $base_settings = \TwitterFeed\CTF_Settings::legacy_shortcode_atts( $shortcode_atts, $db );
351
352 $feed_saver = new \TwitterFeed\Builder\CTF_Feed_Saver( false );
353 $feed_saver->set_data( $base_settings );
354
355 $feed_name = 'My Feed';
356 $feed_saver->set_feed_name( $feed_name );
357
358 $new_feed_id = $feed_saver->update_or_insert();
359
360 $args = array(
361 'new_feed_id' => $new_feed_id,
362 'legacy_feed_id' => $feeds_data[0]['feed_id'],
363 );
364
365 \TwitterFeed\CTF_Feed_Locator::update_legacy_to_builder( $args );
366 }
367 } elseif ( $num_legacy === 0 && $options_support_legacy ) {
368 $ctf_statuses_option['support_legacy_shortcode'] = true;
369 }
370
371 update_option( 'ctf_statuses', $ctf_statuses_option, false );
372 update_option( 'ctf_db_version', CTF_DBVERSION );
373
374 if ( ! wp_next_scheduled( 'ctf_feed_update' ) ) {
375 wp_schedule_event( time() + 60, 'twicedaily', 'ctf_feed_update' );
376 }
377
378 global $wp_roles;
379 $wp_roles->add_cap( 'administrator', 'manage_twitter_feed_options' );
380
381 }
382
383 // For Smash Twitter
384 if ( version_compare( $db_ver, '1.5', '<' ) ) {
385 update_option( 'ctf_db_version', CTF_DBVERSION );
386 global $wpdb;
387 ctf_create_database_table();
388 $table_name = $wpdb->prefix . CTF_FEEDS_POSTS_TABLE;
389
390 $wpdb->query( "ALTER TABLE $table_name ADD COLUMN type VARCHAR(1000) DEFAULT '' NOT NULL" );
391 $wpdb->query( "ALTER TABLE $table_name ADD COLUMN term VARCHAR(1000) DEFAULT '' NOT NULL" );
392 $wpdb->query( "ALTER TABLE $table_name ADD INDEX type_term (term(140),type(51))" );
393
394 \TwitterFeed\SmashTwitter\CronUpdaterManager::schedule_cron_job();
395
396 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
397 // to space out the API requests, we have the initial cron update scheduled a day + random number of hours.
398 $ctf_statuses_option['first_cron_update'] = mt_rand(0,23) * 3600 + time() + DAY_IN_SECONDS;
399 update_option( 'ctf_statuses', $ctf_statuses_option, false );
400
401 update_option( 'ctf_db_version', CTF_DBVERSION );
402
403 }
404
405 }
406 add_action( 'wp_loaded', 'ctf_check_for_db_updates' );
407
408
409 /**
410 * include the admin files only if in the admin area
411 */
412 if ( is_admin() ) {
413
414 $ctf_version = get_option( 'ctf_version', false );
415
416 if ( ! $ctf_version ) {
417 ctf_update_settings();
418 }
419 require_once( CTF_URL . '/inc/CtfAdmin.php' );
420 require_once( CTF_URL . '/inc/notices.php' );
421
422 $admin = new CtfAdmin;
423 }
424
425 /**
426 * Generates the Twitter feed wherever the shortcode is placed
427 *
428 * @param $atts array shortcode arguments
429 *
430 * @return string
431 */
432 function ctf_init( $atts, $preview_settings = false ) {
433 wp_enqueue_script( 'ctf_scripts' );
434 $twitter_feed = TwitterFeed\CtfFeed::init( $atts, null, 0, array(), 1, $preview_settings);
435 if ( isset( $twitter_feed->feed_options['feederror'] ) && ! empty( $twitter_feed->feed_options['feederror'] ) ) {
436 return "<span id='ctf-no-id'>" . sprintf( __( 'No feed found with the ID %1$s. Go to the %2$sAll Feeds page%3$s and select an ID from an existing feed.', 'custom-twitter-feeds' ), esc_html( $twitter_feed->feed_options['feed'] ), '<a href="' . esc_url( admin_url( 'admin.php?page=ctf-feed-builder' ) ) . '">', '</a>' ) . '</span><br /><br />';
437 } else {
438 // if there is an error, display the error html, otherwise the feed
439 if ( ! $twitter_feed->tweet_set || ($twitter_feed->missing_credentials && ! CTF_DOING_SMASH_TWITTER) || ! isset( $twitter_feed->tweet_set[0]['created_at'] ) ) {
440 if ( ! empty( $twitter_feed->tweet_set['errors'] ) ) {
441 $twitter_feed->maybeCacheTweets();
442 } else {
443 $twitter_feed->maybeCacheTweets(true);
444 }
445 $feed_html = '';
446 $feed_html .= $twitter_feed->getTweetSetHtml();
447
448 return $feed_html;
449 } else {
450 if ( ! $twitter_feed->feed_options['persistentcache'] ) {
451 $twitter_feed->maybeCacheTweets();
452 }
453 $feed_html = '';
454 $feed_html .= $twitter_feed->getTweetSetHtml();
455
456 return $feed_html;
457 }
458 }
459 }
460 add_shortcode( 'custom-twitter-feed', 'ctf_init' );
461 add_shortcode( 'custom-twitter-feeds', 'ctf_init' );
462
463 /**
464 * Called via ajax to get more posts after the "load more" button is clicked
465 */
466 function ctf_get_more_posts() {
467 $shortcode_data = json_decode( str_replace( '\"', '"', sanitize_text_field( $_POST['shortcode_data'] ) ), true ); // necessary to unescape quotes
468 $last_id_data = isset( $_POST['last_id_data'] ) ? sanitize_text_field( $_POST['last_id_data'] ) : '';
469 $num_needed = isset( $_POST['num_needed'] ) ? (int)$_POST['num_needed'] : 0;
470 $ids_to_remove = isset( $_POST['ids_to_remove'] ) ? $_POST['ids_to_remove'] : array();
471 $feed = isset( $_POST['v2feed'] ) ? sanitize_key( $_POST['v2feed'] ) : '';
472 if ( empty( $shortcode_data ) ) {
473 $shortcode_data = array();
474 }
475 $shortcode_data['feed'] = $feed;
476
477 $is_pagination = empty( $last_id_data ) ? 0 : 1;
478 $persistent_index = isset( $_POST['persistent_index'] ) ? sanitize_text_field( $_POST['persistent_index'] ) : '';
479
480 $twitter_feed = TwitterFeed\CtfFeed::init( $shortcode_data, $last_id_data, $num_needed, $ids_to_remove, $persistent_index );
481
482 if ( ! CTF_DOING_SMASH_TWITTER && ! $twitter_feed->feed_options['persistentcache'] ) {
483 $twitter_feed->maybeCacheTweets();
484 }
485
486 $atts = $shortcode_data;
487 $feed_id = isset( $_POST['feed_id'] ) ? sanitize_text_field( $_POST['feed_id'] ) : 'unknown';
488 $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
489 $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
490 $feed_details = array(
491 'feed_id' => $feed_id,
492 'atts' => $atts,
493 'location' => array(
494 'post_id' => $post_id,
495 'html' => $location
496 )
497 );
498
499 ctf_do_background_tasks( $feed_details );
500
501 echo $twitter_feed->getItemSetHtml( $is_pagination );
502
503 die();
504 }
505 add_action( 'wp_ajax_nopriv_ctf_get_more_posts', 'ctf_get_more_posts' );
506 add_action( 'wp_ajax_ctf_get_more_posts', 'ctf_get_more_posts' );
507
508 function ctf_do_locator() {
509 if ( ! isset( $_POST['feed_id'] ) || strpos( $_POST['feed_id'], 'ctf' ) === false ) {
510 die( 'invalid feed ID');
511 }
512
513 $feed_id = sanitize_text_field( $_POST['feed_id'] );
514
515 $atts_raw = isset( $_POST['atts'] ) ? json_decode( stripslashes( $_POST['atts'] ), true ) : array();
516 if ( is_array( $atts_raw ) ) {
517 array_map( 'sanitize_text_field', $atts_raw );
518 } else {
519 $atts_raw = array();
520 }
521 $atts = $atts_raw; // now sanitized
522
523 $location = isset( $_POST['location'] ) && in_array( $_POST['location'], array( 'header', 'footer', 'sidebar', 'content' ), true ) ? sanitize_text_field( $_POST['location'] ) : 'unknown';
524 $post_id = isset( $_POST['post_id'] ) && $_POST['post_id'] !== 'unknown' ? (int)$_POST['post_id'] : 'unknown';
525 $feed_details = array(
526 'feed_id' => $feed_id,
527 'atts' => $atts,
528 'location' => array(
529 'post_id' => $post_id,
530 'html' => $location
531 )
532 );
533
534 ctf_do_background_tasks( $feed_details );
535
536 wp_die( 'locating success' );
537 }
538 add_action( 'wp_ajax_ctf_do_locator', 'ctf_do_locator' );
539 add_action( 'wp_ajax_nopriv_ctf_do_locator', 'ctf_do_locator' );
540
541 function ctf_do_background_tasks( $feed_details ) {
542 $locator = new TwitterFeed\CTF_Feed_Locator( $feed_details );
543 $locator->add_or_update_entry();
544 if ( $locator->should_clear_old_locations() ) {
545 $locator->delete_old_locations();
546 }
547 }
548
549 function ctf_plugin_action_links( $links ) {
550 $pro_link = '<a href="https://smashballoon.com/custom-twitter-feeds/demo/?utm_campaign=twitter-free&utm_source=plugins-page&utm_medium=upgrade-link" target="_blank" style="font-weight: bold; color: #1da867;">' . __( 'Try the Pro Demo', 'custom-twitter-feeds' ) . '</a>';
551 $settings_link = '<a href="'. esc_url( admin_url( 'admin.php?page=ctf-feed-builder' ) ) .'">' . __( 'Settings' ) . '</a>';
552 array_unshift( $links, $pro_link, $settings_link );
553
554 return $links;
555 }
556 add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'ctf_plugin_action_links' );
557
558 function ctf_json_encode( $thing ) {
559 if ( function_exists( 'wp_json_encode' ) ) {
560 return wp_json_encode( $thing );
561 } else {
562 return json_encode( $thing );
563 }
564 }
565
566 /**
567 * the html output is controlled by the user selecting which portions of tweets to show
568 *
569 * @param $part string part of the feed in the html
570 * @param $feed_options array options that contain what parts of the tweet to show
571 * @return bool whether or not to show the tweet
572 */
573 function ctf_show( $part, $feed_options ) {
574 if ( ctf_doing_customizer( $feed_options ) ) {
575 return true;
576 }
577
578 $tweet_excludes = isset( $feed_options['tweet_excludes'] ) ? $feed_options['tweet_excludes'] : '';
579 $tweet_includes = isset( $feed_options['tweet_includes'] ) ? $feed_options['tweet_includes'] : '';
580
581 // if part is in the array of excluded parts or not in the array of included parts, don't show
582 if ( ! empty( $tweet_excludes ) ) {
583 return ( in_array( $part, (array) $tweet_excludes ) === false );
584 } else {
585 return ( in_array( $part, (array) $tweet_includes ) === true );
586 }
587 }
588
589 /**
590 * this function returns the properly formatted date string based on user input
591 *
592 * @param $raw_date string the date from the Twitter api
593 * @param $feed_options array options for the feed that contain date formatting settings
594 * @param $utc_offset int offset in seconds for the time display based on timezone
595 * @return string formatted date
596 */
597 function ctf_get_formatted_date( $raw_date, $feed_options, $utc_offset ) {
598
599 $options = get_option( 'ctf_options' );
600 $timezone = isset( $options['timezone'] ) ? $options['timezone'] : 'default';
601 // use php \DateTimeZone class to handle the date formatting and offsets
602 $date_obj = new \DateTime($raw_date, new \DateTimeZone('UTC'));
603
604 if ( $timezone != 'default' ) {
605 $date_obj->setTimeZone( new \DateTimeZone( $timezone ) );
606 $utc_offset = $date_obj->getOffset();
607 }
608 $tz_offset_timestamp = $date_obj->getTimestamp() + $utc_offset;
609
610 // use the custom date format if set, otherwise use from the selected defaults
611 if ( ! empty( $feed_options['datecustom'] ) ) {
612 $date_str = date_i18n( $feed_options['datecustom'], $tz_offset_timestamp );
613 } else {
614
615 switch ( $feed_options['dateformat'] ) {
616 case '2':
617 $date_str = date_i18n( 'F j', $tz_offset_timestamp );
618 break;
619 case '3':
620 $date_str = date_i18n( 'F j, Y', $tz_offset_timestamp );
621 break;
622 case '4':
623 $date_str = date_i18n( 'm.d', $tz_offset_timestamp );
624 break;
625 case '5':
626 $date_str = date_i18n( 'm.d.y', $tz_offset_timestamp );
627 break;
628 case '6':
629 $date_str = date_i18n( 'D M jS, Y', $tz_offset_timestamp );
630 break;
631 case '7':
632 $date_str = date_i18n( 'l F jS, Y', $tz_offset_timestamp );
633 break;
634 case '8':
635 $date_str = date_i18n( 'l F jS, Y - g:i a', $tz_offset_timestamp );
636 break;
637 case '9':
638 $date_str = date_i18n( "l M jS, 'y", $tz_offset_timestamp );
639 break;
640 case '10':
641 $date_str = date_i18n( 'm.d.y', $tz_offset_timestamp );
642 break;
643 case '18':
644 $date_str = date_i18n( 'm.d.y - G:i', $tz_offset_timestamp );
645 break;
646 case '11':
647 $date_str = date_i18n( 'm/d/y', $tz_offset_timestamp );
648 break;
649 case '12':
650 $date_str = date_i18n( 'd.m.y', $tz_offset_timestamp );
651 break;
652 case '19':
653 $date_str = date_i18n( 'd.m.y - G:i', $tz_offset_timestamp );
654 break;
655 case '13':
656 $date_str = date_i18n( 'd/m/y', $tz_offset_timestamp );
657 break;
658 case '14':
659 $date_str = date_i18n( 'd-m-Y, G:i', $tz_offset_timestamp );
660 break;
661 case '15':
662 $date_str = date_i18n( 'jS F Y, G:i', $tz_offset_timestamp );
663 break;
664 case '16':
665 $date_str = date_i18n( 'd M Y, G:i', $tz_offset_timestamp );
666 break;
667 case '17':
668 $date_str = date_i18n( 'l jS F Y, G:i', $tz_offset_timestamp );
669 break;
670 case '20':
671 $date_str = date_i18n( 'Y-m-d', $tz_offset_timestamp );
672 break;
673 default:
674 // default format is similar to Twitter
675 $ctf_minute = ! empty( $options['mtime'] ) ? $options['mtime'] : 'm';
676 $ctf_hour = ! empty( $options['htime'] ) ? $options['htime'] : 'h';
677 $ctf_now_str = ! empty( $options['nowtime'] ) ? $options['nowtime'] : 'now';
678
679 $now = time() + $utc_offset;
680
681 $difference = $now - $tz_offset_timestamp;
682 if ( $difference < 60 ) {
683 $date_str = $ctf_now_str;
684 } elseif ( $difference < 60*60 ) {
685 $date_str = round( $difference/60 ) . $ctf_minute;
686 } elseif ( $difference < 60*60*24 ) {
687 $date_str = round( $difference/3600 ) . $ctf_hour;
688 } else {
689 $one_year_from_date = new \DateTime( $raw_date, new \DateTimeZone( "UTC" ) );
690 $one_year_from_date->modify('+1 year');
691 $one_year_from_date_timestamp = $one_year_from_date->getTimestamp();
692 if ( $now > $one_year_from_date_timestamp ) {
693 $date_str = date_i18n( 'j M Y', $tz_offset_timestamp );
694 } else {
695 $date_str = date_i18n( 'j M', $tz_offset_timestamp );
696 }
697 }
698
699 break;
700 }
701 }
702
703 return $date_str;
704 }
705
706 function ctf_maybe_shorten_text( $string, $feed_settings ) {
707 #if( !ctf_doing_customizer($feed_settings) ){
708 $limit = is_array( $feed_settings ) ? $feed_settings['textlength'] : $feed_settings;
709
710 if ( strlen( $string ) <= $limit
711 || $limit >= 280 ) {
712 return $string;
713 }
714
715 $parts = preg_split( '/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE );
716 $parts_count = count( $parts );
717
718 $length = 0;
719 $last_part = 0;
720 $first_parts = array();
721 $end_parts = array();
722 for ( ; $last_part < $parts_count; $last_part++ ) {
723 $length += strlen( $parts[ $last_part ] );
724 if ( $length < $limit ) {
725 $first_parts[] = $parts[ $last_part ];
726 } else {
727 $end_parts[] = $parts[ $last_part ];
728 }
729 }
730 $return = implode( ' ', $first_parts ) . '<a href="#" class="ctf_more">...</a><span class="ctf_remaining">';
731
732 $return .= implode( ' ', $end_parts ) . '</span>';
733
734 return $return;
735 #}
736 #return $string;
737 }
738 add_filter( 'ctf_tweet_text', 'ctf_maybe_shorten_text', 10, 2 );
739
740 function ctf_replace_urls( $string, $feed_settings, $post ) {
741
742 if ( $feed_settings['shorturls'] ) {
743 return $string;
744 }
745
746 if ( isset( $post['entities']['urls'][0] ) ) {
747 foreach ( $post['entities']['urls'] as $url ) {
748 if ( isset( $url['url'] ) ) {
749 $string = str_replace( $url['url'], $url['expanded_url'], $string );
750 }
751 }
752 }
753
754 return $string;
755 }
756 add_filter( 'ctf_tweet_text', 'ctf_replace_urls', 9, 3 );
757 add_filter( 'ctf_quoted_tweet_text', 'ctf_replace_urls', 9, 3 );
758
759 function ctf_get_fa_el( $icon ) {
760 $options = get_option( 'ctf_options' );
761 $font_method = 'svg';
762
763 $elems = array(
764 'fa-arrows-alt' => array(
765 'icon' => '<span class="fa fa-arrows-alt"></span>',
766 'svg' => '<svg class="svg-inline--fa fa-arrows-alt fa-w-16" aria-hidden="true" aria-label="expand" data-fa-processed="" data-prefix="fa" data-icon="arrows-alt" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M352.201 425.775l-79.196 79.196c-9.373 9.373-24.568 9.373-33.941 0l-79.196-79.196c-15.119-15.119-4.411-40.971 16.971-40.97h51.162L228 284H127.196v51.162c0 21.382-25.851 32.09-40.971 16.971L7.029 272.937c-9.373-9.373-9.373-24.569 0-33.941L86.225 159.8c15.119-15.119 40.971-4.411 40.971 16.971V228H228V127.196h-51.23c-21.382 0-32.09-25.851-16.971-40.971l79.196-79.196c9.373-9.373 24.568-9.373 33.941 0l79.196 79.196c15.119 15.119 4.411 40.971-16.971 40.971h-51.162V228h100.804v-51.162c0-21.382 25.851-32.09 40.97-16.971l79.196 79.196c9.373 9.373 9.373 24.569 0 33.941L425.773 352.2c-15.119 15.119-40.971 4.411-40.97-16.971V284H284v100.804h51.23c21.382 0 32.09 25.851 16.971 40.971z"></path></svg>'
767 ),
768 'fa-check-circle' => array(
769 'icon' => '<span class="fa fa-check-circle"></span>',
770 'svg' => '<svg class="svg-inline--fa fa-check-circle fa-w-16" aria-hidden="true" aria-label="verified" data-fa-processed="" data-prefix="fa" data-icon="check-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg>'
771 ),
772 'fa-reply' => array(
773 'icon' => '<span class="fa fa-reply"></span>',
774 'svg' => '<svg class="svg-inline--fa fa-w-16" viewBox="0 0 24 24" aria-label="reply" role="img" xmlns="http://www.w3.org/2000/svg"><g><path fill="currentColor" d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>'
775 ),
776 'fa-retweet' => array(
777 'icon' => '<span class="fa fa-retweet"></span>',
778 'svg' => '<svg class="svg-inline--fa fa-w-16" viewBox="0 0 24 24" aria-hidden="true" aria-label="retweet" role="img"><path fill="currentColor" d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></svg>'
779 ),
780 'fa-x' => array(
781 'icon' => '<span class="fa fab fa-twitter"></span>',
782 'svg' => '<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M21.1161 6.27344H24.2289L17.4284 14.0459L25.4286 24.6225H19.1645L14.2583 18.2079L8.6444 24.6225H5.52976L12.8035 16.309L5.12891 6.27344H11.552L15.9868 12.1367L21.1161 6.27344ZM20.0236 22.7594H21.7484L10.6148 8.03871H8.7639L20.0236 22.7594Z" fill="black"/>
783 </svg>',
784 ),
785 'fa-heart' => array(
786 'icon' => '<span class="fa fa-heart"></span>',
787 'svg' => '<svg class="svg-inline--fa fa-w-16" viewBox="0 0 24 24" aria-hidden="true" aria-label="like" role="img" xmlns="http://www.w3.org/2000/svg"><g><path fill="currentColor" d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z"></path></g></svg>'
788 ),
789 'fa-twitter' => array(
790 'icon' => '<span class="fa fab fa-twitter"></span>',
791 'svg' => '<svg class="svg-inline--fa fa-twitter fa-w-16" aria-hidden="true" aria-label="twitter logo" data-fa-processed="" data-prefix="fab" data-icon="twitter" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg>'
792 ),
793 'fa-user' => array(
794 'icon' => '<span class="fa fa-user"></span>',
795 'svg' => '<svg class="svg-inline--fa fa-user fa-w-16" aria-hidden="true" aria-label="followers" data-fa-processed="" data-prefix="fa" data-icon="user" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M96 160C96 71.634 167.635 0 256 0s160 71.634 160 160-71.635 160-160 160S96 248.366 96 160zm304 192h-28.556c-71.006 42.713-159.912 42.695-230.888 0H112C50.144 352 0 402.144 0 464v24c0 13.255 10.745 24 24 24h464c13.255 0 24-10.745 24-24v-24c0-61.856-50.144-112-112-112z"></path></svg>'
796 ),
797 'ctf_playbtn' => array(
798 'icon' => '',
799 'svg' => '<svg aria-label="play button" style="color: rgba(255,255,255,1)" class="svg-inline--fa fa-play fa-w-14 ctf_playbtn" aria-hidden="true" data-fa-processed="" data-prefix="fa" data-icon="play" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"></path></svg>'
800 ),
801 'fa-file-video-o' => array(
802 'icon' => '<span class="fa fa-file-video-o ctf-tweet-text-media" aria-hidden="true"></span>',
803 'svg' => '<svg aria-hidden="true" aria-label="video in tweet" focusable="false" data-prefix="far" data-icon="file-video" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="svg-inline--fa fa-file-video fa-w-12 fa-9x ctf-tweet-text-media"><path fill="currentColor" d="M369.941 97.941l-83.882-83.882A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V131.882a48 48 0 0 0-14.059-33.941zM332.118 128H256V51.882L332.118 128zM48 464V48h160v104c0 13.255 10.745 24 24 24h104v288H48zm228.687-211.303L224 305.374V268c0-11.046-8.954-20-20-20H100c-11.046 0-20 8.954-20 20v104c0 11.046 8.954 20 20 20h104c11.046 0 20-8.954 20-20v-37.374l52.687 52.674C286.704 397.318 304 390.28 304 375.986V264.011c0-14.311-17.309-21.319-27.313-11.314z" class=""></path></svg>'
804 ),
805 'fa-picture-o' => array(
806 'icon' => '<span class="fa fa-picture-o ctf-tweet-text-media" aria-hidden="true"></span>',
807 'svg' => '<svg aria-hidden="true" aria-label="images in tweet" focusable="false" data-prefix="far" data-icon="image" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-image fa-w-16 fa-9x ctf-tweet-text-media"><path fill="currentColor" d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 336H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v276a6 6 0 0 1-6 6zM128 152c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zM96 352h320v-80l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L192 304l-39.515-39.515c-4.686-4.686-12.284-4.686-16.971 0L96 304v48z" class=""></path></svg>'
808 ),
809 );
810
811 if ( $font_method !== 'fontfile' ){
812 return $elems[ $icon ]['svg'];
813 }
814
815 return $elems[ $icon ]['icon'];
816 }
817
818 /**
819 * manually clears the cached tweets in case of error or user preference
820 *
821 * @return mixed bool whether or not it was successful
822 */
823 function ctf_clear_cache() {
824
825 //Delete all transients
826 global $wpdb;
827 $table_name = $wpdb->prefix . "options";
828 $result = $wpdb->query("
829 DELETE
830 FROM $table_name
831 WHERE `option_name` LIKE ('%\_transient\_ctf\_%')
832 ");
833 $wpdb->query("
834 DELETE
835 FROM $table_name
836 WHERE `option_name` LIKE ('%\_transient\_timeout\_ctf\_%')
837 ");
838
839 ctf_clear_page_caches();
840
841 }
842 add_action( 'ctf_cron_job', 'ctf_clear_cache' );
843
844 function ctf_clear_cache_admin() {
845 check_ajax_referer('ctf-admin' , 'ctf_nonce');
846 if ( ! ctf_current_user_can( 'manage_twitter_feed_options' ) ) {
847 wp_send_json_error();
848 }
849
850 //Delete all transients
851 global $wpdb;
852 $table_name = $wpdb->prefix . "options";
853 $result = $wpdb->query("
854 DELETE
855 FROM $table_name
856 WHERE `option_name` LIKE ('%\_transient\_ctf\_%')
857 ");
858 $wpdb->query("
859 DELETE
860 FROM $table_name
861 WHERE `option_name` LIKE ('%\_transient\_timeout\_ctf\_%')
862 ");
863
864 ctf_clear_page_caches();
865
866 wp_send_json_success();
867 }
868 add_action( 'wp_ajax_ctf_clear_cache_admin', 'ctf_clear_cache_admin' );
869
870 function ctf_activate() {
871 // set usage tracking to false if fresh install. Skip when the Pro plugin is active: it shares
872 // this option and defaults tracking on, so seeding a disabled record here would silently turn it off.
873 $usage_tracking = get_option( 'ctf_usage_tracking', false );
874
875 global $wp_roles;
876 $wp_roles->add_cap( 'administrator', 'manage_twitter_feed_options' );
877
878 $ctf_network_active = is_multisite() ? (array) get_site_option( 'active_sitewide_plugins', array() ) : array();
879 $ctf_pro_active = in_array( 'custom-twitter-feeds-pro/custom-twitter-feed.php', (array) get_option( 'active_plugins', array() ), true )
880 || isset( $ctf_network_active['custom-twitter-feeds-pro/custom-twitter-feed.php'] );
881
882 if ( ! is_array( $usage_tracking ) && ! $ctf_pro_active ) {
883 $usage_tracking = array(
884 'enabled' => false,
885 'last_send' => 0
886 );
887
888 update_option( 'ctf_usage_tracking', $usage_tracking, false );
889 }
890 global $wp_roles;
891 $wp_roles->add_cap( 'administrator', 'manage_twitter_feed_options' );
892 }
893 register_activation_hook( __FILE__, 'ctf_activate' );
894
895 /**
896 * clear the cache and unschedule an cron jobs when deactivated
897 */
898 function ctf_deactivate() {
899 ctf_clear_cache();
900
901 wp_clear_scheduled_hook( 'ctf_cron_job' );
902 wp_clear_scheduled_hook( \TwitterFeed\UsageTracking\Config::CRON_HOOK );
903 }
904 register_deactivation_hook( __FILE__, 'ctf_deactivate' );
905
906 /**
907 * Loads the javascript for the plugin front-end. Also localizes the admin-ajax file location for use in ajax calls
908 */
909 function ctf_scripts_and_styles( $enqueue = false ) {
910 $options = get_option( 'ctf_options' );
911 $not_ajax_theme = (! isset( $options['ajax_theme'] ) || ! $options['ajax_theme']);
912 $font_method = 'svg';
913
914 $loacalize_args = array(
915 'ajax_url' => admin_url( 'admin-ajax.php' )
916 );
917
918 wp_enqueue_style( 'ctf_styles', plugins_url( '/css/ctf-styles.min.css', __FILE__ ), array(), CTF_VERSION );
919 wp_register_script( 'ctf_scripts', CTF_JS_URL, array( 'jquery' ), CTF_VERSION, true );
920
921 if ( $not_ajax_theme ) {
922 wp_localize_script( 'ctf_scripts', 'ctf', $loacalize_args );
923 } else {
924 wp_localize_script( 'jquery', 'ctf', $loacalize_args );
925 }
926
927 if ( $enqueue ) {
928 wp_enqueue_style( 'ctf_styles' );
929 wp_enqueue_script( 'ctf_scripts' );
930 }
931 }
932 add_action( 'wp_enqueue_scripts', 'ctf_scripts_and_styles' );
933
934 /**
935 * outputs the custom js from the "Customize" tab on the Settings page
936 */
937 function ctf_custom_js() {
938 $options = get_option( 'ctf_options' );
939 $ctf_custom_js = isset( $options[ 'custom_js' ] ) ? $options[ 'custom_js' ] : '';
940
941 if ( ! empty( $ctf_custom_js ) ) {
942 ?>
943 <!-- Custom Twitter Feeds JS -->
944 <script type="text/javascript">
945 <?php echo "window.ctf_custom_js = function($){" . stripslashes( $ctf_custom_js ) . "}\r\n"; ?>
946 </script>
947 <?php
948 }
949 }
950 add_action( 'wp_footer', 'ctf_custom_js' );
951
952 /**
953 * outputs the custom css from the "Customize" tab on the Settings page
954 */
955 function ctf_custom_css() {
956 $options = get_option( 'ctf_options' );
957 $ctf_custom_css = isset( $options[ 'custom_css' ] ) ? $options[ 'custom_css' ] : '';
958
959 if ( ! empty( $ctf_custom_css ) ) {
960 ?>
961 <!-- Custom Twitter Feeds CSS -->
962 <style type="text/css">
963 <?php echo stripslashes( $ctf_custom_css ) . "\r\n"; ?>
964 </style>
965 <?php
966 }
967 }
968 add_action( 'wp_head', 'ctf_custom_css' );
969
970 /**
971 * Some CSS and JS needed in the admin area as well
972 */
973 function ctf_admin_scripts_and_styles() {
974 wp_enqueue_style(
975 'feed-global-style',
976 CTF_PLUGIN_URL . 'admin/builder/assets/css/global.css',
977 false,
978 CTF_VERSION
979 );
980 wp_enqueue_style( 'ctf_admin_styles', plugins_url( '/css/ctf-admin-styles.css', __FILE__ ), array(), CTF_VERSION );
981 wp_enqueue_style( 'sb-font-awesome', 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' );
982 wp_enqueue_script( 'ctf_admin_scripts', plugins_url( '/js/ctf-admin-scripts.js', __FILE__ ) , array( 'jquery' ), CTF_VERSION, false );
983 wp_localize_script( 'ctf_admin_scripts', 'ctf', array(
984 'ajax_url' => admin_url( 'admin-ajax.php' ),
985 'sb_nonce' => wp_create_nonce( 'ctf-smash-balloon' ),
986 'nonce' => wp_create_nonce( 'ctf-admin' )
987 )
988 );
989 $strings = array(
990 'addon_activate' => esc_html__( 'Activate', 'custom-twitter-feeds' ),
991 'addon_activated' => esc_html__( 'Activated', 'custom-twitter-feeds' ),
992 'addon_active' => esc_html__( 'Active', 'custom-twitter-feeds' ),
993 'addon_deactivate' => esc_html__( 'Deactivate', 'custom-twitter-feeds' ),
994 'addon_inactive' => esc_html__( 'Inactive', 'custom-twitter-feeds' ),
995 'addon_install' => esc_html__( 'Install Addon', 'custom-twitter-feeds' ),
996 'addon_error' => esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'custom-twitter-feeds' ),
997 'plugin_error' => esc_html__( 'Could not install a plugin. Please download from WordPress.org and install manually.', 'custom-twitter-feeds' ),
998 'addon_search' => esc_html__( 'Searching Addons', 'custom-twitter-feeds' ),
999 'ajax_url' => admin_url( 'admin-ajax.php' ),
1000 'cancel' => esc_html__( 'Cancel', 'custom-twitter-feeds' ),
1001 'close' => esc_html__( 'Close', 'custom-twitter-feeds' ),
1002 'nonce' => wp_create_nonce( 'ctf-admin' ),
1003 'almost_done' => esc_html__( 'Almost Done', 'custom-twitter-feeds' ),
1004 'oops' => esc_html__( 'Oops!', 'custom-twitter-feeds' ),
1005 'ok' => esc_html__( 'OK', 'custom-twitter-feeds' ),
1006 'plugin_install_activate_btn' => esc_html__( 'Install and Activate', 'custom-twitter-feeds' ),
1007 'plugin_install_activate_confirm' => esc_html__( 'needs to be installed and activated to import its forms. Would you like us to install and activate it for you?', 'custom-twitter-feeds' ),
1008 'plugin_activate_btn' => esc_html__( 'Activate', 'custom-twitter-feeds' ),
1009 'smashPlugins' => CTF_Feed_Builder::install_plugins_popup()
1010 );
1011 $strings = apply_filters( 'ctf_admin_strings', $strings );
1012
1013 wp_localize_script(
1014 'ctf_admin_scripts',
1015 'ctf_admin_strings',
1016 $strings
1017 );
1018 wp_enqueue_style( 'wp-color-picker' );
1019 wp_enqueue_script( 'wp-color-picker' );
1020 wp_enqueue_script(
1021 'jquery-matchheight',
1022 CTF_PLUGIN_URL . 'js/jquery.matchHeight-min.js',
1023 array( 'jquery' ),
1024 '0.7.0',
1025 false
1026 );
1027 }
1028 add_action( 'admin_enqueue_scripts', 'ctf_admin_scripts_and_styles' );
1029
1030
1031 function ctf_is_pro_version() {
1032 return defined( 'CTF_STORE_URL' );
1033 }
1034
1035
1036 function ctf_get_database_settings() {
1037 $options = get_option( 'ctf_options', array() );
1038 $options = set_global_default_settings( $options );
1039 return $options;
1040 }
1041
1042 function set_global_default_settings( $options ) {
1043 $defaults = array(
1044 'disableintents' => false,
1045 'creditctf' => false,
1046 'ajax_theme' => false,
1047 );
1048 foreach ( $defaults as $key => $value ) {
1049 if ( ! isset( $options[ $key ] ) ) {
1050 $options[ $key ] = $value;
1051 }
1052 }
1053 return $options;
1054 }
1055
1056 function ctf_clear_page_caches() {
1057 //Clear cache of major caching plugins
1058 if(isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')){
1059 $GLOBALS['wp_fastest_cache']->deleteCache();
1060 }
1061 //WP Super Cache
1062 if (function_exists('wp_cache_clear_cache')) {
1063 wp_cache_clear_cache();
1064 }
1065 //W3 Total Cache
1066 if (function_exists('w3tc_flush_all')) {
1067 w3tc_flush_all();
1068 }
1069 if (function_exists('sg_cachepress_purge_cache')) {
1070 sg_cachepress_purge_cache();
1071 }
1072
1073 // Litespeed Cache (older method)
1074 if ( method_exists( 'LiteSpeed_Cache_API', 'purge' ) ) {
1075 LiteSpeed_Cache_API::purge( 'esi.custom-twitter-feeds' );
1076 }
1077
1078 // Litespeed Cache (new method)
1079 if(has_action('litespeed_purge')) {
1080 do_action( 'litespeed_purge', 'esi.custom-twitter-feeds' );
1081 }
1082 }
1083
1084 /**
1085 * Add the custom interval of 30 minutes for cron caching
1086 *
1087 * @param array $schedules current list of cron intervals
1088 *
1089 * @return array
1090 *
1091 * @since 2.0
1092 */
1093 function ctf_cron_custom_interval( $schedules ) {
1094 $schedules['ctf30mins'] = array(
1095 'interval' => 30 * 60,
1096 'display' => __( 'Every 30 minutes' )
1097 );
1098 $schedules['ctfweekly'] = array(
1099 'interval' => 3600 * 24 * 7,
1100 'display' => __( 'Weekly' )
1101 );
1102
1103 return $schedules;
1104 }
1105
1106 add_filter( 'cron_schedules', 'ctf_cron_custom_interval' );
1107
1108 function ctf_create_database_table() {
1109 global $wpdb;
1110 global $wp_version;
1111
1112 $table_name = esc_sql( $wpdb->prefix . CTF_POSTS_TABLE );
1113 $feeds_posts_table_name = esc_sql( $wpdb->prefix . CTF_FEEDS_POSTS_TABLE );
1114 $charset_collate = '';
1115
1116 if ( version_compare( $wp_version, '3.5', '>' ) ) {
1117 $charset_collate = $wpdb->get_charset_collate();
1118 }
1119
1120 if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) {
1121 $sql = "CREATE TABLE " . $table_name . " (
1122 id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
1123 twitter_id VARCHAR(1000) DEFAULT '' NOT NULL,
1124 created_on DATETIME,
1125 last_requested DATE,
1126 time_stamp DATETIME,
1127 json_data LONGTEXT DEFAULT '' NOT NULL,
1128 media_id VARCHAR(1000) DEFAULT '' NOT NULL,
1129 sizes VARCHAR(1000) DEFAULT '' NOT NULL,
1130 aspect_ratio DECIMAL (4,2) DEFAULT 0 NOT NULL,
1131 images_done TINYINT(1) DEFAULT 0 NOT NULL
1132 ) $charset_collate;";
1133 $wpdb->query( $sql );
1134 }
1135
1136 if ( $wpdb->get_var( "show tables like '$feeds_posts_table_name'" ) != $feeds_posts_table_name ) {
1137 $sql = "CREATE TABLE " . $feeds_posts_table_name . " (
1138 record_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
1139 id INT(11) UNSIGNED NOT NULL,
1140 feed_id VARCHAR(1000) DEFAULT '' NOT NULL,
1141 INDEX feed_id (feed_id(100))
1142 ) $charset_collate;";
1143 $wpdb->query( $sql );
1144 }
1145
1146 return $wpdb->get_var( "show tables like '$table_name'" ) === $table_name;
1147 }
1148
1149 function ctf_text_domain() {
1150 load_plugin_textdomain( 'custom-twitter-feeds', false, basename( dirname(__FILE__) ) . '/languages' );
1151 }
1152
1153 add_action( 'init', 'ctf_text_domain' );
1154
1155 //BUILDER CODE
1156 function ctf_builder() {
1157 return \TwitterFeed\Builder\CTF_Feed_Builder::instance();
1158 }
1159 ctf_builder();
1160