Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
# Conflicts:
#	phpstan-baseline.neon
  • Loading branch information
tillkruss committed Jan 11, 2023
2 parents 83ea358 + 29bc6dd commit 7e3a04a
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 88 deletions.
17 changes: 15 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ on: [push, pull_request]
jobs:

phpstan:
name: PHPStan (PHP ${{ matrix.php }})
name: PHPStan (PHP ${{ matrix.php }}; Relay ${{ matrix.relay }})
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0']
php: ['7.4', '8.2']
relay: ['0.5.1']

steps:
- name: Checkout
Expand All @@ -22,6 +23,18 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: msgpack, igbinary, mbstring, redis-5.3.7
coverage: none

- name: Install Relay PHP extension
run: |
curl -L "https://builds.r2.relay.so/v${{ matrix.relay }}/relay-v${{ matrix.relay }}-php${{ matrix.php }}-debian-x86-64.tar.gz" | tar xz
cd relay-v${{ matrix.relay }}-php${{ matrix.php }}-debian-x86-64/
sudo cp -v relay.ini $(php-config --ini-dir)
sudo cp -v relay-pkg.so $(php-config --extension-dir)/relay.so
sudo sed -i -e "s/00000000-0000-0000-0000-000000000000/$(cat /proc/sys/kernel/random/uuid)/" $(php-config --extension-dir)/relay.so
- name: Show Relay configuration
run: php --ri relay

- name: Install PHP Dependencies
uses: ramsey/composer-install@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:
fail-fast: false
matrix:
php: ['7.2', '7.3', '7.4', '8.0', '8.1']
redis: ['5.0.12', '6.2.1']
redis: ['6.2.8', '7.0.7']

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/.wp-test
/.phpunit.cache
/.php-tools
/vendor
/reports
/tests/PHPStan/object-cache.php
.phpunit.result.cache
composer.lock
config.sh
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 2.2.3

- Added `wp_cache_flush_group()` support
- Updated Credis to v1.14.0
- Drop `$delay` parameter from `wp_cache_flush()`
- Prevent rare error in diagnostics when reading connection errors

## 2.2.2

