Senaste WordPress uppdateringen 7.1 har problem med WordPress pluginet WProcket. Besökarna mötes av felmedelandet
Det har uppstått ett kritiskt fel på webbplatsen.
Fatal error: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, int given in wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php:562 Stack trace: #0 wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php(562): substr() #1 wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php(535): WP_Rocket\ThirdParty\Plugins\CDN\Cloudflare->unregister_callback() #2 wp-includes/class-wp-hook.php(353): WP_Rocket\ThirdParty\Plugins\CDN\Cloudflare->unregister_cloudflare_clean_on_post() #3 wp-includes/class-wp-hook.php(377): WP_Hook->apply_filters() #4 wp-includes/plugin.php(523): WP_Hook->do_action() #5 wp-settings.php(779): do_action() #6 wp-config.php(98): require_once(‘…’) #7 wp-load.php(50): require_once(‘…’) #8 wp-blog-header.php(13): require_once(‘…’) #9 index.php(17): require(‘…’) #10 {main} thrown in wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php on line 562
Det har uppstått ett kritiskt fel på webbplatsen.
För våra kunder som har managed WordPress har vi redan löst det problemet.
Fixen är att ändra filen Cloudflare.php som ligger i
wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php
Rad 562 ska ändras till detta
if ( substr( (string) $key, – strlen( $method ) ) !== $method ) {
Nedan följer hela filen som kan laddas upp om man sparar filen som Cloudflare.php och laddar upp den i wp-content/plugins/wp-rocket/inc/ThirdParty/Plugins/CDN/ och skriver över filen som finns där.
options = $options;
$this->options_api = $options_api;
$this->beacon = $beacon;
$this->facade = $facade;
}
/**
* Return an array of events that this subscriber wants to listen to.
*
* @return array
*/
public static function get_subscribed_events() {
return [
'admin_notices' => [
[ 'display_server_pushing_mode_notice' ],
[ 'display_apo_cookies_notice' ],
[ 'display_apo_cache_notice' ],
],
'rocket_display_input_do_cloudflare' => 'hide_addon_radio',
'rocket_cloudflare_field_settings' => 'update_addon_field',
'pre_get_rocket_option_do_cloudflare' => 'disable_cloudflare_option',
'rocket_after_clean_domain' => 'purge_cloudflare',
'after_rocket_clean_files' => 'purge_cloudflare_partial',
'after_rocket_clean_home' => 'purge_cloudflare_home',
'rocket_after_automatic_cache_purge' => 'purge_cloudflare_after_automatic_purge',
'rocket_saas_complete_job_status' => 'purge_cloudflare_after_usedcss',
'rocket_rucss_after_clearing_usedcss' => 'purge_cloudflare_after_usedcss',
'admin_post_rocket_enable_separate_mobile_cache' => 'enable_separate_mobile_cache',
'rocket_cdn_helper_addons' => 'add_cdn_helper_message',
'init' => 'unregister_cloudflare_clean_on_post',
];
}
/**
* Display notice for server pushing mode.
*
* @return void
*/
public function display_server_pushing_mode_notice() {
if ( ! rocket_get_constant( 'CLOUDFLARE_PLUGIN_DIR' ) ) {
return;
}
if ( ! rocket_get_constant( 'CLOUDFLARE_HTTP2_SERVER_PUSH_ACTIVE' ) ) {
return;
}
$screen = get_current_screen();
// If current screen is wprocket settings.
if (
isset( $screen->id )
&&
'settings_page_wprocket' !== $screen->id
) {
return;
}
// if current user has required capapabilities.
if ( ! current_user_can( 'rocket_manage_options' ) ) {
return;
}
// If RUCSS is enabled.
if ( ! (bool) $this->options->get( 'remove_unused_css', 0 ) ) {
return;
}
$boxes = get_user_meta( get_current_user_id(), 'rocket_boxes', true );
$notice_name = 'cloudflare_server_push';
if ( in_array( $notice_name, (array) $boxes, true ) ) {
return;
}
$message = sprintf(
// translators: %1$s = plugin name.
__( '%1$s: Cloudflare\'s HTTP/2 Server Push is incompatible with the features of Remove Unused CSS and Combine CSS files. We strongly recommend disabling it.', 'rocket' ),
'WP Rocket'
);
rocket_notice_html(
[
'status' => 'warning',
'dismissible' => '',
'message' => $message,
'id' => 'cloudflare_server_push_notice',
'dismiss_button' => $notice_name,
'dismiss_button_class' => 'button-primary',
]
);
}
/**
* Hide WP Rocket CF Addon activation button if the official CF plugin is enabled
*
* @param bool $enable True to display, False otherwise.
*
* @return bool
*/
public function hide_addon_radio( $enable ) {
if ( ! $this->is_plugin_active() ) {
return $enable;
}
return false;
}
/**
* Updates WP Rocket CF Addon field when the official CF plugin is enabled
*
* @param array $settings Array of values to populate the field.
*
* @return array
*/
public function update_addon_field( $settings ) {
if ( ! $this->is_plugin_active() ) {
return $settings;
}
$settings['do_cloudflare']['title'] = __( 'Your site is using the official Cloudflare plugin. We have enabled Cloudflare auto-purge for compatibility. If you have APO activated, it is also compatible.', 'rocket' );
$settings['do_cloudflare']['description'] = __( 'Cloudflare cache will be purged each time WP Rocket clears its cache to ensure content is always up-to-date.', 'rocket' );
$settings['do_cloudflare']['helper'] = '';
$settings['do_cloudflare']['settings_page'] = '';
return $settings;
}
/**
* Disable WP Rocket CF option when Cloudflare plugin is enabled
*
* @param mixed $value Pre option value.
*
* @return bool
*/
public function disable_cloudflare_option( $value ) {
if ( ! $this->is_plugin_active() ) {
return $value;
}
return false;
}
/**
* Display a notice when APO is enabled and mandatory/dynamic cookies exists
*
* @return void
*/
public function display_apo_cookies_notice() {
if ( ! $this->can_display_notice() ) {
return;
}
if (
empty( get_rocket_cache_mandatory_cookies() )
&&
empty( get_rocket_cache_dynamic_cookies() )
) {
return;
}
$doc = $this->beacon->get_suggest( 'cloudflare_apo' );
$message = sprintf(
// Translators: %1$s = strong opening tag, %2$s = strong closing tag.
__( '%1$sWP Rocket:%2$s You are using "Dynamic Cookies Cache". Cloudflare APO is not yet compatible with that feature.', 'rocket' ) . '
',
'',
''
);
$message .= sprintf(
// Translators:%1$s = opening tag, %2$s = closing tag.
__( 'You should either disable Cloudflare APO or check with the theme/plugin requiring the use of “Dynamic Cookies Cache” developers for an alternative way to be page-cache friendly. %1$sMore info%2$s', 'rocket' ),
'',
''
);
rocket_notice_html(
[
'status' => 'warning',
'dismissible' => '',
'message' => $message,
]
);
}
/**
* Display a notice when there is a mismatch between WP Rocket separate cache by mobile value and APO cache by device type
*
* @return void
*/
public function display_apo_cache_notice() {
if ( ! $this->can_display_notice() ) {
return;
}
$cf_device_type = get_option( 'automatic_platform_optimization_cache_by_device_type', [] );
if ( ! key_exists( 'value', $cf_device_type ) ) {
return;
}
$mobile_cache = $this->options->get( 'do_caching_mobile_files', 0 );
if ( (int) $mobile_cache === (int) $cf_device_type['value'] ) {
return;
}
$doc = $this->beacon->get_suggest( 'cloudflare_apo' );
$boxes = get_user_meta( get_current_user_id(), 'rocket_boxes', true );
if (
1 === (int) $mobile_cache
&&
0 === (int) $cf_device_type['value']
) {
rocket_notice_html(
[
'status' => 'warning',
'dismissible' => '',
'message' => sprintf(
// Translators: %1$s = strong opening tag, %2$s = strong closing tag, %3$s = opening tag, %4$s = closing tag, %5$s = opening tag.
__( '%1$sWP Rocket:%2$s You are using "Separate cache files for mobile devices". You need to activate "Cache by Device Type" %3$ssetting%5$s on Cloudflare APO to serve the right version of the cache. %4$sMore info%5$s', 'rocket' ),
'',
'',
'',
'',
''
),
]
);
} elseif (
0 === (int) $mobile_cache
&&
1 === (int) $cf_device_type['value']
&&
! in_array( __FUNCTION__, (array) $boxes, true )
) {
rocket_notice_html(
[
'status' => 'warning',
'message' => sprintf(
// Translators: %1$s = strong opening tag, %2$s = strong closing tag.
__( '%1$sWP Rocket:%2$s You have "Cache by Device Type" enabled on Cloudflare APO. If you judge it necessary for the website to have a different cache on mobile and desktop, we suggest you enable our “Separate Cache Files for Mobiles Devices” to ensure the generated cache is accurate.', 'rocket' ),
'',
''
),
'dismiss_button' => __FUNCTION__,
'dismissible' => '',
'action' => 'enable_separate_mobile_cache',
]
);
}
}
/**
* Checks if APO notices should be displayed
*
* @return bool
*/
private function can_display_notice(): bool {
if ( ! current_user_can( 'rocket_manage_options' ) ) {
return false;
}
$screen = get_current_screen();
if (
isset( $screen->id )
&&
'settings_page_wprocket' !== $screen->id
) {
return false;
}
if ( ! $this->is_plugin_active() ) {
return false;
}
return $this->is_apo_enabled();
}
/**
* Purge everything on Cloudflare
*
* @return void
*/
public function purge_cloudflare() {
if ( ! $this->is_plugin_active() ) {
return;
}
$this->facade->purge_everything();
}
/**
* Purge home page on Cloudflare
*
* @since 3.20.2
*
* @param string $lang Current language.
*
* @return void
*/
public function purge_cloudflare_home( $lang = '' ) {
if ( ! $this->is_plugin_active() ) {
return;
}
// Get the home URL for the specific language.
$home_url = get_rocket_i18n_home_url( $lang );
// Try to get post ID from home URL.
$post_id = url_to_postid( $home_url );
// If we have a valid post ID, purge that specific URL.
if ( $post_id > 0 ) {
$this->facade->purge_urls( $post_id );
return;
}
// If no post ID found, check if we have a static front page.
if ( 'page' === get_option( 'show_on_front' ) ) {
$page_on_front = get_option( 'page_on_front' );
if ( $page_on_front && get_post( $page_on_front ) instanceof \WP_Post ) {
$this->facade->purge_urls( (int) $page_on_front );
}
}
}
/**
* Purges posts when using purge this URL button
*
* @param array $urls Array of URLs.
*
* @return void
*/
public function purge_cloudflare_partial( $urls ) {
if ( ! $this->is_plugin_active() ) {
return;
}
$post_ids = array_filter( array_map( 'url_to_postid', $urls ) );
$this->facade->purge_urls( $post_ids );
}
/**
* Purges Cloudflare cache after automatic cache purge (cache lifespan)
*
* @since 3.20.2
*
* @param array $deleted Array of deleted cache data.
*
* @return void
*/
public function purge_cloudflare_after_automatic_purge( $deleted ) {
if ( ! $this->is_plugin_active() ) {
return;
}
$urls_to_purge = Utils::process_deleted_cache_urls( $deleted );
if ( empty( $urls_to_purge ) ) {
return;
}
// Convert URLs to post IDs for Cloudflare purging.
$post_ids = array_filter( array_map( 'url_to_postid', $urls_to_purge ) );
if ( ! empty( $post_ids ) ) {
$this->facade->purge_urls( $post_ids );
}
}
/**
* Purges CF after Used CSS generation or clean
*
* @param string $url URL to purge.
*
* @return void
*/
public function purge_cloudflare_after_usedcss( $url ) {
if ( ! $this->is_plugin_active() ) {
return;
}
$post_id = url_to_postid( $url );
if ( empty( $post_id ) ) {
return;
}
$this->facade->purge_urls( $post_id );
}
/**
* Enable separate cache for mobile option
*
* @return void
*/
public function enable_separate_mobile_cache() {
check_admin_referer( 'rocket_enable_separate_mobile_cache' );
if ( ! current_user_can( 'rocket_manage_options' ) ) {
return;
}
$this->options->set( 'cache_mobile', 1 );
$this->options->set( 'do_caching_mobile_files', 1 );
$this->options_api->set( 'settings', $this->options->get_options() );
wp_safe_redirect( wp_get_referer() );
rocket_get_constant( 'WP_ROCKET_IS_TESTING', false ) ? wp_die() : exit;
}
/**
* Checks if CF plugin is enabled & credentials saved
*
* @return bool
*/
private function is_plugin_active(): bool {
if ( ! is_plugin_active( 'cloudflare/cloudflare.php' ) ) {
return false;
}
if (
empty( get_option( 'cloudflare_api_email', '' ) )
||
empty( get_option( 'cloudflare_api_key', '' ) )
||
empty( get_option( 'cloudflare_cached_domain_name', '' ) )
) {
return false;
}
return true;
}
/**
* Checks if CF APO is enabled
*
* @return bool
*/
private function is_apo_enabled(): bool {
$is_apo_enabled = get_option( 'automatic_platform_optimization', [] );
if ( ! key_exists( 'value', $is_apo_enabled ) ) {
return false;
}
return (bool) $is_apo_enabled['value'];
}
/**
* Add the helper message on the CDN settings.
*
* @param string[] $addons Name from the addon that requires the helper message.
* @return string[]
*/
public function add_cdn_helper_message( array $addons ): array {
if ( ! $this->is_plugin_active() ) {
return $addons;
}
$addons[] = 'Cloudflare';
return $addons;
}
/**
* Purge Cloudflare on deactivate.
*
* @return void
*/
public function deactivate() {
$this->purge_cloudflare();
}
/**
* Unregister Call on clean posts.
*
* @return void
*/
public function unregister_cloudflare_clean_on_post() {
$this->unregister_callback( 'deleted_post', 'purgeCacheByRelevantURLs' );
$this->unregister_callback( 'transition_post_status', 'purgeCacheOnPostStatusChange', PHP_INT_MAX );
}
/**
* Unregister a callback.
*
* @param string $hook Hook on which to unregister.
* @param string $method The callback to unregister.
* @param int $priority the priority from the callback.
* @return void
*/
protected function unregister_callback( string $hook, string $method, int $priority = 10 ) {
global $wp_filter;
if ( ! key_exists( $hook, $wp_filter ) ) {
return;
}
$original_wp_filter = $wp_filter[ $hook ]->callbacks;
if ( ! key_exists( $priority, $original_wp_filter ) ) {
return;
}
foreach ( $original_wp_filter[ $priority ] as $key => $config ) {
if ( substr( (string) $key, - strlen( $method ) ) !== $method ) {
continue;
}
unset( $wp_filter[ $hook ]->callbacks[ $priority ][ $key ] );
}
}
}