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 / CTF_Feed_Locator.php
custom-twitter-feeds / inc Last commit date
Admin 1 month ago Builder 1 month ago Integrations 1 month ago SmashTwitter 1 month ago UsageTracking 1 month ago V2 1 month ago blocks 1 month ago CTF_Display_Elements.php 1 month ago CTF_Feed.php 1 month ago CTF_Feed_Locator.php 1 month ago CTF_GDPR_Integrations.php 1 month ago CTF_Parse.php 1 month ago CTF_Settings.php 1 month ago CtfAdmin.php 1 month ago CtfCache.php 1 month ago CtfFeed.php 1 month ago CtfOauthConnect.php 1 month ago SB_Twitter_Cron_Updater.php 1 month ago admin-hooks.php 1 month ago ctf-functions.php 1 month ago notices.php 1 month ago widget.php 1 month ago
CTF_Feed_Locator.php
588 lines
1 <?php
2 /**
3 * Class CTF_Feed_Locator
4 *
5 * Locates feeds on the site and logs information about them in the database.
6 *
7 * @since 1.14
8 */
9 namespace TwitterFeed;
10 use TwitterFeed\Builder\CTF_Db;
11 if ( ! defined( 'ABSPATH' ) ) {
12 die( '-1' );
13 }
14
15 class CTF_Feed_Locator
16 {
17 private $feed_details;
18
19 private $expiration_time;
20
21 private $matching_entries;
22
23 public function __construct( $feed_details ) {
24 /**
25 * Example of how $feed_details is structured
26 *
27 * $feed_details = array(
28 * 'feed_id' => $transient_name,
29 * 'atts' => $atts,
30 * 'location' => array(
31 * 'post_id' => get_the_ID(),
32 * 'html' => 'unknown'
33 * )
34 * );
35 */
36 if ( isset( $feed_details['atts'] ) && ! empty( $feed_details['atts']['feed'] ) ) {
37 $feed_details['feed_id'] = '*' . $feed_details['atts']['feed'];
38 }
39 $this->feed_details = $feed_details;
40
41 $this->matching_entries = array();
42
43 $this->expiration_time = time() - 2 * WEEK_IN_SECONDS;
44 }
45
46 /**
47 * Returns records that match the post ID and feed ID
48 * of the feed being located
49 *
50 * @return array
51 *
52 * @since 1.14
53 */
54 public function retrieve_matching_entries() {
55 global $wpdb;
56 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
57
58 $results = $wpdb->get_results( $wpdb->prepare("
59 SELECT *
60 FROM $feed_locator_table_name
61 WHERE post_id = %d
62 AND feed_id = %s", $this->feed_details['location']['post_id'], $this->feed_details['feed_id'] ),ARRAY_A );
63
64 return $results;
65 }
66
67 /**
68 * Add feed being located to the database
69 *
70 * @since 1.14
71 */
72 public function insert_entry() {
73 if ( empty( $this->feed_details['location']['post_id'] ) ) {
74 return false;
75 }
76 global $wpdb;
77
78 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
79
80 $affected = $wpdb->query( $wpdb->prepare( "INSERT INTO $feed_locator_table_name
81 (feed_id,
82 post_id,
83 html_location,
84 shortcode_atts,
85 last_update)
86 VALUES (
87 %s,
88 %d,
89 %s,
90 %s,
91 %s);",
92 $this->feed_details['feed_id'],
93 $this->feed_details['location']['post_id'],
94 $this->feed_details['location']['html'],
95 ctf_json_encode( $this->feed_details['atts'] ),
96 date( 'Y-m-d H:i:s' ) ) );
97 }
98
99 /**
100 * Update a record based on the existing "id" column. Location can change
101 * from "unknown" to one of footer, content, header, or sidebar.
102 *
103 * @param $id
104 * @param $location
105 *
106 * @since 1.14
107 */
108 public function update_entry( $id, $location ) {
109 global $wpdb;
110
111 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
112
113 $query = $wpdb->query( $wpdb->prepare( "
114 UPDATE $feed_locator_table_name
115 SET last_update = %s, html_location = %s
116 WHERE id = %d;", date( 'Y-m-d H:i:s' ), $location, $id ) );
117 }
118
119 /**
120 * Processes a feed being located based on whether or not the record
121 * exists as well as whether or not an unknown location needs to be
122 * updated.
123 *
124 * @since 1.14
125 */
126 public function add_or_update_entry() {
127 if ( empty( $this->feed_details['feed_id'] ) ) {
128 return;
129 }
130
131 $this->matching_entries = $this->retrieve_matching_entries();
132
133 if ( empty( $this->matching_entries ) ) {
134 $this->insert_entry();
135 } else {
136 $matching_indices = array();
137 $matched_location = false;
138 $non_unknown_match = false;
139 $unknown_match = false;
140
141 foreach ( $this->matching_entries as $index => $matching_entry ) {
142 $details_atts = is_array( $this->feed_details['atts'] ) ? $this->feed_details['atts'] : array();
143 $matching_atts = json_decode( $matching_entry['shortcode_atts'], true );
144 if ( ! is_array( $matching_atts ) ) {
145 $matching_atts = array();
146 }
147 $atts_diff = array_diff( $matching_atts, $details_atts ); // determines if the shortcode settings match the shortcode settings of an existing feed
148 if ( empty( $atts_diff ) ) {
149 $matching_indices[] = $matching_entry['id'];
150 if ( $matching_entry['html_location'] === $this->feed_details['location']['html'] ) {
151 $matched_location = $index;
152 $this->update_entry( $matching_entry['id'], $matching_entry['html_location'] );
153 }
154 if ( $matching_entry['html_location'] !== 'unknown' ) {
155 $non_unknown_match = $index;
156 } else {
157 $unknown_match = $index;
158 }
159 }
160 }
161
162 if ( false === $matched_location ) {
163 // if there is no matched location, there is only one feed on the page, and the feed being checked has an unknown location, update the known location
164 if ( count( $matching_indices ) === 1
165 && $this->feed_details['location']['html'] === 'unknown'
166 && false !== $non_unknown_match ) {
167 $this->update_entry( $this->matching_entries[ $non_unknown_match ]['id'], $this->matching_entries[ $non_unknown_match ]['html_location'] );
168 } else {
169 if ( $this->feed_details['location']['html'] !== 'unknown'
170 && false !== $unknown_match ) {
171 $this->update_entry( $this->matching_entries[ $unknown_match ]['id'], $this->feed_details['location']['html'] );
172 } else {
173 $this->insert_entry();
174 }
175
176 }
177 }
178
179 }
180 }
181
182 /**
183 * Old feeds are only detected once a day to keep load on the server low.
184 *
185 * @return bool
186 *
187 * @since 1.14
188 */
189 public static function should_clear_old_locations() {
190 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
191 $last_old_feed_check = isset( $ctf_statuses_option['feed_locator']['last_check'] ) ? $ctf_statuses_option['feed_locator']['last_check'] : 0;
192
193 return $last_old_feed_check < time() - DAY_IN_SECONDS;
194 }
195
196 /**
197 * Old feeds are removed if they haven't been updated in two weeks.
198 *
199 * @since 1.14
200 */
201 public static function delete_old_locations() {
202 global $wpdb;
203
204 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
205 $two_weeks_ago = date( 'Y-m-d H:i:s', time() - 2 * WEEK_IN_SECONDS );
206
207 $affected = $wpdb->query( $wpdb->prepare(
208 "DELETE FROM $feed_locator_table_name WHERE last_update < %s;", $two_weeks_ago ) );
209
210 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
211 $ctf_statuses_option['feed_locator']['last_check'] = time();
212 if ( ! isset( $ctf_statuses_option['feed_locator']['initialized'] ) ) {
213 $ctf_statuses_option['feed_locator']['initialized'] = time();
214 }
215
216 update_option( 'ctf_statuses', $ctf_statuses_option, true );
217 }
218
219 /**
220 * Feeds are located with the page load randomly (5% or 1/30 loads)
221 * to decrease load on the server.
222 *
223 * If the locating just started (within 5 minutes) it is run more often
224 * to collect feed locations quickly.
225 *
226 * @return bool
227 *
228 * @since 1.14
229 */
230 public static function should_do_locating() {
231 if ( is_admin() ) {
232 return false;
233 }
234 $ctf_statuses_option = get_option( 'ctf_statuses', array() );
235 if ( isset( $ctf_statuses_option['feed_locator']['initialized'] )
236 && $ctf_statuses_option['feed_locator']['initialized'] < (time() - 300) ) {
237 $should_do_locating = rand( 1, 10 ) === 10;
238 } else {
239 $should_do_locating = rand( 1, 30 ) === 30;
240 }
241 $should_do_locating = apply_filters( 'ctf_should_do_locating', $should_do_locating );
242
243 return $should_do_locating;
244 }
245
246 /**
247 * Simliar to the should_do_locating method but will add an additional
248 * database query to see if there is a feed with an unknown location that
249 * matches the details of the feed in question.
250 *
251 * @param $feed_id
252 * @param $post_id
253 *
254 * @return bool
255 *
256 * @since 1.14
257 */
258 public static function should_do_ajax_locating( $feed_id, $post_id ) {
259 if ( is_admin() ) {
260 return false;
261 }
262 $should_do_locating = rand( 1, 50 ) === 50;
263
264 $should_do_locating = apply_filters( 'ctf_should_do_ajax_locating', $should_do_locating );
265
266 return $should_do_locating;
267 }
268
269 /**
270 * Feeds are located with the page load randomly (1/30 loads)
271 * to decrease load on the server.
272 *
273 * If the locating just started (within 5 minutes) it is run more often
274 * to collect feed locations quickly.
275 *
276 * @param $feed_id
277 * @param $post_id
278 *
279 * @return bool
280 *
281 * @since 1.14
282 */
283 public static function entries_need_locating( $feed_id, $post_id ) {
284 global $wpdb;
285 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
286
287 $one_day_ago = date( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS );
288
289 $results = $wpdb->get_results( $wpdb->prepare("
290 SELECT id
291 FROM $feed_locator_table_name
292 WHERE html_location = 'unknown'
293 AND last_update < %s
294 AND feed_id = %s
295 AND post_id = %d
296 LIMIT 1;", $one_day_ago, $feed_id, $post_id ),ARRAY_A );
297
298 return isset( $results[0] );
299 }
300
301 /**
302 * A custom table stores locations
303 *
304 * @since 1.14
305 */
306 public static function create_table() {
307 global $wpdb;
308
309 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
310
311 if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
312 $sql = "CREATE TABLE " . $feed_locator_table_name . " (
313 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
314 feed_id VARCHAR(50) DEFAULT '' NOT NULL,
315 post_id BIGINT(20) UNSIGNED NOT NULL,
316 html_location VARCHAR(50) DEFAULT 'unknown' NOT NULL,
317 shortcode_atts LONGTEXT NOT NULL,
318 last_update DATETIME
319 );";
320 $wpdb->query( $sql );
321 }
322 $error = $wpdb->last_error;
323 $query = $wpdb->last_query;
324 $had_error = false;
325 if ( $wpdb->get_var( "show tables like '$feed_locator_table_name'" ) != $feed_locator_table_name ) {
326 $had_error = true;
327 }
328
329 if ( ! $had_error ) {
330 $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX feed_id (feed_id)" );
331 $wpdb->query( "ALTER TABLE $feed_locator_table_name ADD INDEX post_id (post_id)" );
332 }
333 }
334
335 /**
336 * Counts the number of unique feeds in the database.
337 *
338 * @return int
339 *
340 * @since 1.14
341 */
342 public static function count_unique() {
343 global $wpdb;
344
345 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
346 $results_content = $wpdb->get_results( "
347 SELECT COUNT(*) AS num_entries
348 FROM $feed_locator_table_name
349 WHERE html_location = 'content'
350 ", ARRAY_A );
351
352
353 $results_other = $wpdb->get_results( "
354 SELECT COUNT(*) AS num_entries
355 FROM $feed_locator_table_name
356 WHERE html_location != 'content'
357 AND html_location != 'unknown'
358 GROUP BY feed_id
359 ", ARRAY_A );
360
361 $total = 0;
362 if ( isset( $results_content[0]['num_entries'] ) ) {
363 $total += (int)$results_content[0]['num_entries'];
364 }
365 if ( isset( $results_other[0]['num_entries'] ) ) {
366 $total += (int)$results_other[0]['num_entries'];
367 }
368
369 return $total;
370 }
371
372 /**
373 * Creates a summary of the located feeds in an array
374 *
375 * @return array
376 *
377 * @since 1.14
378 */
379 public static function summary() {
380 global $wpdb;
381
382 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
383
384 $locations = array(
385 array(
386 'label' => __( 'Content', 'custom-twitter-feeds' ),
387 'html_locations' => array( 'content', 'unknown' )
388 ),
389 array(
390 'label' => __( 'Header', 'custom-twitter-feeds' ),
391 'html_locations' => array( 'header' ),
392 'group_by' => 'feed_id'
393 ),
394 array(
395 'label' => __( 'Sidebar', 'custom-twitter-feeds' ),
396 'html_locations' => array( 'sidebar' ),
397 'group_by' => 'feed_id'
398 ),
399 array(
400 'label' => __( 'Footer', 'custom-twitter-feeds' ),
401 'html_locations' => array( 'footer' ),
402 'group_by' => 'feed_id'
403 )
404 );
405
406 $one_result_found = false;
407
408 foreach ( $locations as $key => $location ) {
409 $in = implode( "', '", $location['html_locations'] );
410 $group_by = isset( $location['group_by'] ) ? "GROUP BY " . $location['group_by'] : "";
411 $results = $wpdb->get_results("
412 SELECT *
413 FROM $feed_locator_table_name
414 WHERE html_location IN ('$in')
415 $group_by
416 ORDER BY last_update ASC",ARRAY_A );
417
418 if ( isset( $results[0] ) ) {
419 $one_result_found = true;
420 }
421
422 $locations[ $key ]['results'] = $results;
423 }
424
425 if ( ! $one_result_found ) {
426 return array();
427 }
428
429 return $locations;
430 }
431
432
433 /**
434 * Queries the locator table for feeds by feed_id
435 *
436 * @param $args
437 *
438 * @return array|object|null
439 *
440 * @since 2.0
441 */
442 public static function twitter_feed_locator_query( $args ) {
443 global $wpdb;
444 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
445
446 $group_by = '';
447 if ( isset( $args['group_by'] ) ) {
448 $group_by = "GROUP BY " . esc_sql( $args['group_by'] );
449 }
450
451 $location_string = 'content';
452 if ( isset( $args['html_location'] ) ) {
453 $locations = array_map( 'esc_sql', $args['html_location'] );
454 $location_string = implode( "', '", $locations );
455 }
456
457 $page = 0;
458 if ( isset( $args['page'] ) ) {
459 $page = (int)$args['page'] - 1;
460 unset( $args['page'] );
461 }
462
463 $offset = max( 0, $page * CTF_Db::RESULTS_PER_PAGE );
464
465 if ( isset( $args['shortcode_atts'] ) ) {
466 $results = $wpdb->get_results( $wpdb->prepare("
467 SELECT *
468 FROM $feed_locator_table_name
469 WHERE shortcode_atts = %s
470 AND html_location IN ( '$location_string' )
471 $group_by
472 LIMIT %d
473 OFFSET %d;", $args['shortcode_atts'], CTF_Db::RESULTS_PER_PAGE, $offset ),ARRAY_A );
474 } else {
475 $results = $wpdb->get_results( $wpdb->prepare("
476 SELECT *
477 FROM $feed_locator_table_name
478 WHERE feed_id = %s
479 AND html_location IN ( '$location_string' )
480 $group_by
481 LIMIT %d
482 OFFSET %d;", $args['feed_id'], CTF_Db::RESULTS_PER_PAGE, $offset ),ARRAY_A );
483 }
484
485 return $results;
486 }
487
488 /**
489 * Queries all legacy feeds that have been located
490 *
491 * @param $args
492 *
493 * @return array|object|null
494 *
495 * @since 2.0
496 */
497 public static function legacy_twitter_feed_locator_query( $args ) {
498 global $wpdb;
499 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
500
501 $group_by = '';
502 if ( isset( $args['group_by'] ) ) {
503 $group_by = "GROUP BY " . esc_sql( $args['group_by'] );
504 }
505
506 $location_string = 'content';
507 if ( isset( $args['html_location'] ) ) {
508 $locations = array_map( 'esc_sql', $args['html_location'] );
509 $location_string = implode( "', '", $locations );
510 }
511
512 $page = 0;
513 if ( isset( $args['page'] ) ) {
514 $page = (int)$args['page'] - 1;
515 unset( $args['page'] );
516 }
517
518 $offset = max( 0, $page * CTF_Db::RESULTS_PER_PAGE );
519 $limit = CTF_Db::RESULTS_PER_PAGE;
520
521 $results = $wpdb->get_results( "
522 SELECT *
523 FROM $feed_locator_table_name
524 WHERE feed_id NOT LIKE '*%'
525 AND html_location IN ( '$location_string' )
526 $group_by
527 LIMIT $limit
528 OFFSET $offset;", ARRAY_A );
529
530 return $results;
531 }
532
533 public static function update_legacy_to_builder( $args ) {
534 global $wpdb;
535 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
536
537 $data = array(
538 'feed_id' => '*'.$args['new_feed_id'],
539 'shortcode_atts' => '{"feed":"'.$args['new_feed_id'].'"}'
540 );
541
542 $affected = $wpdb->query(
543 $wpdb->prepare(
544 "UPDATE $feed_locator_table_name
545 SET feed_id = %s, shortcode_atts = %s",
546 $data['feed_id'], $data['shortcode_atts']
547 )
548 );
549
550 return $affected;
551 }
552
553 /**
554 * Simple count of rows based on args
555 *
556 * @param array $args
557 *
558 * @return int
559 *
560 * @since 2.0
561 */
562 public static function count( $args ) {
563 global $wpdb;
564 $feed_locator_table_name = esc_sql( $wpdb->prefix . CTF_FEED_LOCATOR );
565
566 if ( isset( $args['shortcode_atts'] ) ) {
567 $results = $wpdb->get_results( $wpdb->prepare("
568 SELECT COUNT(*) AS num_entries
569 FROM $feed_locator_table_name
570 WHERE shortcode_atts = %s
571 ", $args['shortcode_atts'] ), ARRAY_A );
572 } else {
573 $results = $wpdb->get_results( $wpdb->prepare("
574 SELECT COUNT(*) AS num_entries
575 FROM $feed_locator_table_name
576 WHERE feed_id = %s
577 ", $args['feed_id'] ), ARRAY_A );
578 }
579
580
581 if ( isset( $results[0]['num_entries'] ) ) {
582 return (int)$results[0]['num_entries'];
583 }
584
585 return 0;
586 }
587 }
588