- Use `QM_Data_Cache` instead of `QM_Data`
Expand Down
12 changes: 5 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"yoast/wp-test-utils": "^1.0",
"dms/phpunit-arraysubset-asserts": "^0.4.0",
"szepeviktor/phpstan-wordpress": "^1.1",
"php-stubs/wp-cli-stubs": "^2.6"
"php-stubs/wp-cli-stubs": "^2.7"
},
"autoload-dev": {
"psr-4": {
Expand All @@ -53,17 +53,15 @@
},
"scripts": {
"stan": [
"@php -r \"is_dir('.php-tools') || mkdir('.php-tools');\"",
"@php -r \"file_exists('.php-tools/relay.stub.php') || system('curl https://cachewerk.s3.amazonaws.com/relay/dev/relay.stub.php -o ./.php-tools/relay.stub.php');\"",
"sed -e 's#WP_Object_Cache#Redis_Pro_WP_Object_Cache#;s#class Redis_Pro_WP_Object_Cache#& extends WP_Object_Cache#' includes/object-cache.php > .php-tools/object-cache.php",
"sed -e 's#WP_Object_Cache#Redis_Pro_WP_Object_Cache#;s#class Redis_Pro_WP_Object_Cache#& extends WP_Object_Cache#' includes/object-cache.php > tests/PHPStan/object-cache.php",
"phpstan analyze"
]
},
"config": {
"allow-plugins": {
"composer/installers": true,
"mnsami/composer-custom-directory-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
"composer/installers": true,
"mnsami/composer-custom-directory-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
2 changes: 1 addition & 1 deletion dependencies/colinmollenhour/credis/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -1587,7 +1587,7 @@ protected function decode_reply($name, $response, array &$arguments = array() )
*/
private static function _prepare_command($args)
{
return sprintf('*%d%s%s%s', count($args), CRLF, implode(CRLF, array_map(array('self', '_map'), $args)), CRLF);
return sprintf('*%d%s%s%s', count($args), CRLF, implode(CRLF, array_map([static::class, '_map'], $args)), CRLF);
}

private static function _map($arg)
Expand Down
1 change: 1 addition & 0 deletions includes/class-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ public function initialize_filesystem( $url, $silent = false ) {
* @return true|WP_Error
*/
public function test_filesystem_writing() {
/** @var \WP_Filesystem_Base $wp_filesystem */
global $wp_filesystem;

if ( ! $this->initialize_filesystem( '', true ) ) {
Expand Down
12 changes: 6 additions & 6 deletions includes/diagnostics.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@
$info[ 'Connection Exception' ] = sprintf( '%s (%s)', $exception->getMessage(), get_class( $exception ) );
}

$info[ 'Errors' ] = wp_json_encode(
array_values( $wp_object_cache->errors ),
JSON_PRETTY_PRINT
);
$errors = is_array( $wp_object_cache->errors ) ? $wp_object_cache->errors : [];
$info[ 'Errors' ] = wp_json_encode( array_values( $errors ), JSON_PRETTY_PRINT );
}

$info['PhpRedis'] = class_exists( 'Redis' ) ? phpversion( 'redis' ) : 'Not loaded';
Expand Down Expand Up @@ -87,6 +85,7 @@
'WP_REDIS_MAXTTL',
'WP_REDIS_PREFIX',
'WP_CACHE_KEY_SALT',
'WP_REDIS_PLUGIN_PATH',
'WP_REDIS_GLOBAL_GROUPS',
'WP_REDIS_IGNORED_GROUPS',
'WP_REDIS_UNFLUSHABLE_GROUPS',
Expand All @@ -103,15 +102,16 @@
}

if ( defined( 'WP_REDIS_PASSWORD' ) ) {
/** @var string|array|null $password */
$password = WP_REDIS_PASSWORD;

if ( is_array( $password ) ) {
if ( isset( $password[1] ) && ! is_null( $password[1] ) && '' !== $password[1] ) {
if ( isset( $password[1] ) && '' !== $password[1] ) {
$password[1] = str_repeat( '', 8 );
}

$info['WP_REDIS_PASSWORD'] = wp_json_encode( $password, JSON_UNESCAPED_UNICODE );
} elseif ( ! is_null( $password ) && '' !== $password ) {
} elseif ( is_string( $password ) && '' !== $password ) {
$info['WP_REDIS_PASSWORD'] = str_repeat( '', 8 );
}
}
Expand Down
120 changes: 100 additions & 20 deletions includes/object-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: Redis Object Cache Drop-In
* Plugin URI: https://wordpress.org/plugins/redis-cache/
* Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Relay, replication, sentinels, clustering and WP-CLI.
* Version: 2.2.2
* Version: 2.2.3
* Author: Till Krüss
* Author URI: https://objectcache.pro
* License: GPLv3
Expand Down Expand Up @@ -35,9 +35,9 @@ function wp_cache_supports( $feature ) {
case 'get_multiple':
case 'delete_multiple':
case 'flush_runtime':
case 'flush_group':
return true;

case 'flush_group':
default:
return false;
}
Expand Down Expand Up @@ -141,14 +141,25 @@ function wp_cache_delete_multiple( array $keys, $group = '' ) {
* Invalidate all items in the cache. If `WP_REDIS_SELECTIVE_FLUSH` is `true`,
* only keys prefixed with the `WP_REDIS_PREFIX` are flushed.
*
* @param int $delay Number of seconds to wait before invalidating the items.
*
* @return bool Returns TRUE on success or FALSE on failure.
*/
function wp_cache_flush( $delay = 0 ) {
function wp_cache_flush() {
global $wp_object_cache;

return $wp_object_cache->flush();
}

/**
* Removes all cache items in a group.
*
* @param string $group Name of group to remove from cache.
* @return true Returns TRUE on success or FALSE on failure.
*/
function wp_cache_flush_group( $group )
{
global $wp_object_cache;

return $wp_object_cache->flush( $delay );
return $wp_object_cache->flush_group( $group );
}

/**
Expand Down Expand Up @@ -397,7 +408,7 @@ class WP_Object_Cache {
/**
* List of global groups.
*
* @var array
* @var array<string>
*/
public $global_groups = [
'blog-details',
Expand Down Expand Up @@ -1533,16 +1544,9 @@ public function flush_runtime() {
* Invalidate all items in the cache. If `WP_REDIS_SELECTIVE_FLUSH` is `true`,
* only keys prefixed with the `WP_REDIS_PREFIX` are flushed.
*
* @param int $delay Number of seconds to wait before invalidating the items.
* @return bool Returns TRUE on success or FALSE on failure.
* @return bool True on success, false on failure.
*/
public function flush( $delay = 0 ) {
$delay = abs( (int) $delay );

if ( $delay ) {
sleep( $delay );
}

public function flush() {
$results = [];
$this->cache = [];

Expand Down Expand Up @@ -1607,12 +1611,12 @@ public function flush( $delay = 0 ) {
*
* @since 1.3.5
* @param null|array $results Array of flush results.
* @param int $delay Given number of seconds to waited before invalidating the items.
* @param int $deprecated Unused. Default 0.
* @param bool $seletive Whether a selective flush took place.
* @param string $salt The defined key prefix.
* @param float $execute_time Execution time for the request in seconds.
*/
do_action( 'redis_object_cache_flush', $results, $delay, $selective, $salt, $execute_time );
do_action( 'redis_object_cache_flush', $results, 0, $selective, $salt, $execute_time );
}
}

Expand All @@ -1629,6 +1633,81 @@ public function flush( $delay = 0 ) {
return true;
}

/**
* Removes all cache items in a group.
*
* @param string $group Name of group to remove from cache.
* @return bool Returns TRUE on success or FALSE on failure.
*/
public function flush_group( $group )
{
$san_group = $this->sanitize_key_part( $group );

if ( is_multisite() && ! $this->is_global_group( $san_group ) ) {
$salt = str_replace( "{$this->blog_prefix}:", '*:', $this->fast_build_key( '*', $san_group ) );
} else {
$salt = $this->fast_build_key( '*', $san_group );
}

foreach ( $this->cache as $key => $value ) {
if ( strpos( $key, "{$san_group}:" ) === 0 || strpos( $key, ":{$san_group}:" ) !== false ) {
unset( $this->cache[ $key ] );
}
}

if ( in_array( $san_group, $this->unflushable_groups ) ) {
return false;
}

if ( ! $this->redis_status() ) {
return false;
}

$results = [];

$start_time = microtime( true );
$script = $this->lua_flush_closure( $salt, false );

try {
if ( defined( 'WP_REDIS_CLUSTER' ) ) {
foreach ( $this->redis->_masters() as $master ) {
$redis = new Redis;
$redis->connect( $master[0], $master[1] );
$results[] = $this->parse_redis_response( $script() );
unset( $redis );
}
} else {
$results[] = $this->parse_redis_response( $script() );
}
} catch ( Exception $exception ) {
$this->handle_exception( $exception );

return false;
}

if ( function_exists( 'do_action' ) ) {
$execute_time = microtime( true ) - $start_time;

/**
* Fires on every group cache flush
*
* @param null|array $results Array of flush results.
* @param string $salt The defined key prefix.
* @param float $execute_time Execution time for the request in seconds.
* @since 2.2.3
*/
do_action( 'redis_object_cache_flush_group', $results, $salt, $execute_time );
}

foreach ( $results as $result ) {
if ( ! $result ) {
return false;
}
}

return true;
}

/**
* Returns a closure to flush selectively.
*
Expand Down Expand Up @@ -1668,10 +1747,11 @@ function ( $character ) {
* Returns a closure ready to be called to flush selectively ignoring unflushable groups.
*
* @param string $salt The salt to be used to differentiate.
* @param bool $escape ...
* @return callable Generated callable executing the lua script.
*/
protected function lua_flush_closure( $salt ) {
$salt = $this->glob_quote( $salt );
protected function lua_flush_closure( $salt, $escape = true ) {
$salt = $escape ? $this->glob_quote( $salt ) : $salt;

return function () use ( $salt ) {
$script = <<<LUA
Expand Down
Loading

0 comments on commit 7e3a04a

Please sign in to comment.