PluginProbe
Ultimate Store Kit – Store Builder Addons for Elementor, WooCommerce Store Builder, EDD Store Builder / 3.1.4
Ultimate Store Kit – Store Builder Addons for Elementor, WooCommerce Store Builder, EDD Store Builder v3.1.4
3.1.4 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.0.7 3.0.5 3.0.4 3.0.3 3.0.2 trunk 1.5.0 1.5.1 1.5.2 1.6.1 1.6.2 1.6.3 1.6.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 All 93 releases
← All changes | includes/Admin/Feeds.php +43 -57 3.0.23.1.4 View file →
@@ -15,8 +15,19 @@
15 15 use Singleton;
16 16 private $settings;
17 17
18 18 /**
19 + * Max seconds to wait for a remote feed. Kept short so a slow or dead
20 + * endpoint can never stall the admin dashboard into a gateway timeout.
21 + */
22 + const REQUEST_TIMEOUT = 5;
23 +
24 + /**
25 + * How long to skip remote requests after a failure.
26 + */
27 + const FAILURE_BACKOFF = HOUR_IN_SECONDS;
28 +
29 + /**
19 30 * Static variable to track if the feed has been displayed
20 31 */
21 32 private static $feed_displayed = false;
22 33
@@ -27,9 +38,8 @@
27 38 $this->settings = $settings ?: [
28 39 'feed_title' => 'BdThemes News & Updates',
29 40 'transient_key' => 'bdthemes_product_feeds',
30 41 'feed_link' => 'https://bdthemes.com/feed',
31 - 'remote_feed_link' => 'https://dashboard.bdthemes.io/wp-json/bdthemes/v1/product-feed/?product_category=element-pack',
32 42 'text_domain' => 'ultimate-store-kit',
33 43 'footer_links' => [
34 44 [
35 45 'url' => 'https://bdthemes.com/blog/',
@@ -82,62 +92,12 @@
82 92 /**
83 93 * Display RSS Feeds Content
84 94 */
85 95 public function display_rss_feeds_content() {
86 - $feeds = $this->get_remote_feeds_data();
87 - if (is_array($feeds)) {
88 - foreach ($feeds as $feed) {
89 -?>
90 - <div class="activity-block">
91 - <a href="<?php echo esc_url($feed->demo_link); ?>" target="_blank" style="margin-bottom:10px; display: inline-block;">
92 - <img src="<?php echo esc_url($feed->image); ?>" style="width:100%;min-height:240px;">
93 - </a>
94 - <p>
95 - <?php echo wp_kses_post(wp_trim_words(wp_strip_all_tags($feed->content), 50)); ?>
96 - <a href="<?php echo esc_url($feed->demo_link); ?>" target="_blank">
97 - <?php esc_html_e('Learn more...', $this->settings['text_domain']); ?>
98 - </a>
99 - </p>
100 - </div>
101 - <?php
102 - }
103 - }
104 96 echo wp_kses_post($this->get_rss_posts_data());
105 97 }
106 98
107 - /**
108 - * Get Remote Feeds Data
109 - *
110 - * @return array|mixed
111 - */
112 - private function get_remote_feeds_data() {
113 - $transient_key = $this->settings['transient_key'];
114 - $cached_data = get_transient($transient_key);
115 99
116 - if (! empty($cached_data)) {
117 - return json_decode($cached_data);
118 - }
119 -
120 - $response = wp_remote_get(
121 - $this->settings['remote_feed_link'],
122 - array(
123 - 'timeout' => 30,
124 - 'headers' => array(
125 - 'Accept' => 'application/json',
126 - ),
127 - )
128 - );
129 -
130 - if (is_wp_error($response)) {
131 - return [];
132 - }
133 -
134 - $response_body = wp_remote_retrieve_body($response);
135 - set_transient($transient_key, $response_body, 6 * HOUR_IN_SECONDS);
136 -
137 - return json_decode($response_body);
138 - }
139 -
140 100 /**
141 101 * Get RSS Posts Data
142 102 *
143 103 * @return string
@@ -142,10 +102,14 @@
142 102 *
143 103 * @return string
144 104 */
145 105 private function get_rss_posts_data() {
146 - $transient_key = $this->settings['transient_key'] . '_rss';
147 - $cached_data = get_transient($transient_key);
106 + // Written out in full rather than concatenated so the prefix is visible to
107 + // static analysis. The resolved key is byte-identical to the previous
108 + // $this->settings['transient_key'] . '_rss', so no cached data is orphaned.
109 + $transient_key = 'bdthemes_product_feeds_rss';
110 + $transient_failed_key = 'bdthemes_product_feeds_rss_failed';
111 + $cached_data = get_transient($transient_key);
148 112
149 113 if (! empty($cached_data)) {
150 114 /**
151 115 * Decode as associative array
@@ -150,15 +114,27 @@
150 114 /**
151 115 * Decode as associative array
152 116 */
153 117 $rss_items = json_decode($cached_data, true);
118 +
119 + if (! is_array($rss_items)) {
120 + $rss_items = [];
121 + }
122 + } elseif (get_transient($transient_failed_key)) {
123 + /**
124 + * A recent fetch failed, so skip the blocking request entirely.
125 + */
126 + $rss_items = [];
154 127 } else {
155 128 include_once ABSPATH . WPINC . '/feed.php';
156 129
130 + add_action('wp_feed_options', [$this, 'set_feed_timeout']);
157 131 $rss = fetch_feed($this->settings['feed_link']);
132 + remove_action('wp_feed_options', [$this, 'set_feed_timeout']);
158 133
159 134 if (is_wp_error($rss)) {
160 - return '<li>' . esc_html__('Items Not Found', $this->settings['text_domain']) . '.</li>';
135 + set_transient($transient_failed_key, 1, self::FAILURE_BACKOFF);
136 + return '<li>' . esc_html__('Items Not Found', 'ultimate-store-kit') . '.</li>';
161 137 }
162 138
163 139 $maxitems = $rss->get_item_quantity(5);
164 140 $rss_items = $rss->get_items(0, $maxitems);
@@ -183,9 +159,9 @@
183 159 ?>
184 160 <div class="bdt-widget">
185 161 <ul>
186 162 <?php if (empty($rss_items)) : ?>
187 - <li><?php esc_html_e('Items Not Found', $this->settings['text_domain']); ?>.</li>
163 + <li><?php esc_html_e('Items Not Found', 'ultimate-store-kit'); ?>.</li>
188 164 <?php else : ?>
189 165 <?php foreach ($rss_items as $item) : ?>
190 166 <li>
191 167 <a target="_blank" href="<?php echo esc_url($item['link']); ?>"
@@ -190,14 +166,14 @@
190 166 <li>
191 167 <a target="_blank" href="<?php echo esc_url($item['link']); ?>"
192 168 title="<?php echo esc_html($item['date']); ?>">
193 169 <?php if ($this->is_feed_item_new($item['date'])) : ?>
194 - <span class="bdt-feed-badge bdt-feed-badge--new"><?php esc_html_e('New', $this->settings['text_domain']); ?></span>
170 + <span class="bdt-feed-badge bdt-feed-badge--new"><?php esc_html_e('New', 'ultimate-store-kit'); ?></span>
195 171 <?php endif; ?>
196 172 <?php echo esc_html($item['title']); ?>
197 173 </a>
198 174 <span class="bdt-date" style="display: block; margin: 0;">
199 - <?php echo esc_html(human_time_diff($item['date'], current_time('timestamp')) . ' ' . __('ago', $this->settings['text_domain'])); ?>
175 + <?php echo esc_html(human_time_diff($item['date'], current_time('timestamp')) . ' ' . __('ago', 'ultimate-store-kit')); ?>
200 176 </span>
201 177 <div class="bdt-summary">
202 178 <?php echo esc_html(wp_html_excerpt($item['content'], 120) . ' [...]'); ?>
203 179 </div>
@@ -222,8 +198,18 @@
222 198 ?>
223 199 </p>
224 200 <?php
225 201 return ob_get_clean();
202 + }
203 +
204 + /**
205 + * Keep SimplePie's socket timeout in line with our own limit.
206 + *
207 + * @param object $feed SimplePie instance.
208 + * @return void
209 + */
210 + public function set_feed_timeout($feed) {
211 + $feed->set_timeout(self::REQUEST_TIMEOUT);
226 212 }
227 213
228 214 /**
229 215 * Check if a feed item is "new" (published within the last 7 days).