oont-contents/plugins/wp-rocket/inc/Engine/Cache/WPCache.php
2025-02-08 15:10:23 +01:00

392 lines
8.9 KiB
PHP

<?php
namespace WP_Rocket\Engine\Cache;
use WP_Rocket\Engine\Activation\ActivationInterface;
use WP_Rocket\Engine\Deactivation\DeactivationInterface;
class WPCache implements ActivationInterface, DeactivationInterface {
/**
* Filesystem instance.
*
* @var WP_Filesystem_Direct
*/
private $filesystem;
/**
* Instantiate the class
*
* @param WP_Filesystem_Direct $filesystem Filesystem instance.
*/
public function __construct( $filesystem ) {
$this->filesystem = $filesystem;
}
/**
* Performs these actions during the plugin activation
*
* @return void
*/
public function activate() {
add_action( 'rocket_activation', [ $this, 'update_wp_cache' ] );
}
/**
* Performs these actions during the plugin deactivation
*
* @return void
*/
public function deactivate() {
add_action( 'rocket_deactivation', [ $this, 'update_wp_cache' ] );
add_filter( 'rocket_prevent_deactivation', [ $this, 'maybe_prevent_deactivation' ] );
}
/**
* Sets the WP_CACHE constant on (de)activation
*
* @since 3.6.3
*
* @param int $sites_number Number of WP Rocket config files found.
* @return void
*/
public function update_wp_cache( $sites_number = 0 ) {
if ( ! rocket_valid_key() ) {
return;
}
$value = true;
if ( 'rocket_deactivation' === current_filter() ) {
if ( is_multisite() && 0 !== $sites_number ) {
return;
}
$value = false;
}
$this->set_wp_cache_constant( $value );
}
/**
* Updates the causes array on deactivation if needed
*
* @since 3.6.3
*
* @param array $causes Array of causes to pass to the notice.
*/
public function maybe_prevent_deactivation( $causes ) {
if (
$this->find_wpconfig_path()
||
// This filter is documented in inc/Engine/Cache/WPCache.php.
! (bool) apply_filters( 'rocket_set_wp_cache_constant', true )
) {
return $causes;
}
$causes[] = 'wpconfig';
return $causes;
}
/**
* Set WP_CACHE constant to true if needed
*
* @since 3.6.1
*
* @return void
*/
public function maybe_set_wp_cache() {
if (
rocket_get_constant( 'DOING_AJAX' )
||
rocket_get_constant( 'DOING_AUTOSAVE' )
) {
return;
}
if ( rocket_get_constant( 'WP_CACHE' ) ) {
return;
}
$this->set_wp_cache_constant( true );
}
/**
* Sets the value of the WP_CACHE constant in wp-config.php
*
* @since 3.6.1
*
* @param bool $value The value to set for WP_CACHE constant.
* @return bool true on success, false otherwise.
*/
public function set_wp_cache_constant( $value ) {
if ( ! $this->should_set_wp_cache_constant( $value ) ) {
return false;
}
$config_file_path = $this->find_wpconfig_path();
if ( ! $config_file_path ) {
return false;
}
$config_file_contents = $this->filesystem->get_contents( $config_file_path );
$value = $value ? 'true' : 'false';
/**
* Filter allow to change the value of WP_CACHE constant
*
* @since 2.1
*
* @param string $value The value of WP_CACHE constant.
*/
$value = apply_filters( 'set_rocket_wp_cache_define', $value ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
$wp_cache_found = preg_match( '/^\s*define\(\s*\'WP_CACHE\'\s*,\s*(?<value>[^\s\)]*)\s*\)/m', $config_file_contents, $matches );
if (
! empty( $matches['value'] )
&&
$matches['value'] === $value
) {
return false;
}
$constant = $this->get_wp_cache_content( $value );
if ( ! $wp_cache_found ) {
$config_file_contents = preg_replace( '/(<\?php)/i', "<?php\r\n{$constant}\r\n", $config_file_contents, 1 );
} elseif ( ! empty( $matches['value'] ) && $matches['value'] !== $value ) {
$config_file_contents = preg_replace( '/^\s*define\(\s*\'WP_CACHE\'\s*,\s*([^\s\)]*)\s*\).+/m', $constant, $config_file_contents );
}
return $this->filesystem->put_contents( $config_file_path, $config_file_contents, rocket_get_filesystem_perms( 'file' ) );
}
/**
* Checks if we should set the WP_CACHE constant
*
* @since 3.6.1
*
* @param bool $value The value to set for WP_CACHE constant.
* @return bool
*/
private function should_set_wp_cache_constant( $value ) {
if ( ! $this->is_user_allowed() ) {
return false;
}
if (
true === $value
&&
rocket_get_constant( 'WP_CACHE' )
) {
return false;
}
/**
* Filters the writing of the WP_CACHE constant in wp-config.php
*
* @since 3.6.1
* @param bool $set True to allow writing, false otherwise.
*/
return (bool) apply_filters( 'rocket_set_wp_cache_constant', true );
}
/**
* Try to find the correct wp-config.php file, support one level up in file tree.
*
* @since 3.6.1
*
* @return string|bool The path of wp-config.php file or false if not found.
*/
private function find_wpconfig_path() {
/**
* Filter the wp-config's filename.
*
* @since 2.11
*
* @param string $filename The WP Config filename, without the extension.
*/
$config_file_name = apply_filters( 'rocket_wp_config_name', 'wp-config' );
$abspath = rocket_get_constant( 'ABSPATH' );
$config_file = "{$abspath}{$config_file_name}.php";
if ( $this->filesystem->is_writable( $config_file ) ) {
return $config_file;
}
$abspath_parent = dirname( $abspath ) . DIRECTORY_SEPARATOR;
$config_file_alt = "{$abspath_parent}{$config_file_name}.php";
if (
$this->filesystem->exists( $config_file_alt )
&&
$this->filesystem->is_writable( $config_file_alt )
&&
! $this->filesystem->exists( "{$abspath_parent}wp-settings.php" )
) {
return $config_file_alt;
}
// No writable file found.
return false;
}
/**
* This warning is displayed when the wp-config.php file isn't writable
*
* @since 3.6.1
*
* @return void
*/
public function notice_wp_config_permissions() {
global $pagenow;
if (
'plugins.php' === $pagenow
||
isset( $_GET['activate'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
) {
return;
}
if ( ! $this->is_user_allowed() ) {
return;
}
if ( rocket_get_constant( 'WP_CACHE' ) ) {
return;
}
// This filter is documented in inc/Engine/Cache/WPCache.php.
if ( ! (bool) apply_filters( 'rocket_set_wp_cache_constant', true ) ) {
return;
}
if ( $this->find_wpconfig_path() ) {
return;
}
$notice_name = 'rocket_warning_wp_config_permissions';
if (
in_array(
$notice_name,
(array) get_user_meta( get_current_user_id(), 'rocket_boxes', true ),
true
)
) {
return;
}
rocket_notice_html(
[
'status' => 'error',
'dismissible' => '',
'message' => rocket_notice_writing_permissions( 'wp-config.php' ),
'dismiss_button' => $notice_name,
'readonly_content' => $this->get_wp_cache_content(),
]
);
}
/**
* Checks if current user can perform the action
*
* @since 3.6.1
*
* @return bool
*/
private function is_user_allowed() {
return ( rocket_get_constant( 'WP_CLI', false ) || current_user_can( 'rocket_manage_options' ) ) && rocket_valid_key();
}
/**
* Gets the content to add to the wp-config.php file
*
* @since 3.6.1
*
* @param string $value Value for the WP_CACHE constant.
* @return string
*/
private function get_wp_cache_content( $value = 'true' ) {
$plugin_name = rocket_get_constant( 'WP_ROCKET_PLUGIN_NAME' );
return "define( 'WP_CACHE', {$value} ); // Added by {$plugin_name}";
}
/**
* Adds a Site Health check for the WP_CACHE constant value
*
* @since 3.6.1
*
* @param array $tests An array of tests to perform.
* @return array
*/
public function add_wp_cache_status_test( $tests ) {
// This filter is documented in inc/Engine/Cache/WPCache.php.
if ( ! (bool) apply_filters( 'rocket_set_wp_cache_constant', true ) ) {
return $tests;
}
$tests['direct']['wp_cache_status'] = [
'label' => __( 'WP_CACHE value', 'rocket' ),
'test' => [ $this, 'check_wp_cache_value' ],
];
return $tests;
}
/**
* Checks the WP_CACHE constant value and return the result for Site Health
*
* @since 3.6.1
*
* @return array
*/
public function check_wp_cache_value() {
$result = [
'badge' => [
'label' => __( 'Cache', 'rocket' ),
],
'description' => sprintf(
'<p>%s</p>',
__( 'The WP_CACHE constant needs to be set to true for WP Rocket cache to work properly', 'rocket' )
),
'actions' => '',
'test' => 'wp_cache_status',
];
$value = rocket_get_constant( 'WP_CACHE' );
if ( true === $value ) {
$result['label'] = __( 'WP_CACHE is set to true', 'rocket' );
$result['status'] = 'good';
$result['badge']['color'] = 'green';
return $result;
}
if ( null === $value ) {
$result['label'] = __( 'WP_CACHE is not set', 'rocket' );
$result['status'] = 'critical';
$result['badge']['color'] = 'red';
return $result;
}
if ( false === $value ) {
$result['label'] = __( 'WP_CACHE is set to false', 'rocket' );
$result['status'] = 'critical';
$result['badge']['color'] = 'red';
return $result;
}
return $result;
}
}