PluginProbe ʕ •ᴥ•ʔ
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress / 4.8.1
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress v4.8.1
4.8.1 trunk 1.0 1.1 1.12.1 1.2.3 1.2.4 1.2.5 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5 1.5.1 1.5.2 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.5.1 1.6.6 1.6.6.1 1.6.6.2 1.6.6.3 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.9.0 1.9.1 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.8.1 1.9.9 1.9.9.1 1.9.9.2 1.9.9.3 2.0 2.0.1 2.1 2.1.1 2.1.2 2.1.3 2.10 2.11 2.11.1 2.12 2.12.1 2.12.2 2.12.3 2.12.4 2.13 2.14 2.14.1 2.15 2.15.1 2.16 2.16.1 2.17 2.17.1 2.18 2.18.1 2.18.2 2.18.3 2.19 2.19.1 2.19.2 2.19.3 2.2 2.2.1 2.3 2.3.1 2.3.10 2.3.2 2.3.3 2.3.4 2.3.6 2.3.7 2.3.8 2.3.9 2.4 2.4.1 2.4.1.1 2.4.1.2 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5 2.5.1 2.5.2 2.6 2.6.1 2.6.2 2.6.3 2.6.4 2.7 2.7.1 2.7.2 2.8 2.9 2.9.1 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.1 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.7.5 4.7.6 4.7.7
custom-facebook-feed / inc / CFF_Oembed.php
custom-facebook-feed / inc Last commit date
Admin 2 weeks ago Builder 2 weeks ago Helpers 2 weeks ago Integrations 2 weeks ago CFF_Autolink.php 2 weeks ago CFF_Blocks.php 2 weeks ago CFF_Cache.php 2 weeks ago CFF_Education.php 2 weeks ago CFF_Elementor_Base.php 2 weeks ago CFF_Elementor_Widget.php 2 weeks ago CFF_Error_Reporter.php 2 weeks ago CFF_FB_Settings.php 2 weeks ago CFF_Feed_Elementor_Control.php 2 weeks ago CFF_Feed_Locator.php 2 weeks ago CFF_Feed_Pro.php 2 weeks ago CFF_GDPR_Integrations.php 2 weeks ago CFF_Group_Posts.php 2 weeks ago CFF_HTTP_Request.php 2 weeks ago CFF_Oembed.php 2 weeks ago CFF_Parse.php 2 weeks ago CFF_Resizer.php 2 weeks ago CFF_Response.php 2 weeks ago CFF_Shortcode.php 2 weeks ago CFF_Shortcode_Display.php 2 weeks ago CFF_SiteHealth.php 2 weeks ago CFF_Utils.php 2 weeks ago CFF_View.php 2 weeks ago Custom_Facebook_Feed.php 2 weeks ago Email_Notification.php 2 weeks ago Platform_Data.php 2 weeks ago SB_Facebook_Data_Encryption.php 2 weeks ago SB_Facebook_Data_Manager.php 2 weeks ago index.php 2 weeks ago
CFF_Oembed.php
517 lines
1 <?php
2
3 /**
4 * Class CFF_Oembed
5 *
6 * Replaces the native WordPress functionality for Facebook oembed
7 * to allow authenticated oembeds
8 *
9 * @since 2.16/3.16
10 */
11
12 namespace CustomFacebookFeed;
13
14 if (! defined('ABSPATH')) {
15 die('-1');
16 }
17
18 class CFF_Oembed
19 {
20 /**
21 * CFF_Oembed constructor.
22 *
23 * If an account has been connected, hooks are added
24 * to change how Facebook links are handled for oembeds
25 *
26 * @since 2.16/3.16
27 */
28 public function __construct()
29 {
30 if (CFF_Oembed::can_do_oembed()) {
31 if (CFF_Oembed::can_check_for_old_oembeds()) {
32 add_action('init', array('CustomFacebookFeed\CFF_Oembed', 'clear_checks'));
33 add_action('admin_init', array($this, 'cffOembedNotice'));
34 }
35 add_filter('oembed_providers', array( 'CustomFacebookFeed\CFF_Oembed', 'oembed_providers' ), 10, 1);
36 add_filter('oembed_fetch_url', array( 'CustomFacebookFeed\CFF_Oembed', 'oembed_set_fetch_url' ), 10, 3);
37 add_filter('oembed_result', array( 'CustomFacebookFeed\CFF_Oembed', 'oembed_result' ), 10, 3);
38 }
39 if (CFF_Oembed::should_extend_ttl()) {
40 add_filter('oembed_ttl', array( 'CustomFacebookFeed\CFF_Oembed', 'oembed_ttl' ), 10, 4);
41 }
42 }
43
44 /**
45 * Check to make sure there is a saved access token to
46 * enable authenticated oembeds
47 *
48 * @return bool
49 *
50 * @since 2.16/3.16
51 */
52 public static function can_do_oembed()
53 {
54 $oembed_token_settings = get_option('cff_oembed_token', array());
55
56 if (isset($oembed_token_settings['disabled']) && $oembed_token_settings['disabled'] === true) {
57 return false;
58 }
59
60 $access_token = CFF_Oembed::last_access_token();
61 if (! $access_token) {
62 return false;
63 }
64
65 return true;
66 }
67
68 /**
69 * The "time to live" for Instagram oEmbeds is extended if the access token expires.
70 * Even if new oEmbeds will not use the Instagram Feed system due to an expired token
71 * the time to live should continue to be extended.
72 *
73 * @return bool
74 *
75 * @since 2.16/3.16
76 */
77 public static function should_extend_ttl()
78 {
79 $oembed_token_settings = get_option('cff_oembed_token', array());
80
81 if (isset($oembed_token_settings['disabled']) && $oembed_token_settings['disabled']) {
82 return false;
83 }
84
85 $will_expire = CFF_Oembed::oembed_access_token_will_expire();
86 if ($will_expire) {
87 return true;
88 }
89
90 return false;
91 }
92
93 /**
94 * Checking for old oembeds makes permanent changes to posts
95 * so we want the user to turn it off and on
96 *
97 * @return bool
98 *
99 * @since 2.16/3.16
100 */
101 public static function can_check_for_old_oembeds()
102 {
103 $cff_statuses = get_option('cff_statuses', array());
104 if (isset($cff_statuses['oembed_api_change_notice'])) {
105 return false;
106 }
107 return true;
108 }
109
110 /**
111 * Filters the WordPress list of oembed providers to
112 * change what url is used for remote requests for the
113 * oembed data
114 *
115 * @param array $providers
116 *
117 * @return mixed
118 *
119 * @since 2.16/3.16
120 */
121 public static function oembed_providers($providers)
122 {
123 $oembed_url = CFF_Oembed::oembed_url();
124 if ($oembed_url) {
125 $post_embed_providers = CFF_Oembed::post_providers();
126 foreach ($post_embed_providers as $post_provider) {
127 $providers[ $post_provider ] = array( $oembed_url . 'oembed_post', true );
128 }
129
130 $video_embed_providers = CFF_Oembed::video_providers();
131 foreach ($video_embed_providers as $video_provider) {
132 $providers[ $video_provider ] = array( $oembed_url . 'oembed_video', true );
133 }
134 }
135
136 return $providers;
137 }
138
139 /**
140 * Add the access token from a connected account to make an authenticated
141 * call to get oembed data from Facebook
142 *
143 * @param string $provider
144 * @param string $url
145 * @param array $args
146 *
147 * @return string
148 *
149 * @since 2.16/3.16
150 */
151 public static function oembed_set_fetch_url($provider, $url, $args)
152 {
153 $access_token = CFF_Oembed::last_access_token();
154 if (! $access_token) {
155 return $provider;
156 }
157
158 if (
159 strpos($provider, 'oembed_post') !== false
160 || strpos($provider, 'oembed_video') !== false
161 ) {
162 if (strpos($url, '?') !== false) {
163 $provider = self::get_provider_from_url_with_query_vars($provider, $url);
164 }
165 $provider = add_query_arg('access_token', $access_token, $provider);
166 }
167
168 return $provider;
169 }
170
171 /**
172 * URLs with query variables are handled specially
173 *
174 * @param $provider
175 * @param $url
176 *
177 * @return array|mixed|string|string[]
178 */
179 public static function get_provider_from_url_with_query_vars($provider, $url)
180 {
181 $exploded = explode('?', $url);
182 if (! empty($exploded[1])) {
183 if (strpos($url, '?v=') !== false) {
184 $exploded = explode('&', $url);
185 $provider = str_replace(urlencode('&' . $exploded[1]), '', $provider);
186 }
187 }
188
189 return $provider;
190 }
191
192 /**
193 * New oembeds are wrapped in a div for easy detection of older oembeds
194 * that will need to be updated
195 *
196 * @param string $html
197 * @param string $url
198 * @param array $args
199 *
200 * @return string
201 *
202 * @since 2.16/3.16
203 */
204 public static function oembed_result($html, $url, $args)
205 {
206 $post_embed_providers = CFF_Oembed::post_providers();
207 foreach ($post_embed_providers as $post_provider) {
208 if (preg_match($post_provider, $url) === 1) {
209 if (strpos($html, 'class="fb-post"') !== false) {
210 $html = '<div class="cff-embed-wrap cff-post-embed-wrap">' . str_replace('class="fb-post"', 'class="fb-post cff-embed cff-post-embed"', $html) . '</div>';
211 }
212 }
213 }
214
215 $video_embed_providers = CFF_Oembed::video_providers();
216 foreach ($video_embed_providers as $video_provider) {
217 if (preg_match($video_provider, $url) === 1) {
218 if (strpos($html, 'class="fb-video"') !== false) {
219 $html = '<div class="cff-embed-wrap cff-video-embed-wrap">' . str_replace('class="fb-video"', 'class="fb-video cff-embed cff-video-embed"', $html) . '</div>';
220 }
221 }
222 }
223
224 return $html;
225 }
226
227 /**
228 * Extend the "time to live" for oEmbeds created with access tokens that expire
229 *
230 * @param $ttl
231 * @param $url
232 * @param $attr
233 * @param $post_ID
234 *
235 * @return float|int
236 *
237 * @since 2.16/3.16
238 */
239 public static function oembed_ttl($ttl, $url, $attr, $post_ID)
240 {
241 $providers = CFF_Oembed::post_providers();
242 foreach ($providers as $provider) {
243 if (preg_match($provider, $url) === 1) {
244 $ttl = 30 * YEAR_IN_SECONDS;
245 }
246 }
247
248 $providers = CFF_Oembed::video_providers();
249 foreach ($providers as $provider) {
250 if (preg_match($provider, $url) === 1) {
251 $ttl = 30 * YEAR_IN_SECONDS;
252 }
253 }
254
255 return $ttl;
256 }
257
258 /**
259 * Only one api URL for FB
260 *
261 * @return bool|string
262 *
263 * @since 2.16/3.16
264 */
265 public static function oembed_url()
266 {
267 return 'https://graph.facebook.com/';
268 }
269
270 /**
271 * Any access token will work for oembeds so the access token
272 * saved in settings is used
273 *
274 * @return bool|string
275 *
276 * @since 2.16/3.16
277 */
278 public static function last_access_token()
279 {
280 $oembed_token_settings = get_option('cff_oembed_token', array());
281 $will_expire = CFF_Oembed::oembed_access_token_will_expire();
282 $encryption = new \CustomFacebookFeed\SB_Facebook_Data_Encryption();
283
284 if (
285 ! empty($oembed_token_settings['access_token'])
286 && (! $will_expire || $will_expire > time())
287 ) {
288 $oembed_token_settings['access_token'] = $encryption->maybe_decrypt($oembed_token_settings['access_token']);
289 return $oembed_token_settings['access_token'];
290 } else {
291 $settings_access_token = trim(get_option('cff_access_token'));
292 $settings_access_token = $encryption->maybe_decrypt($settings_access_token);
293 if (! empty($settings_access_token)) {
294 return $settings_access_token;
295 }
296
297 if (class_exists('SB_Instagram_Oembed')) {
298 $sbi_oembed_token_settings = get_option('sbi_oembed_token', array());
299 if (! empty($sbi_oembed_token_settings['access_token'])) {
300 $sbi_oembed_token_settings['access_token'] = $encryption->maybe_decrypt($sbi_oembed_token_settings['access_token']);
301 return $sbi_oembed_token_settings['access_token'];
302 }
303 }
304 }
305
306 return false;
307 }
308
309 /**
310 * Access tokens created from FB accounts not connected to an
311 * FB page expire after 60 days.
312 *
313 * @return bool|int
314 */
315 public static function oembed_access_token_will_expire()
316 {
317 $oembed_token_settings = get_option('cff_oembed_token', array());
318 $will_expire = isset($oembed_token_settings['expiration_date']) && (int)$oembed_token_settings['expiration_date'] > 0 ? (int)$oembed_token_settings['expiration_date'] : false;
319
320 return $will_expire;
321 }
322
323
324 /**
325 * Loop through post meta data and if it's an oembed and has content
326 * that looks like a Facebook oembed, delete it
327 *
328 * @param $post_ID
329 *
330 * @return int number of old oembed caches found
331 *
332 * @since 2.16/3.16
333 */
334 public static function delete_facebook_oembed_caches($post_ID)
335 {
336 $post_metas = get_post_meta($post_ID);
337 if (empty($post_metas)) {
338 return 0;
339 }
340
341 $total_found = 0;
342 foreach ($post_metas as $post_meta_key => $post_meta_value) {
343 if ('_oembed_' === substr($post_meta_key, 0, 8)) {
344 if (
345 strpos($post_meta_value[0], 'class="fb-post"') !== false
346 && strpos($post_meta_value[0], 'cff-embed-wrap') === false
347 ) {
348 $total_found++;
349 delete_post_meta($post_ID, $post_meta_key);
350 if ('_oembed_time_' !== substr($post_meta_key, 0, 13)) {
351 delete_post_meta($post_ID, str_replace('_oembed_', '_oembed_time_', $post_meta_key));
352 }
353 } elseif (
354 strpos($post_meta_value[0], 'class="fb-video"') !== false
355 && strpos($post_meta_value[0], 'cff-embed-wrap') === false
356 ) {
357 $total_found++;
358 delete_post_meta($post_ID, $post_meta_key);
359 if ('_oembed_time_' !== substr($post_meta_key, 0, 13)) {
360 delete_post_meta($post_ID, str_replace('_oembed_', '_oembed_time_', $post_meta_key));
361 }
362 }
363 }
364 }
365
366 return $total_found;
367 }
368
369 /**
370 * Current list of regex to identify FB URLs that could become oembeds using
371 * the 'oembed_post' endpoint.
372 *
373 * @return array
374 *
375 * @since 2.16/3.16
376 */
377 public static function post_providers()
378 {
379 $post_embed_providers = array(
380 '#https?://www\.facebook\.com/.*/posts/.*#i',
381 '#https?://www\.facebook\.com/.*/activity/.*#i',
382 '#https?://www\.facebook\.com/.*/photos/.*#i',
383 '#https?://www\.facebook\.com/photo(s/|\.php).*#i',
384 '#https?://www\.facebook\.com/permalink\.php.*#i',
385 '#https?://www\.facebook\.com/media/.*#i',
386 '#https?://www\.facebook\.com/questions/.*#i',
387 '#https?://www\.facebook\.com/notes/.*#i',
388 );
389
390 return $post_embed_providers;
391 }
392
393 /**
394 * Current list of regex to identify FB URLs that could become oembeds using
395 * the 'oembed_video' endpoint.
396 *
397 * @return array
398 *
399 * @since 2.16/3.16
400 */
401 public static function video_providers()
402 {
403 $video_embed_providers = array(
404 '#https?://www\.facebook\.com/.*/videos/.*#i',
405 '#https?://www\.facebook\.com/video\.php.*#i',
406 '#https?://www\.facebook\.com/watch/.*#i',
407 '#https?://fb\.watch/.*#i'
408 );
409
410 return $video_embed_providers;
411 }
412
413 /**
414 * Used for clearing the oembed update check flag for all posts
415 *
416 * @since 2.16/3.16
417 */
418 public static function clear_checks()
419 {
420 global $wpdb;
421 $table_name = esc_sql($wpdb->prefix . "postmeta");
422 $result = $wpdb->query("
423 DELETE
424 FROM $table_name
425 WHERE meta_key = '_cff_oembed_done_checking';");
426 }
427
428 /**
429 * Display oembed notice in the plugin's pages
430 *
431 * @since 6.3.7
432 */
433 public function cffOembedNotice()
434 {
435 $allowed_screens = array(
436 'cff-feed-builder',
437 'cff-settings',
438 'cff-oembeds-manager',
439 'cff-extensions-manager',
440 'cff-about-us',
441 'cff-support',
442 );
443 $current_screen = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
444 $is_allowed = in_array($current_screen, $allowed_screens);
445
446 // We will display the notice only on those allowed screens.
447 if (!$current_screen || ! $is_allowed) {
448 return;
449 }
450
451 // Only display notice to admins.
452 $cap = current_user_can('manage_custom_facebook_feed_options') ? 'manage_custom_facebook_feed_options' : 'manage_options';
453 $cap = apply_filters('cff_settings_pages_capability', $cap);
454 if (!current_user_can($cap)) {
455 return;
456 }
457
458 $cff_statuses = get_option('cff_statuses', array());
459 if (isset($cff_statuses['oembed_api_change_notice'])) {
460 return;
461 }
462
463 global $cff_notices;
464 $title = __('Account reconnection needed for Facebook and Instagram oEmbeds', 'custom-facebook-feed');
465 $message = '<p>' . __('Starting May of 2024, Facebook is making some changes to their API that will affect your oEmbeds. Make sure to connect to our oEmbed specific Smash Balloon Tools app to avoid disruption.', 'custom-facebook-feed') . '</p>';
466
467 $error_args = array(
468 'class' => 'cff-admin-notices',
469 'title' => array(
470 'text' => $title,
471 'class' => 'sb-notice-title',
472 'tag' => 'h4',
473 ),
474 'message' => $message,
475 'buttons' => array(
476 array(
477 'text' => __('Reconnect', 'custom-facebook-feed'),
478 'class' => 'sb-btn sb-reconnect-oembed',
479 'tag' => 'button',
480 ),
481 ),
482 'buttons_wrap_start' => '<div class="buttons">',
483 'buttons_wrap_end' => '</div>',
484 'priority' => 1,
485 'page' => array(
486 'cff-feed-builder',
487 'cff-settings',
488 'cff-oembeds-manager',
489 'cff-extensions-manager',
490 'cff-about-us',
491 'cff-support',
492 ),
493 'icon' => array(
494 'src' => CFF_PLUGIN_URL . 'admin/assets/img/cff-exclamation.svg',
495 'wrap' => '<span class="sb-notice-icon sb-error-icon"><img {src}></span>',
496 ),
497 'styles' => array(
498 'display' => 'flex',
499 'justify-content' => 'space-between',
500 'gap' => '2rem',
501 ),
502 'wrap_schema' => '<div {id} {class}>{icon}<div class="cff-notice-wrap" {styles}><div class="cff-notice-body">{title}{message}</div>{buttons}</div></div>',
503 );
504
505 $cff_notices->add_notice('oembed_api_change', 'information', $error_args);
506 $cff_statuses['oembed_api_change_notice'] = true;
507 update_option('cff_statuses', $cff_statuses);
508 }
509 }
510
511 /*
512 function cffOembedInit() {
513 return new CFF_Oembed();
514 }
515 cffOembedInit();
516 */
517