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