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 / Services / ShortcodeService.php
reviews-feed / class / Common / Services Last commit date
Upgrade 1 month ago CLIService.php 1 month ago FeedCacheUpdateService.php 1 month ago MigrationReactivationNotice.php 1 month ago SBR_Upgrader.php 1 month ago SettingsManagerService.php 1 month ago ShortcodeService.php 1 month ago SiteUrlWatcher.php 1 month ago UsageTrackingService.php 1 month ago
ShortcodeService.php
208 lines
1 <?php
2
3 namespace SmashBalloon\Reviews\Common\Services;
4
5 use SmashBalloon\Reviews\Common\Feed;
6 use SmashBalloon\Reviews\Common\FeedCache;
7 use SmashBalloon\Reviews\Common\FeedDisplay;
8 use SmashBalloon\Reviews\Common\Feed_Locator;
9 use SmashBalloon\Reviews\Common\Parser;
10 use SmashBalloon\Reviews\Common\SBR_Settings;
11 use Smashballoon\Stubs\Services\ServiceProvider;
12
13 class ShortcodeService extends ServiceProvider
14 {
15 public function register()
16 {
17 add_shortcode('reviews-feed', [$this, 'render']);
18 }
19
20 public function render($atts = array())
21 {
22 $feed_id = ! empty($atts['feed']) ? $atts['feed'] : 0;
23 $is_single_manual_review = isset($atts['name']) && ! empty($atts['name']) ? true : false;
24
25 $settings = SBR_Settings::get_settings_by_feed_id($feed_id, false, $is_single_manual_review);
26
27 if ($is_single_manual_review) {
28 $settings = array_merge(
29 $settings,
30 $this->get_single_manual_review_content($atts)
31 );
32 }
33
34 do_action('sbr_before_shortcode_render', $settings);
35
36 // Track feed location for usage statistics.
37 $this->track_feed_location($feed_id, $atts);
38
39 $feed = new Feed($settings, $feed_id, new FeedCache($feed_id, 2 * DAY_IN_SECONDS));
40
41 $feed->init();
42 if (! empty($feed->get_errors())) {
43 $feed_display = new FeedDisplay($feed, new Parser());
44 return $feed_display->error_html();
45 }
46 $feed->get_set_cache();
47
48 $feed_display = new FeedDisplay($feed, new Parser());
49
50 return $feed_display->with_wrap();
51 }
52
53 /**
54 * Track the feed location for usage statistics.
55 *
56 * @param int|string $feed_id The feed ID.
57 * @param array $atts Shortcode attributes.
58 */
59 private function track_feed_location($feed_id, $atts)
60 {
61 // Only track if we have a valid feed ID and post ID.
62 if (empty($feed_id)) {
63 return;
64 }
65
66 // Get the current post ID.
67 $post_id = get_the_ID();
68 if (! $post_id) {
69 // Try to get from global post.
70 global $post;
71 $post_id = ! empty($post->ID) ? $post->ID : 0;
72 }
73
74 if (! $post_id) {
75 return;
76 }
77
78 // Determine HTML location based on context.
79 $html_location = $this->determine_html_location();
80
81 // Check if we should track this request.
82 // Track more frequently initially to collect data, then reduce to save DB load.
83 $should_track = $this->should_track_location($feed_id, $post_id);
84 if (! $should_track) {
85 return;
86 }
87
88 $feed_details = array(
89 'feed_id' => $feed_id,
90 'atts' => is_array($atts) ? $atts : array( 'feed' => $feed_id ),
91 'location' => array(
92 'post_id' => $post_id,
93 'html' => $html_location,
94 ),
95 );
96
97 // Ensure feed attribute is set.
98 if (! isset($feed_details['atts']['feed'])) {
99 $feed_details['atts']['feed'] = $feed_id;
100 }
101
102 $locator = new Feed_Locator($feed_details);
103 $locator->add_or_update_entry();
104 }
105
106 /**
107 * Determine if we should track this feed location.
108 *
109 * Always tracks if this feed/post combination hasn't been tracked yet.
110 * For already tracked combinations, uses random sampling to reduce DB load.
111 *
112 * @param int|string $feed_id The feed ID.
113 * @param int $post_id The post ID.
114 * @return bool Whether to track this location.
115 */
116 private function should_track_location($feed_id, $post_id)
117 {
118 global $wpdb;
119
120 $feed_locator_table = $wpdb->prefix . SBR_FEED_LOCATOR;
121
122 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is safe.
123 $existing = $wpdb->get_var(
124 $wpdb->prepare(
125 "SELECT COUNT(*) FROM $feed_locator_table WHERE feed_id = %s AND post_id = %d",
126 (string) $feed_id,
127 $post_id
128 )
129 );
130 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
131
132 // If no existing entry, always track (first visit).
133 if (empty($existing) || (int) $existing === 0) {
134 return true;
135 }
136
137 // For existing entries, use random sampling to update periodically (reduce DB load).
138 // This helps keep the last_update timestamp fresh.
139 return Feed_Locator::should_do_locating();
140 }
141
142 /**
143 * Determine the HTML location where the feed is being rendered.
144 *
145 * @return string The HTML location (content, header, footer, sidebar, or unknown).
146 */
147 private function determine_html_location()
148 {
149 // Check if we're in a sidebar/widget.
150 if (is_active_widget(false, false, 'text', true) || doing_action('dynamic_sidebar')) {
151 return 'sidebar';
152 }
153
154 // Check if we're in the header.
155 if (doing_action('wp_head') || did_action('wp_head') && ! did_action('wp_footer') && ! in_the_loop()) {
156 return 'header';
157 }
158
159 // Check if we're in the footer.
160 if (doing_action('wp_footer')) {
161 return 'footer';
162 }
163
164 // Check if we're in the main content loop.
165 if (in_the_loop() || is_singular()) {
166 return 'content';
167 }
168
169 return 'unknown';
170 }
171
172 /**
173 * Get single manual review content settings.
174 *
175 * @param array $atts Shortcode attributes.
176 * @return array Settings array.
177 */
178 public function get_single_manual_review_content($atts)
179 {
180 $settings = array();
181 $settings['singleManualReview'] = true;
182 $settings['singleManualReviewContent'] = array(
183 'name' => isset($atts['name']) && ! empty($atts['name']) ? $atts['name'] : false,
184 'content' => isset($atts['content']) && ! empty($atts['content']) ? $atts['content'] : false,
185 'rating' => isset($atts['rating']) && ! empty($atts['rating']) ? $atts['rating'] : false,
186 'avatar' => isset($atts['avatar']) && ! empty($atts['avatar']) ? $atts['avatar'] : false,
187 'time' => isset($atts['time']) && ! empty($atts['time']) ? $atts['time'] : false,
188 'provider' => isset($atts['provider']) && ! empty($atts['provider']) ? $atts['provider'] : false,
189 );
190 $settings['showHeader'] = false;
191 $settings['showLoadButton'] = false;
192
193 // This to remove the multiple columns since we are only showing one Review.
194 $settings['gridDesktopColumns'] = 1;
195 $settings['gridTabletColumns'] = 1;
196 $settings['gridMobileColumns'] = 1;
197 $settings['masonryDesktopColumns'] = 1;
198 $settings['masonryTabletColumns'] = 1;
199 $settings['masonryMobileColumns'] = 1;
200 $settings['carouselDesktopColumns'] = 1;
201 $settings['carouselTabletColumns'] = 1;
202 $settings['carouselMobileColumns'] = 1;
203
204 return $settings;
205 }
206
207 }
208