PluginProbe ʕ •ᴥ•ʔ
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More / 2.9.0
Reviews Feed – Add Testimonials and Customer Reviews From Google Reviews, Yelp, TripAdvisor, and More v2.9.0
2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.7 2.6.8 2.6.5 2.6.4 2.6.3 2.6.2 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1 1.1.1 1.1.2 1.2.0 2.0 2.1.0 2.1.1 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1
reviews-feed / class / Common / Feed_Locator.php
reviews-feed / class / Common Last commit date
Admin 1 month ago Builder 1 month ago Customizer 1 month ago Exceptions 1 month ago Helpers 1 month ago Integrations 1 month ago Migrations 1 month ago ReviewAlerts 1 month ago Services 1 month ago Settings 1 month ago Support 1 month ago Traits 1 month ago Utils 1 month ago AuthorizationStatusCheck.php 1 month ago BusinessDataCache.php 1 month ago Clear_Cache.php 1 month ago Container.php 1 month ago DisplayElements.php 1 month ago Email_Notification.php 1 month ago Error_Reporter.php 1 month ago Feed.php 1 month ago FeedCache.php 1 month ago FeedCacheUpdater.php 1 month ago FeedDisplay.php 1 month ago Feed_Locator.php 1 month ago Parser.php 1 month ago PostAggregator.php 1 month ago RemoteRequest.php 1 month ago SBR_Education.php 1 month ago SBR_Settings.php 1 month ago ServiceContainer.php 1 month ago SinglePostCache.php 1 month ago TemplateRenderer.php 1 month ago Tooltip_Wizard.php 1 month ago Util.php 1 month ago
Feed_Locator.php
530 lines
1 <?php
2
3 // phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL
4 // Note: Legacy file with pre-existing PHPCS issues. Direct DB queries required for feed locator.
5
6 /**
7 * Class SBY_Feed_Locator
8 *
9 * Locates feeds on the site and logs information about them in the database.
10 *
11 * @since 1.0
12 */
13
14 namespace SmashBalloon\Reviews\Common;
15
16 use Smashballoon\Customizer\V2\DB;
17
18 class Feed_Locator{
19 private $feed_details;
20
21 private $expiration_time;
22
23 private $matching_entries;
24
25 public function __construct($feed_details)
26 {
27
28 $this->feed_details = $feed_details;
29
30 $this->matching_entries = array();
31
32 $this->expiration_time = time() - 2 * WEEK_IN_SECONDS;
33 }
34
35 /**
36 * Returns records that match the post ID and feed ID
37 * of the feed being located
38 *
39 * @return array
40 *
41 * @since 1.0
42 */
43 public function retrieve_matching_entries()
44 {
45 global $wpdb;
46 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
47
48 $results = $wpdb->get_results($wpdb->prepare("
49 SELECT *
50 FROM $feed_locator_table_name
51 WHERE post_id = %d
52 AND feed_id = %s", $this->feed_details['location']['post_id'], $this->feed_details['feed_id']), ARRAY_A);
53
54 return $results;
55 }
56
57 /**
58 * Add feed being located to the database
59 *
60 * @since 1.0
61 */
62 public function insert_entry()
63 {
64 global $wpdb;
65
66 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
67
68 $affected = $wpdb->query($wpdb->prepare(
69 "INSERT INTO $feed_locator_table_name
70 (feed_id,
71 post_id,
72 html_location,
73 shortcode_atts,
74 last_update)
75 VALUES (
76 %s,
77 %d,
78 %s,
79 %s,
80 %s);",
81 $this->feed_details['atts']['feed'],
82 $this->feed_details['location']['post_id'],
83 $this->feed_details['location']['html'],
84 sbr_json_encode($this->feed_details['atts']),
85 date('Y-m-d H:i:s')
86 ));
87 }
88
89 /**
90 * Update a record based on the existing "id" column. Location can change
91 * from "unknown" to one of footer, content, header, or sidebar.
92 *
93 * @param $id
94 * @param $location
95 *
96 * @since 1.0
97 */
98 public function update_entry($id, $location)
99 {
100 global $wpdb;
101
102 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
103
104 $query = $wpdb->query($wpdb->prepare("
105 UPDATE $feed_locator_table_name
106 SET last_update = %s, html_location = %s
107 WHERE id = %d;", date('Y-m-d H:i:s'), $location, $id));
108 }
109
110 /**
111 * Processes a feed being located based on whether or not the record
112 * exists as well as whether or not an unknown location needs to be
113 * updated.
114 *
115 * @since 1.0
116 */
117 public function add_or_update_entry()
118 {
119 if (empty($this->feed_details['feed_id'])) {
120 return;
121 }
122
123 $this->matching_entries = $this->retrieve_matching_entries();
124
125 if (empty($this->matching_entries)) {
126 $this->insert_entry();
127 } else {
128 $matching_indices = array();
129 $matched_location = false;
130 $non_unknown_match = false;
131 $unknown_match = false;
132
133 foreach ($this->matching_entries as $index => $matching_entry) {
134 $details_atts = is_array($this->feed_details['atts']) ? $this->feed_details['atts'] : array();
135 $matching_atts = json_decode($matching_entry['shortcode_atts'], true);
136 if (! is_array($matching_atts)) {
137 $matching_atts = array();
138 }
139 $atts_diff = array_diff($matching_atts, $details_atts); // determines if the shortcode settings match the shortcode settings of an existing feed
140 if (empty($atts_diff)) {
141 $matching_indices[] = $matching_entry['id'];
142 if ($matching_entry['html_location'] === $this->feed_details['location']['html']) {
143 $matched_location = $index;
144 $this->update_entry($matching_entry['id'], $matching_entry['html_location']);
145 }
146 if ($matching_entry['html_location'] !== 'unknown') {
147 $non_unknown_match = $index;
148 } else {
149 $unknown_match = $index;
150 }
151 }
152 }
153
154 if (false === $matched_location) {
155 // 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
156 if (
157 count($matching_indices) === 1
158 && $this->feed_details['location']['html'] === 'unknown'
159 && false !== $non_unknown_match
160 ) {
161 $this->update_entry($this->matching_entries[ $non_unknown_match ]['id'], $this->matching_entries[ $non_unknown_match ]['html_location']);
162 } else {
163 if (
164 $this->feed_details['location']['html'] !== 'unknown'
165 && false !== $unknown_match
166 ) {
167 $this->update_entry($this->matching_entries[ $unknown_match ]['id'], $this->feed_details['location']['html']);
168 } else {
169 $this->insert_entry();
170 }
171 }
172 }
173 }
174 }
175
176 /**
177 * Old feeds are only detected once a day to keep load on the server low.
178 *
179 * @return bool
180 *
181 * @since 1.0
182 */
183 public static function should_clear_old_locations()
184 {
185 $sbr_statuses_option = get_option('sbr_statuses', array());
186 $last_old_feed_check = isset($sbr_statuses_option['feed_locator']['last_check']) ? $sbr_statuses_option['feed_locator']['last_check'] : 0;
187
188 return $last_old_feed_check < time() - DAY_IN_SECONDS;
189 }
190
191 /**
192 * Old feeds are removed if they haven't been updated in two weeks.
193 *
194 * @since 1.0
195 */
196 public static function delete_old_locations()
197 {
198 global $wpdb;
199
200 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
201 $two_weeks_ago = date('Y-m-d H:i:s', time() - 2 * WEEK_IN_SECONDS);
202
203 $affected = $wpdb->query($wpdb->prepare(
204 "DELETE FROM $feed_locator_table_name WHERE last_update < %s;",
205 $two_weeks_ago
206 ));
207
208 $sbr_statuses_option = get_option('sbr_statuses', array());
209 $sbr_statuses_option['feed_locator']['last_check'] = time();
210 if (! isset($sbr_statuses_option['feed_locator']['initialized'])) {
211 $sbr_statuses_option['feed_locator']['initialized'] = time();
212 }
213
214 update_option('sbr_statuses', $sbr_statuses_option, true);
215 }
216
217 /**
218 * Feeds are located with the page load randomly (5% or 1/30 loads)
219 * to decrease load on the server.
220 *
221 * If the locating just started (within 5 minutes) it is run more often
222 * to collect feed locations quickly.
223 *
224 * @return bool
225 *
226 * @since 1.0
227 */
228 public static function should_do_locating()
229 {
230 $sbr_statuses_option = get_option('sbr_statuses', array());
231 if (
232 isset($sbr_statuses_option['feed_locator']['initialized'])
233 && $sbr_statuses_option['feed_locator']['initialized'] < (time() - 300)
234 ) {
235 $should_do_locating = rand(1, 10) === 10;
236 } else {
237 $should_do_locating = rand(1, 30) === 30;
238 }
239 $should_do_locating = apply_filters('sbr_should_do_locating', $should_do_locating);
240
241 return $should_do_locating;
242 }
243
244 /**
245 * Simliar to the should_do_locating method but will add an additional
246 * database query to see if there is a feed with an unknown location that
247 * matches the details of the feed in question.
248 *
249 * @param $feed_id
250 * @param $post_id
251 *
252 * @return bool
253 *
254 * @since 1.0
255 */
256 public static function should_do_ajax_locating($feed_id, $post_id)
257 {
258
259 $should_do_locating = rand(1, 50) === 50;
260
261 $should_do_locating = apply_filters('sbr_should_do_ajax_locating', $should_do_locating);
262
263 return $should_do_locating;
264 }
265
266 /**
267 * Feeds are located with the page load randomly (1/30 loads)
268 * to decrease load on the server.
269 *
270 * If the locating just started (within 5 minutes) it is run more often
271 * to collect feed locations quickly.
272 *
273 * @param $feed_id
274 * @param $post_id
275 *
276 * @return bool
277 *
278 * @since 1.0
279 */
280 public static function entries_need_locating($feed_id, $post_id)
281 {
282 global $wpdb;
283 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
284
285 $one_day_ago = date('Y-m-d H:i:s', time() - DAY_IN_SECONDS);
286
287 $results = $wpdb->get_results($wpdb->prepare("
288 SELECT id
289 FROM $feed_locator_table_name
290 WHERE html_location = 'unknown'
291 AND last_update < %s
292 AND feed_id = %s
293 AND post_id = %d
294 LIMIT 1;", $one_day_ago, $feed_id, $post_id), ARRAY_A);
295
296 return isset($results[0]);
297 }
298
299 /**
300 * A custom table stores locations
301 *
302 * @since 1.0
303 */
304 public static function create_table()
305 {
306 global $wpdb;
307
308 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
309
310 if ($wpdb->get_var("show tables like '$feed_locator_table_name'") != $feed_locator_table_name) {
311 $sql = "CREATE TABLE " . $feed_locator_table_name . " (
312 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
313 feed_id VARCHAR(50) DEFAULT '' NOT NULL,
314 post_id BIGINT(20) UNSIGNED NOT NULL,
315 html_location VARCHAR(50) DEFAULT 'unknown' NOT NULL,
316 shortcode_atts LONGTEXT NOT NULL,
317 last_update DATETIME
318 );";
319 $wpdb->query($sql);
320 }
321 $error = $wpdb->last_error;
322 $query = $wpdb->last_query;
323 $had_error = false;
324 if ($wpdb->get_var("show tables like '$feed_locator_table_name'") != $feed_locator_table_name) {
325 $had_error = true;
326 }
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 /**
337 * Counts the number of unique feeds in the database.
338 *
339 * @return int
340 *
341 * @since 1.0
342 */
343 public static function count_unique()
344 {
345 global $wpdb;
346
347 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
348 $results_content = $wpdb->get_results("
349 SELECT COUNT(*) AS num_entries
350 FROM $feed_locator_table_name
351 WHERE html_location = 'content'
352 ", ARRAY_A);
353
354
355 $results_other = $wpdb->get_results("
356 SELECT COUNT(*) AS num_entries
357 FROM $feed_locator_table_name
358 WHERE html_location != 'content'
359 AND html_location != 'unknown'
360 GROUP BY feed_id
361 ", ARRAY_A);
362
363 $total = 0;
364 if (isset($results_content[0]['num_entries'])) {
365 $total += (int)$results_content[0]['num_entries'];
366 }
367 if (isset($results_other[0]['num_entries'])) {
368 $total += (int)$results_other[0]['num_entries'];
369 }
370
371 return $total;
372 }
373
374 /**
375 * Creates a summary of the located feeds in an array
376 *
377 * @return array
378 *
379 * @since 1.0
380 */
381 public static function summary()
382 {
383 global $wpdb;
384
385 $feed_locator_table_name = esc_sql($wpdb->prefix . SBR_FEED_LOCATOR);
386
387 $locations = array(
388 array(
389 'label' => __('Content', 'reviews-feed'),
390 'html_locations' => array( 'content', 'unknown' )
391 ),
392 array(
393 'label' => __('Header', 'reviews-feed'),
394 'html_locations' => array( 'header' ),
395 'group_by' => 'feed_id'
396 ),
397 array(
398 'label' => __('Sidebar', 'reviews-feed'),
399 'html_locations' => array( 'sidebar' ),
400 'group_by' => 'feed_id'
401 ),
402 array(
403 'label' => __('Footer', 'reviews-feed'),
404 'html_locations' => array( 'footer' ),
405 'group_by' => 'feed_id'
406 )
407 );
408
409 $one_result_found = false;
410
411 foreach ($locations as $key => $location) {
412 $in = implode("', '", $location['html_locations']);
413 $group_by = isset($location['group_by']) ? "GROUP BY " . $location['group_by'] : "";
414 $results = $wpdb->get_results("
415 SELECT *
416 FROM $feed_locator_table_name
417 WHERE html_location IN ('$in')
418 $group_by
419 ORDER BY last_update ASC", ARRAY_A);
420
421 if (isset($results[0])) {
422 $one_result_found = true;
423 }
424
425 $locations[ $key ]['results'] = $results;
426 }
427
428 if (! $one_result_found) {
429 return array();
430 }
431
432 return $locations;
433 }
434
435
436 public static function feed_locator_query($args)
437 {
438 global $wpdb;
439 $feed_locator_table_name = $wpdb->prefix . SBR_FEED_LOCATOR;
440
441 $group_by = '';
442 if (isset($args['group_by'])) {
443 $group_by = 'GROUP BY ' . esc_sql($args['group_by']);
444 }
445
446 $location_string = 'content';
447 if (isset($args['html_location'])) {
448 $locations = array_map('esc_sql', $args['html_location']);
449 $location_string = implode("', '", $locations);
450 }
451
452 $page = 0;
453 if (isset($args['page'])) {
454 $page = (int) $args['page'] - 1;
455 unset($args['page']);
456 }
457
458 $offset = max(0, $page * DB::RESULTS_PER_PAGE);
459 $limit = DB::RESULTS_PER_PAGE;
460
461 // Build feed_id filter - if specific feed_id provided, filter by it
462 $feed_id_filter = "feed_id NOT LIKE '*%'";
463 if (isset($args['feed_id']) && ! empty($args['feed_id'])) {
464 $feed_id_filter = $wpdb->prepare('feed_id = %s', $args['feed_id']);
465 }
466
467 $results = $wpdb->get_results(
468 "
469 SELECT *
470 FROM $feed_locator_table_name
471 WHERE $feed_id_filter
472 AND html_location IN ( '$location_string' )
473 $group_by
474 LIMIT $limit
475 OFFSET $offset;",
476 ARRAY_A
477 );
478
479 return $results;
480 }
481
482 /**
483 * Simple count of rows based on args
484 *
485 * @param array $args
486 *
487 * @return int
488 *
489 * @since 4.0
490 */
491 public static function count($args)
492 {
493 global $wpdb;
494 $feed_locator_table_name = $wpdb->prefix . SBR_FEED_LOCATOR;
495
496 if (isset($args['shortcode_atts'])) {
497 $results = $wpdb->get_results(
498 $wpdb->prepare(
499 "
500 SELECT COUNT(*) AS num_entries
501 FROM $feed_locator_table_name
502 WHERE shortcode_atts = %s
503 ",
504 $args['shortcode_atts']
505 ),
506 ARRAY_A
507 );
508 } else {
509 $results = $wpdb->get_results(
510 $wpdb->prepare(
511 "
512 SELECT COUNT(*) AS num_entries
513 FROM $feed_locator_table_name
514 WHERE feed_id = %s
515 ",
516 $args['feed_id']
517 ),
518 ARRAY_A
519 );
520 }
521
522 if (isset($results[0]['num_entries'])) {
523 return (int) $results[0]['num_entries'];
524 }
525
526 return 0;
527 }
528
529 }
530