Admin
4 months ago
Builder
4 months ago
Helpers
4 months ago
Integrations
4 months ago
CFF_Autolink.php
4 months ago
CFF_Blocks.php
4 months ago
CFF_Cache.php
4 months ago
CFF_Education.php
4 months ago
CFF_Elementor_Base.php
4 months ago
CFF_Elementor_Widget.php
4 months ago
CFF_Error_Reporter.php
4 months ago
CFF_FB_Settings.php
4 months ago
CFF_Feed_Elementor_Control.php
4 months ago
CFF_Feed_Locator.php
4 months ago
CFF_Feed_Pro.php
4 months ago
CFF_GDPR_Integrations.php
4 months ago
CFF_Group_Posts.php
4 months ago
CFF_HTTP_Request.php
4 months ago
CFF_Oembed.php
4 months ago
CFF_Parse.php
4 months ago
CFF_Resizer.php
4 months ago
CFF_Response.php
4 months ago
CFF_Shortcode.php
4 months ago
CFF_Shortcode_Display.php
4 months ago
CFF_SiteHealth.php
4 months ago
CFF_Utils.php
4 months ago
CFF_View.php
4 months ago
Custom_Facebook_Feed.php
4 months ago
Email_Notification.php
4 months ago
Platform_Data.php
4 months ago
SB_Facebook_Data_Encryption.php
4 months ago
SB_Facebook_Data_Manager.php
4 months ago
index.php
4 months ago
CFF_Utils.php
979 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Class CFF_Utils |
| 5 | * |
| 6 | * Contains miscellaneous CFF functions |
| 7 | * |
| 8 | * @since 2.19 |
| 9 | */ |
| 10 | |
| 11 | namespace CustomFacebookFeed; |
| 12 | |
| 13 | use CustomFacebookFeed\SB_Facebook_Data_Encryption; |
| 14 | |
| 15 | if (!defined('ABSPATH')) { |
| 16 | exit; // Exit if accessed directly |
| 17 | } |
| 18 | |
| 19 | |
| 20 | |
| 21 | class CFF_Utils |
| 22 | { |
| 23 | /** |
| 24 | * Get JSON object of feed data |
| 25 | * |
| 26 | * @access public |
| 27 | * @static |
| 28 | * @since 2.19 |
| 29 | */ |
| 30 | public static function cff_fetchUrl($url, $check_admin = true) |
| 31 | { |
| 32 | $response = wp_safe_remote_get($url); |
| 33 | do_action('cff_api_connect_response', $response, $url); |
| 34 | |
| 35 | if (! CFF_Utils::cff_is_wp_error($response)) { |
| 36 | $feedData = wp_remote_retrieve_body($response); |
| 37 | |
| 38 | if (! CFF_Utils::cff_is_fb_error($feedData)) { |
| 39 | \cff_main()->cff_error_reporter->remove_error('connection'); |
| 40 | |
| 41 | $feedData = apply_filters('cff_filter_api_data', $feedData); |
| 42 | |
| 43 | return $feedData; |
| 44 | } else { |
| 45 | if (strpos($url, '&limit=') !== false) { |
| 46 | CFF_Utils::cff_log_fb_error($feedData, $url, $check_admin); |
| 47 | } |
| 48 | |
| 49 | |
| 50 | $error = json_decode($feedData, true); |
| 51 | $reporter = CFF_Utils::cff_is_pro_version() ? \cff_main_pro()->cff_error_reporter : \cff_main()->cff_error_reporter; |
| 52 | |
| 53 | if ($reporter->is_critical_error($error)) { |
| 54 | $parsed_url = parse_url($url); |
| 55 | if (! empty($parsed_url['query'])) { |
| 56 | parse_str($parsed_url['query'], $parsed); |
| 57 | |
| 58 | if (isset($parsed['access_token'])) { |
| 59 | $args = [ |
| 60 | 'access_token' => $parsed['access_token'] |
| 61 | ]; |
| 62 | $source_data = \CustomFacebookFeed\Builder\CFF_Db::source_query($args); |
| 63 | |
| 64 | if ($source_data) { |
| 65 | foreach ($source_data as $source) { |
| 66 | \CustomFacebookFeed\Builder\CFF_Source::add_error($source['account_id'], $feedData); |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | return $feedData; |
| 74 | } |
| 75 | } else { |
| 76 | if (strpos($url, '&limit=') !== false) { |
| 77 | CFF_Utils::cff_log_wp_error($response, $url); |
| 78 | } |
| 79 | |
| 80 | return '{}'; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | |
| 85 | /** |
| 86 | * |
| 87 | * @access public |
| 88 | * @static |
| 89 | * @since 2.19 |
| 90 | */ |
| 91 | public static function cff_desc_tags($description) |
| 92 | { |
| 93 | preg_match_all("/@\[(.*?)\]/", $description, $cff_tag_matches); |
| 94 | $replace_strings_arr = array(); |
| 95 | foreach ($cff_tag_matches[1] as $cff_tag_match) { |
| 96 | $cff_tag_parts = explode(':', $cff_tag_match); |
| 97 | $replace_strings_arr[] = '<a href="https://facebook.com/' . $cff_tag_parts[0] . '">' . $cff_tag_parts[2] . '</a>'; |
| 98 | } |
| 99 | $cff_tag_iterator = 0; |
| 100 | $cff_description_tagged = ''; |
| 101 | $cff_text_split = preg_split("/@\[(.*?)\]/", $description); |
| 102 | foreach ($cff_text_split as $cff_desc_split) { |
| 103 | if ($cff_tag_iterator < count($replace_strings_arr)) { |
| 104 | $cff_description_tagged .= $cff_desc_split . $replace_strings_arr[ $cff_tag_iterator ]; |
| 105 | } else { |
| 106 | $cff_description_tagged .= $cff_desc_split; |
| 107 | } |
| 108 | $cff_tag_iterator++; |
| 109 | } |
| 110 | |
| 111 | return $cff_description_tagged; |
| 112 | } |
| 113 | |
| 114 | |
| 115 | /** |
| 116 | * Sort message tags by offset value |
| 117 | * |
| 118 | * @access public |
| 119 | * @static |
| 120 | * @since 2.19 |
| 121 | */ |
| 122 | public static function cffSortTags($a, $b) |
| 123 | { |
| 124 | return $a['offset'] - $b['offset']; |
| 125 | } |
| 126 | |
| 127 | |
| 128 | /** |
| 129 | * |
| 130 | * @access public |
| 131 | * @static |
| 132 | * @since 2.19 |
| 133 | */ |
| 134 | public static function cff_is_wp_error($response) |
| 135 | { |
| 136 | return is_wp_error($response); |
| 137 | } |
| 138 | |
| 139 | |
| 140 | /** |
| 141 | * |
| 142 | * @access public |
| 143 | * @static |
| 144 | * @since 2.19 |
| 145 | */ |
| 146 | public static function cff_log_wp_error($response, $url) |
| 147 | { |
| 148 | if (is_wp_error($response)) { |
| 149 | delete_option('cff_dismiss_critical_notice'); |
| 150 | |
| 151 | $admin_message_error = ''; |
| 152 | if (isset($response) && isset($response->errors)) { |
| 153 | foreach ($response->errors as $key => $item) { |
| 154 | $admin_message_error .= ' ' . $key . ' - ' . $item[0]; |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | $admin_message = __('Error connecting to the Facebook API:', 'custom-facebook-feed') . ' ' . $admin_message_error; |
| 159 | $public_message = __('Unable to make remote requests to the Facebook API. Log in as an admin to view more details.', 'custom-facebook-feed'); |
| 160 | $frontend_directions = '<p class="cff-error-directions"><a href="https://smashballoon.com/custom-facebook-feed/docs/errors/" target="_blank" rel="noopener">' . __('Directions on How to Resolve This Issue', 'custom-facebook-feed') . '</a></p>'; |
| 161 | $backend_directions = '<a class="button button-primary" href="https://smashballoon.com/custom-facebook-feed/docs/errors/" target="_blank" rel="noopener">' . __('Directions on How to Resolve This Issue', 'custom-facebook-feed') . '</a>'; |
| 162 | $error = array( |
| 163 | 'accesstoken' => 'none', |
| 164 | 'public_message' => $public_message, |
| 165 | 'admin_message' => $admin_message, |
| 166 | 'frontend_directions' => $frontend_directions, |
| 167 | 'backend_directions' => $backend_directions, |
| 168 | 'post_id' => get_the_ID(), |
| 169 | 'errorno' => 'wp_remote_get' |
| 170 | ); |
| 171 | \cff_main()->cff_error_reporter->add_error('wp_remote_get', $error); |
| 172 | } else { |
| 173 | \cff_main()->cff_error_reporter->remove_error('connection'); |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | |
| 178 | /** |
| 179 | * |
| 180 | * @access public |
| 181 | * @static |
| 182 | * @since 2.19 |
| 183 | */ |
| 184 | public static function cff_is_fb_error($response) |
| 185 | { |
| 186 | return ($response !== null && strpos($response, '{"error":') === 0); |
| 187 | } |
| 188 | |
| 189 | |
| 190 | /** |
| 191 | * |
| 192 | * @access public |
| 193 | * @static |
| 194 | * @since 2.19 |
| 195 | */ |
| 196 | public static function cff_log_fb_error($response, $url, $check_admin = true) |
| 197 | { |
| 198 | if (is_admin() && $check_admin == true) { |
| 199 | return; |
| 200 | } |
| 201 | delete_option('cff_dismiss_critical_notice'); |
| 202 | |
| 203 | $access_token_refresh_errors = array( 10, 4, 200 ); |
| 204 | |
| 205 | $response = json_decode($response, true); |
| 206 | $api_error_code = $response['error']['code']; |
| 207 | |
| 208 | // Page Public Content Access error |
| 209 | $ppca_error = false; |
| 210 | if (strpos($response['error']['message'], 'Public Content Access') !== false) { |
| 211 | $ppca_error = true; |
| 212 | } |
| 213 | |
| 214 | if (in_array((int)$api_error_code, $access_token_refresh_errors, true) && !$ppca_error) { |
| 215 | $pieces = explode('access_token=', $url); |
| 216 | $accesstoken_parts = isset($pieces[1]) ? explode('&', $pieces[1]) : 'none'; |
| 217 | $accesstoken = $accesstoken_parts[0]; |
| 218 | |
| 219 | $api_error_number_message = sprintf(__('API Error %s:', 'custom-facebook-feed'), $api_error_code); |
| 220 | $link = admin_url('admin.php?page=cff-settings'); |
| 221 | $error = array( |
| 222 | 'accesstoken' => $accesstoken, |
| 223 | 'post_id' => get_the_ID(), |
| 224 | 'errorno' => $api_error_code |
| 225 | ); |
| 226 | |
| 227 | \cff_main()->cff_error_reporter->add_error('accesstoken', $error, $accesstoken); |
| 228 | } else { |
| 229 | \cff_main()->cff_error_reporter->add_error('api', $response); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | |
| 234 | /** |
| 235 | * Make links into span instead when the post text is made clickable |
| 236 | * |
| 237 | * @access public |
| 238 | * @static |
| 239 | * @since 2.19 |
| 240 | */ |
| 241 | public static function cff_wrap_span($text) |
| 242 | { |
| 243 | $pattern = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#'; |
| 244 | return preg_replace_callback($pattern, array('CustomFacebookFeed\CFF_Utils','cff_wrap_span_callback'), $text); |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * @return Json Encode |
| 249 | * |
| 250 | * @since 2.1.1 |
| 251 | */ |
| 252 | public static function cff_json_encode($thing) |
| 253 | { |
| 254 | return wp_json_encode($thing); |
| 255 | } |
| 256 | |
| 257 | /** |
| 258 | * |
| 259 | * @access public |
| 260 | * @static |
| 261 | * @since 2.19 |
| 262 | */ |
| 263 | public static function cff_wrap_span_callback($matches) |
| 264 | { |
| 265 | $max_url_length = 100; |
| 266 | $max_depth_if_over_length = 2; |
| 267 | $ellipsis = '…'; |
| 268 | $target = 'target="_blank"'; |
| 269 | $url_full = $matches[0]; |
| 270 | $url_short = ''; |
| 271 | if (strlen($url_full) > $max_url_length) { |
| 272 | $parts = parse_url($url_full); |
| 273 | $url_short = $parts['scheme'] . '://' . preg_replace('/^www\./', '', $parts['host']) . '/'; |
| 274 | $path_components = explode('/', trim($parts['path'], '/')); |
| 275 | foreach ($path_components as $dir) { |
| 276 | $url_string_components[] = $dir . '/'; |
| 277 | } |
| 278 | if (!empty($parts['query'])) { |
| 279 | $url_string_components[] = '?' . $parts['query']; |
| 280 | } |
| 281 | if (!empty($parts['fragment'])) { |
| 282 | $url_string_components[] = '#' . $parts['fragment']; |
| 283 | } |
| 284 | for ($k = 0; $k < count($url_string_components); $k++) { |
| 285 | $curr_component = $url_string_components[$k]; |
| 286 | if ($k >= $max_depth_if_over_length || strlen($url_short) + strlen($curr_component) > $max_url_length) { |
| 287 | if ($k == 0 && strlen($url_short) < $max_url_length) { |
| 288 | // Always show a portion of first directory |
| 289 | $url_short .= substr($curr_component, 0, $max_url_length - strlen($url_short)); |
| 290 | } |
| 291 | $url_short .= $ellipsis; |
| 292 | break; |
| 293 | } |
| 294 | $url_short .= $curr_component; |
| 295 | } |
| 296 | } else { |
| 297 | $url_short = $url_full; |
| 298 | } |
| 299 | return "<span class='cff-break-word'>$url_short</span>"; |
| 300 | } |
| 301 | |
| 302 | |
| 303 | /** |
| 304 | * Use the timezone to offset the date as all post dates are in UTC +0000 |
| 305 | * |
| 306 | * @access public |
| 307 | * @static |
| 308 | * @since 2.19 |
| 309 | */ |
| 310 | public static function cff_set_timezone($original, $cff_timezone) |
| 311 | { |
| 312 | $cff_date_time = new \DateTime(date('m/d g:i a'), new \DateTimeZone('UTC')); |
| 313 | $cff_date_time->setTimeZone(new \DateTimeZone($cff_timezone)); |
| 314 | $cff_date_time_offset = $cff_date_time->getOffset(); |
| 315 | |
| 316 | $original = $original + $cff_date_time_offset; |
| 317 | |
| 318 | return $original; |
| 319 | } |
| 320 | |
| 321 | |
| 322 | /** |
| 323 | * Time stamp functison - used for posts |
| 324 | * |
| 325 | * @access public |
| 326 | * @static |
| 327 | * @since 2.19 |
| 328 | */ |
| 329 | public static function cff_getdate($original, $date_format, $custom_date, $cff_date_translate_strings, $cff_timezone) |
| 330 | { |
| 331 | // Offset the date by the timezone |
| 332 | $new_time = CFF_Utils::cff_set_timezone($original, $cff_timezone); |
| 333 | switch ($date_format) { |
| 334 | case '2': |
| 335 | $print = date_i18n('F jS, g:i a', $new_time); |
| 336 | break; |
| 337 | case '3': |
| 338 | $print = date_i18n('F jS', $new_time); |
| 339 | break; |
| 340 | case '4': |
| 341 | $print = date_i18n('D F jS', $new_time); |
| 342 | break; |
| 343 | case '5': |
| 344 | $print = date_i18n('l F jS', $new_time); |
| 345 | break; |
| 346 | case '6': |
| 347 | $print = date_i18n('D M jS, Y', $new_time); |
| 348 | break; |
| 349 | case '7': |
| 350 | $print = date_i18n('l F jS, Y', $new_time); |
| 351 | break; |
| 352 | case '8': |
| 353 | $print = date_i18n('l F jS, Y - g:i a', $new_time); |
| 354 | break; |
| 355 | case '9': |
| 356 | $print = date_i18n("l M jS, 'y", $new_time); |
| 357 | break; |
| 358 | case '10': |
| 359 | $print = date_i18n('m.d.y', $new_time); |
| 360 | break; |
| 361 | case '11': |
| 362 | $print = date_i18n('m/d/y', $new_time); |
| 363 | break; |
| 364 | case '12': |
| 365 | $print = date_i18n('d.m.y', $new_time); |
| 366 | break; |
| 367 | case '13': |
| 368 | $print = date_i18n('d/m/y', $new_time); |
| 369 | break; |
| 370 | case '14': |
| 371 | $print = date_i18n('d-m-Y, G:i', $new_time); |
| 372 | break; |
| 373 | case '15': |
| 374 | $print = date_i18n('jS F Y, G:i', $new_time); |
| 375 | break; |
| 376 | case '16': |
| 377 | $print = date_i18n('d M Y, G:i', $new_time); |
| 378 | break; |
| 379 | case '17': |
| 380 | $print = date_i18n('l jS F Y, G:i', $new_time); |
| 381 | break; |
| 382 | case '18': |
| 383 | $print = date_i18n('m.d.y - G:i', $new_time); |
| 384 | break; |
| 385 | case '19': |
| 386 | $print = date_i18n('d.m.y - G:i', $new_time); |
| 387 | break; |
| 388 | default: |
| 389 | $cff_second = $cff_date_translate_strings['cff_translate_second']; |
| 390 | $cff_seconds = $cff_date_translate_strings['cff_translate_seconds']; |
| 391 | $cff_minute = $cff_date_translate_strings['cff_translate_minute']; |
| 392 | $cff_minutes = $cff_date_translate_strings['cff_translate_minutes']; |
| 393 | $cff_hour = $cff_date_translate_strings['cff_translate_hour']; |
| 394 | $cff_hours = $cff_date_translate_strings['cff_translate_hours']; |
| 395 | $cff_day = $cff_date_translate_strings['cff_translate_day']; |
| 396 | $cff_days = $cff_date_translate_strings['cff_translate_days']; |
| 397 | $cff_week = $cff_date_translate_strings['cff_translate_week']; |
| 398 | $cff_weeks = $cff_date_translate_strings['cff_translate_weeks']; |
| 399 | $cff_month = $cff_date_translate_strings['cff_translate_month']; |
| 400 | $cff_months = $cff_date_translate_strings['cff_translate_months']; |
| 401 | $cff_year = $cff_date_translate_strings['cff_translate_years']; |
| 402 | $cff_years = $cff_date_translate_strings['cff_translate_years']; |
| 403 | $cff_ago = $cff_date_translate_strings['cff_translate_ago']; |
| 404 | |
| 405 | $periods = array($cff_second, $cff_minute, $cff_hour, $cff_day, $cff_week, $cff_month, $cff_year, "decade"); |
| 406 | $periods_plural = array($cff_seconds, $cff_minutes, $cff_hours, $cff_days, $cff_weeks, $cff_months, $cff_years, "decade"); |
| 407 | |
| 408 | $lengths = array("60","60","24","7","4.35","12","10"); |
| 409 | $now = time(); |
| 410 | |
| 411 | // is it future date or past date |
| 412 | if ($now > $original) { |
| 413 | $difference = $now - $original; |
| 414 | $tense = $cff_ago; |
| 415 | } else { |
| 416 | $difference = $original - $now; |
| 417 | $tense = $cff_ago; |
| 418 | } |
| 419 | for ($j = 0; $difference >= $lengths[$j] && $j < count($lengths) - 1; $j++) { |
| 420 | $difference /= $lengths[$j]; |
| 421 | } |
| 422 | |
| 423 | $difference = round($difference); |
| 424 | |
| 425 | if ($difference != 1) { |
| 426 | $periods[$j] = $periods_plural[$j]; |
| 427 | } |
| 428 | $print = "$difference $periods[$j] {$tense}"; |
| 429 | |
| 430 | break; |
| 431 | } |
| 432 | if (!empty($custom_date)) { |
| 433 | $print = date_i18n($custom_date, $new_time); |
| 434 | } |
| 435 | |
| 436 | return $print; |
| 437 | } |
| 438 | |
| 439 | |
| 440 | /** |
| 441 | * |
| 442 | * @access public |
| 443 | * @static |
| 444 | * @since 2.19 |
| 445 | */ |
| 446 | public static function cff_eventdate($original, $date_format, $custom_date) |
| 447 | { |
| 448 | switch ($date_format) { |
| 449 | case '2': |
| 450 | $print = date_i18n('<k>F jS, </k>g:ia', $original); |
| 451 | break; |
| 452 | case '3': |
| 453 | $print = date_i18n('g:ia<k> - F jS</k>', $original); |
| 454 | break; |
| 455 | case '4': |
| 456 | $print = date_i18n('g:ia<k>, F jS</k>', $original); |
| 457 | break; |
| 458 | case '5': |
| 459 | $print = date_i18n('<k>l F jS - </k> g:ia', $original); |
| 460 | break; |
| 461 | case '6': |
| 462 | $print = date_i18n('<k>D M jS, Y, </k>g:iA', $original); |
| 463 | break; |
| 464 | case '7': |
| 465 | $print = date_i18n('<k>l F jS, Y, </k>g:iA', $original); |
| 466 | break; |
| 467 | case '8': |
| 468 | $print = date_i18n('<k>l F jS, Y - </k>g:ia', $original); |
| 469 | break; |
| 470 | case '9': |
| 471 | $print = date_i18n("<k>l M jS, 'y</k>", $original); |
| 472 | break; |
| 473 | case '10': |
| 474 | $print = date_i18n('<k>m.d.y - </k>g:iA', $original); |
| 475 | break; |
| 476 | case '11': |
| 477 | $print = date_i18n('<k>m/d/y, </k>g:ia', $original); |
| 478 | break; |
| 479 | case '12': |
| 480 | $print = date_i18n('<k>d.m.y - </k>g:iA', $original); |
| 481 | break; |
| 482 | case '13': |
| 483 | $print = date_i18n('<k>d/m/y, </k>g:ia', $original); |
| 484 | break; |
| 485 | case '14': |
| 486 | $print = date_i18n('<k>M j, </k>g:ia', $original); |
| 487 | break; |
| 488 | case '15': |
| 489 | $print = date_i18n('<k>M j, </k>G:i', $original); |
| 490 | break; |
| 491 | case '16': |
| 492 | $print = date_i18n('<k>d-m-Y, </k>G:i', $original); |
| 493 | break; |
| 494 | case '17': |
| 495 | $print = date_i18n('<k>jS F Y, </k>G:i', $original); |
| 496 | break; |
| 497 | case '18': |
| 498 | $print = date_i18n('<k>d M Y, </k>G:i', $original); |
| 499 | break; |
| 500 | case '19': |
| 501 | $print = date_i18n('<k>l jS F Y, </k>G:i', $original); |
| 502 | break; |
| 503 | case '20': |
| 504 | $print = date_i18n('<k>m.d.y - </k>G:i', $original); |
| 505 | break; |
| 506 | case '21': |
| 507 | $print = date_i18n('<k>d.m.y - </k>G:i', $original); |
| 508 | break; |
| 509 | default: |
| 510 | $print = date_i18n('<k>F j, Y, </k>g:ia', $original); |
| 511 | break; |
| 512 | } |
| 513 | if (!empty($custom_date)) { |
| 514 | $print = date_i18n($custom_date, $original); |
| 515 | } |
| 516 | return $print; |
| 517 | } |
| 518 | |
| 519 | |
| 520 | /** |
| 521 | * Use custom stripos function if it's not available (only available in PHP 5+) |
| 522 | * |
| 523 | * @access public |
| 524 | * @static |
| 525 | * @since 2.19 |
| 526 | */ |
| 527 | public static function stripos($haystack, $needle) |
| 528 | { |
| 529 | if (empty(stristr($haystack, $needle))) { |
| 530 | $haystack = is_array($haystack) ? implode(" ", $haystack) : $haystack; |
| 531 | } |
| 532 | if (empty(stristr($haystack, $needle))) { |
| 533 | return false; |
| 534 | } |
| 535 | return strpos($haystack, stristr($haystack, $needle)); |
| 536 | } |
| 537 | |
| 538 | |
| 539 | /** |
| 540 | * |
| 541 | * @access public |
| 542 | * @static |
| 543 | * @since 2.19 |
| 544 | */ |
| 545 | public static function cff_stripos_arr($haystack, $needle) |
| 546 | { |
| 547 | if (!is_array($needle)) { |
| 548 | $needle = array($needle); |
| 549 | } |
| 550 | foreach ($needle as $what) { |
| 551 | if (($pos = CFF_Utils::stripos($haystack, ltrim($what))) !== false) { |
| 552 | return $pos; |
| 553 | } |
| 554 | } |
| 555 | return false; |
| 556 | } |
| 557 | |
| 558 | |
| 559 | /** |
| 560 | * |
| 561 | * @access public |
| 562 | * @static |
| 563 | * @since 2.19 |
| 564 | */ |
| 565 | public static function cff_mb_substr_replace($string, $replacement, $start, $length = null) |
| 566 | { |
| 567 | if (is_array($string)) { |
| 568 | $num = count($string); |
| 569 | // $replacement |
| 570 | $replacement = is_array($replacement) ? array_slice($replacement, 0, $num) : array_pad(array($replacement), $num, $replacement); |
| 571 | // $start |
| 572 | if (is_array($start)) { |
| 573 | $start = array_slice($start, 0, $num); |
| 574 | foreach ($start as $key => $value) { |
| 575 | $start[$key] = is_int($value) ? $value : 0; |
| 576 | } |
| 577 | } else { |
| 578 | $start = array_pad(array($start), $num, $start); |
| 579 | } |
| 580 | // $length |
| 581 | if (!isset($length)) { |
| 582 | $length = array_fill(0, $num, 0); |
| 583 | } elseif (is_array($length)) { |
| 584 | $length = array_slice($length, 0, $num); |
| 585 | foreach ($length as $key => $value) { |
| 586 | $length[$key] = isset($value) ? (is_int($value) ? $value : $num) : 0; |
| 587 | } |
| 588 | } else { |
| 589 | $length = array_pad(array($length), $num, $length); |
| 590 | } |
| 591 | // Recursive call |
| 592 | return array_map(__FUNCTION__, $string, $replacement, $start, $length); |
| 593 | } |
| 594 | preg_match_all('/./us', (string)$string, $smatches); |
| 595 | preg_match_all('/./us', (string)$replacement, $rmatches); |
| 596 | if ($length === null) { |
| 597 | $length = mb_strlen($string); |
| 598 | } |
| 599 | array_splice($smatches[0], $start, $length, $rmatches[0]); |
| 600 | return join($smatches[0]); |
| 601 | } |
| 602 | |
| 603 | |
| 604 | /** |
| 605 | * Push to assoc array |
| 606 | * |
| 607 | * @access public |
| 608 | * @static |
| 609 | * @since 2.19 |
| 610 | */ |
| 611 | public static function cff_array_push_assoc($array, $key, $value) |
| 612 | { |
| 613 | $array[$key] = $value; |
| 614 | return $array; |
| 615 | } |
| 616 | |
| 617 | |
| 618 | /** |
| 619 | * Convert string to slug |
| 620 | * |
| 621 | * @access public |
| 622 | * @static |
| 623 | * @since 2.19 |
| 624 | */ |
| 625 | public static function cff_to_slug($string) |
| 626 | { |
| 627 | return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $string))); |
| 628 | } |
| 629 | |
| 630 | |
| 631 | /** |
| 632 | * Convert string to slug |
| 633 | * |
| 634 | * @access public |
| 635 | * @static |
| 636 | * @since 2.19 |
| 637 | */ |
| 638 | public static function cff_get_utc_offset() |
| 639 | { |
| 640 | return get_option('gmt_offset', 0) * HOUR_IN_SECONDS; |
| 641 | } |
| 642 | |
| 643 | |
| 644 | public static function cff_schedule_report_email() |
| 645 | { |
| 646 | $options = get_option('cff_style_settings'); |
| 647 | $input = isset($options[ 'email_notification' ]) ? $options[ 'email_notification' ] : 'monday'; |
| 648 | $timestamp = strtotime('next ' . $input); |
| 649 | $timestamp = $timestamp + (3600 * 24 * 7); |
| 650 | $six_am_local = $timestamp + CFF_Utils::cff_get_utc_offset() + (6 * 60 * 60); |
| 651 | wp_schedule_event($six_am_local, 'cffweekly', 'cff_feed_issue_email'); |
| 652 | } |
| 653 | |
| 654 | |
| 655 | /** |
| 656 | * |
| 657 | * @access public |
| 658 | * @static |
| 659 | * @since 2.19 |
| 660 | */ |
| 661 | public static function cff_is_pro_version() |
| 662 | { |
| 663 | return defined('CFFWELCOME_VER'); |
| 664 | } |
| 665 | |
| 666 | /** |
| 667 | * |
| 668 | * @access public |
| 669 | * @static |
| 670 | * @since 2.19 |
| 671 | */ |
| 672 | public static function cff_get_set_cache($cff_posts_json_url, $transient_name, $cff_cache_time, $cache_seconds, $data_att_html, $cff_show_access_token, $access_token, $backup = false) |
| 673 | { |
| 674 | $cache_seconds = max($cache_seconds, 60); |
| 675 | |
| 676 | // Trying to use new cache table |
| 677 | $shortcode_atts = is_array($data_att_html) ? $data_att_html : json_decode(str_replace('"', '"', $data_att_html), true); |
| 678 | |
| 679 | if (! empty($shortcode_atts['feed'])) { |
| 680 | $feed_id = (int)$shortcode_atts['feed']; |
| 681 | $is_legacy = false; |
| 682 | } else { |
| 683 | $feed_id = $transient_name; |
| 684 | $is_legacy = true; |
| 685 | } |
| 686 | |
| 687 | $feed_page = isset($shortcode_atts['feedPage']) ? $shortcode_atts['feedPage'] : 1; |
| 688 | $feed_cache = new CFF_Cache($feed_id, $feed_page, $cache_seconds, $is_legacy); |
| 689 | $feed_cache->retrieve_and_set(); |
| 690 | |
| 691 | $cache_type = 'posts'; |
| 692 | if (strpos($transient_name, 'cff_header_') !== false) { |
| 693 | $cache_type = 'header'; |
| 694 | } |
| 695 | |
| 696 | // no pages in free |
| 697 | $cache_type_page = $cache_type; |
| 698 | if ($cache_type === 'posts' && $feed_page > 1) { |
| 699 | $cache_type_page = 'posts_' . $feed_page; |
| 700 | } |
| 701 | |
| 702 | if ($feed_cache->is_expired($cache_type)) { |
| 703 | // Get the contents of the Facebook page |
| 704 | $posts_json = CFF_Utils::cff_fetchUrl($cff_posts_json_url); |
| 705 | |
| 706 | if ($is_legacy && $cache_type === 'header') { |
| 707 | $feed_cache->update_or_insert($cache_type, $posts_json); |
| 708 | } |
| 709 | |
| 710 | // Check whether any data is returned from the API. If it isn't then don't cache the error response and instead keep checking the API on every page load until data is returned. |
| 711 | $FBdata = json_decode($posts_json); |
| 712 | |
| 713 | // Check whether the JSON is wrapped in a "data" property as if it doesn't then it's a featured post |
| 714 | $prefix_data = '{"data":'; |
| 715 | (substr($posts_json, 0, strlen($prefix_data)) == $prefix_data) ? $cff_featured_post = false : $cff_featured_post = true; |
| 716 | |
| 717 | // Add API URL to beginning of JSON array |
| 718 | $prefix = '{'; |
| 719 | if (substr($posts_json, 0, strlen($prefix)) == $prefix) { |
| 720 | $posts_json = substr($posts_json, strlen($prefix)); |
| 721 | } |
| 722 | |
| 723 | // Encode and replace quotes so can be stored as a string |
| 724 | $data_att_html = str_replace('"', '"', json_encode($data_att_html)); |
| 725 | $posts_json = '{"api_url":"' . $cff_posts_json_url . '", "shortcode_options":"' . $data_att_html . '", ' . $posts_json; |
| 726 | |
| 727 | // If it's a featured post then it doesn't contain 'data' |
| 728 | if (!$cff_featured_post) { |
| 729 | $FBdata = $FBdata->data; |
| 730 | } |
| 731 | |
| 732 | // Check the API response |
| 733 | if (!empty($FBdata)) { |
| 734 | // Error returned by API |
| 735 | if (isset($FBdata->error)) { |
| 736 | // Cache the error JSON so doesn't keep making repeated requests |
| 737 | // See if a backup cache exists |
| 738 | if (false !== $feed_cache->get($cache_type . '_backup')) { |
| 739 | $posts_cache = $feed_cache->get($cache_type . '_backup'); |
| 740 | $posts_json = is_null($posts_cache) ? '{}' : $posts_cache; |
| 741 | // Add error message to backup cache so can be displayed at top of feed |
| 742 | isset($FBdata->error->message) ? $error_message = $FBdata->error->message : $error_message = ''; |
| 743 | isset($FBdata->error->type) ? $error_type = $FBdata->error->type : $error_type = ''; |
| 744 | $prefix = '{'; |
| 745 | if (substr($posts_json, 0, strlen($prefix)) == $prefix) { |
| 746 | $posts_json = substr($posts_json, strlen($prefix)); |
| 747 | } |
| 748 | $error_json = '{"cached_error": { "message": "' . $error_message . '", "type": "' . $error_type . '" }'; |
| 749 | $error_json .= !empty($posts_json) ? ', ' . $posts_json : '}'; |
| 750 | $posts_json = $error_json; |
| 751 | } |
| 752 | |
| 753 | // Posts data returned by API |
| 754 | } else { |
| 755 | // If a backup should be created for this data then create one |
| 756 | if ($backup) { |
| 757 | $feed_cache->update_or_insert($cache_type . '_backup', $posts_json); |
| 758 | } |
| 759 | |
| 760 | if ($cache_type === 'posts') { |
| 761 | $feed_cache->after_new_posts_retrieved(); |
| 762 | } |
| 763 | } |
| 764 | |
| 765 | $feed_cache->update_or_insert($cache_type, $posts_json); |
| 766 | } |
| 767 | } else { |
| 768 | $posts_json = $feed_cache->get($cache_type_page); |
| 769 | if (strpos($posts_json, '"error":{"message":') !== false) { |
| 770 | // Use backup cache if exists |
| 771 | $posts_json = $feed_cache->get($cache_type . '_backup'); |
| 772 | } |
| 773 | |
| 774 | // If we can't find the transient then fall back to just getting the json from the api |
| 775 | if ($posts_json == false) { |
| 776 | $posts_json = CFF_Utils::cff_fetchUrl($cff_posts_json_url); |
| 777 | } |
| 778 | } |
| 779 | |
| 780 | return $posts_json; |
| 781 | } |
| 782 | |
| 783 | |
| 784 | /** |
| 785 | * Check if On |
| 786 | * Function to check if a shortcode options is set to ON or TRUE |
| 787 | * |
| 788 | * @access public |
| 789 | * @static |
| 790 | * @since 2.19 |
| 791 | * @return boolean |
| 792 | */ |
| 793 | public static function check_if_on($value) |
| 794 | { |
| 795 | return ( isset($value) && !empty($value) && ( $value == 'true' || $value == 'on') ) ? true : false; |
| 796 | } |
| 797 | |
| 798 | /** |
| 799 | * Check if On |
| 800 | * Function to check if a shortcode options is set to ON or TRUE |
| 801 | * |
| 802 | * @access public |
| 803 | * @static |
| 804 | * @since 2.19 |
| 805 | * @return boolean |
| 806 | */ |
| 807 | public static function check_if_onexist($value) |
| 808 | { |
| 809 | return ( ( isset($value) ) ) ? true : false; |
| 810 | } |
| 811 | |
| 812 | /** |
| 813 | * Check Value |
| 814 | * Function to check a value if exists or return a default one |
| 815 | * |
| 816 | * @access public |
| 817 | * @static |
| 818 | * @since 2.19 |
| 819 | * @return mixed |
| 820 | */ |
| 821 | public static function return_value($value, $default = '') |
| 822 | { |
| 823 | return ( isset($value) && !empty($value) ) ? $value : $default; |
| 824 | } |
| 825 | |
| 826 | |
| 827 | /** |
| 828 | * Get CSS value |
| 829 | * Checks if the value is a valid CSS distance |
| 830 | * |
| 831 | * @access public |
| 832 | * @static |
| 833 | * @since 2.19 |
| 834 | * @return string |
| 835 | */ |
| 836 | public static function get_css_distance($value) |
| 837 | { |
| 838 | return ( is_numeric(substr($value, -1, 1)) ) ? $value . 'px' : $value; |
| 839 | } |
| 840 | |
| 841 | |
| 842 | /** |
| 843 | * |
| 844 | * |
| 845 | * This function will get the Profile Pic, Cover, Name, About |
| 846 | * For the visual header display |
| 847 | * |
| 848 | * @access public |
| 849 | * @static |
| 850 | * @since 2.19 |
| 851 | */ |
| 852 | public static function fetch_header_data($page_id, $cff_is_group, $access_token, $cff_cache_time, $cff_multifeed_active = false, $data_att_html = array()) |
| 853 | { |
| 854 | // Create Transient Name |
| 855 | $transient_name = 'cff_header_' . $page_id; |
| 856 | $transient_name = substr($transient_name, 0, 45); |
| 857 | |
| 858 | // These fields only apply to pages |
| 859 | !$cff_is_group ? $page_only_fields = ',fan_count,about' : $page_only_fields = ''; |
| 860 | |
| 861 | $header_access_token = $access_token; |
| 862 | if (is_array($access_token)) { |
| 863 | $header_access_token = reset($access_token); |
| 864 | if (empty($header_access_token)) { |
| 865 | $header_access_token = key($access_token); |
| 866 | } |
| 867 | } |
| 868 | |
| 869 | $encryption = new SB_Facebook_Data_Encryption(); |
| 870 | $header_access_token = $encryption->decrypt($header_access_token) ? $encryption->decrypt($header_access_token) : $header_access_token; |
| 871 | |
| 872 | |
| 873 | $header_details_json_url = 'https://graph.facebook.com/v23.0/' . $page_id . '?fields=id,picture.height(150).width(150),cover,name,link' . $page_only_fields . '&access_token=' . $header_access_token; |
| 874 | |
| 875 | // Get the data |
| 876 | $header_details = CFF_Utils::cff_get_set_cache($header_details_json_url, $transient_name, $cff_cache_time, WEEK_IN_SECONDS, $data_att_html, false, $access_token, true); |
| 877 | $header_details = json_decode($header_details); |
| 878 | return $header_details; |
| 879 | } |
| 880 | |
| 881 | |
| 882 | /** |
| 883 | * |
| 884 | * |
| 885 | * Print Template |
| 886 | * returns an HTML Template |
| 887 | * |
| 888 | * @access public |
| 889 | * @static |
| 890 | * @since 2.19 |
| 891 | */ |
| 892 | public static function print_template_part($template_name, $args = array(), $this_class = null) |
| 893 | { |
| 894 | extract($args); |
| 895 | ob_start(); |
| 896 | include trailingslashit(CFF_PLUGIN_DIR) . 'templates/' . $template_name . '.php'; |
| 897 | $template = ob_get_contents(); |
| 898 | ob_get_clean(); |
| 899 | return $template; |
| 900 | } |
| 901 | |
| 902 | /** |
| 903 | * |
| 904 | * Get Connected Accounts |
| 905 | * |
| 906 | * @since 2.19 |
| 907 | */ |
| 908 | public static function cff_get_connected_accounts() |
| 909 | { |
| 910 | $cff_connected_accounts = get_option('cff_connected_accounts', array()); |
| 911 | if (!is_array($cff_connected_accounts) && !empty($cff_connected_accounts)) { |
| 912 | $cff_connected_accounts = str_replace('\"', '"', $cff_connected_accounts); |
| 913 | $cff_connected_accounts = str_replace("\'", "'", $cff_connected_accounts); |
| 914 | $cff_connected_accounts = json_decode($cff_connected_accounts, true); |
| 915 | } |
| 916 | if (!is_array($cff_connected_accounts) || $cff_connected_accounts == null) { |
| 917 | $cff_connected_accounts = []; |
| 918 | } |
| 919 | return $cff_connected_accounts; |
| 920 | } |
| 921 | /** |
| 922 | * |
| 923 | * Get Connected Accounts |
| 924 | * |
| 925 | * @since 3.18 |
| 926 | */ |
| 927 | public static function cff_get_connected_accounts_object() |
| 928 | { |
| 929 | $cff_connected_accounts = get_option('cff_connected_accounts', array()); |
| 930 | if (!empty($cff_connected_accounts)) { |
| 931 | $cff_connected_accounts = str_replace('\"', '"', $cff_connected_accounts); |
| 932 | $cff_connected_accounts = str_replace("\'", "'", $cff_connected_accounts); |
| 933 | $cff_connected_accounts = json_decode($cff_connected_accounts); |
| 934 | } |
| 935 | $check_array = (array) $cff_connected_accounts; |
| 936 | if (empty($check_array)) { |
| 937 | $cff_connected_accounts = false; |
| 938 | } |
| 939 | return $cff_connected_accounts; |
| 940 | } |
| 941 | |
| 942 | /** |
| 943 | * Summary of get_post_text |
| 944 | * |
| 945 | * @param array $post |
| 946 | * |
| 947 | * @return string |
| 948 | */ |
| 949 | public static function get_post_text($post) |
| 950 | { |
| 951 | if (!empty($post['story'])) { |
| 952 | return $post['story']; |
| 953 | } |
| 954 | if (!empty($post['message'])) { |
| 955 | return $post['message']; |
| 956 | } |
| 957 | if (!empty($post['name']) && empty($post['story']) && empty($post['message'])) { |
| 958 | return $post['name']; |
| 959 | } |
| 960 | return ''; |
| 961 | } |
| 962 | |
| 963 | /** |
| 964 | * Summary of parse_json_data |
| 965 | * |
| 966 | * @param mixed $data |
| 967 | * |
| 968 | * @return array |
| 969 | */ |
| 970 | public static function parse_json_data($data) |
| 971 | { |
| 972 | $json = json_decode($data, true); |
| 973 | if (is_string($json)) { |
| 974 | $json = json_decode($json, true); |
| 975 | } |
| 976 | return is_array($json) ? $json : []; |
| 977 | } |
| 978 | } |
| 979 |