Plugin Directory

Changeset 3029656


Ignore:
Timestamp:
01/31/2024 04:43:55 PM (2 years ago)
Author:
spinupwp
Message:

--username

Location:
spinupwp/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • spinupwp/trunk/drop-ins/object-cache.php

    r2812614 r3029656  
    1010License URI: http://www.gnu.org/licenses/gpl-3.0.html
    1111
    12 Based on Till Krüss’ Redis Object Cache:
     12Based on Till Krüss’ Redis Object Cache v2.5.0:
    1313 - https://wordpress.org/plugins/redis-cache/
    1414 - https://github.com/rhubarbgroup/redis-cache/
     
    1717defined( '\\ABSPATH' ) || exit;
    1818
     19// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact, Generic.WhiteSpace.ScopeIndent.Incorrect
    1920if ( ! defined( 'WP_REDIS_DISABLED' ) || ! WP_REDIS_DISABLED ) :
     21
     22/**
     23 * Determines whether the object cache implementation supports a particular feature.
     24 *
     25 * Possible values include:
     26 *  - `add_multiple`, `set_multiple`, `get_multiple` and `delete_multiple`
     27 *  - `flush_runtime` and `flush_group`
     28 *
     29 * @param string $feature Name of the feature to check for.
     30 * @return bool True if the feature is supported, false otherwise.
     31 */
     32function wp_cache_supports( $feature ) {
     33    switch ( $feature ) {
     34        case 'add_multiple':
     35        case 'set_multiple':
     36        case 'get_multiple':
     37        case 'delete_multiple':
     38        case 'flush_runtime':
     39        case 'flush_group':
     40            return true;
     41
     42        default:
     43            return false;
     44    }
     45}
     46
    2047
    2148/**
     
    116143 * only keys prefixed with the `WP_REDIS_PREFIX` are flushed.
    117144 *
    118  * @param int $delay  Number of seconds to wait before invalidating the items.
    119  *
    120145 * @return bool       Returns TRUE on success or FALSE on failure.
    121146 */
    122 function wp_cache_flush( $delay = 0 ) {
     147function wp_cache_flush() {
    123148    global $wp_object_cache;
    124149
    125     return $wp_object_cache->flush( $delay );
     150    return $wp_object_cache->flush();
     151}
     152
     153/**
     154 * Removes all cache items in a group.
     155 *
     156 * @param string $group Name of group to remove from cache.
     157 * @return true Returns TRUE on success or FALSE on failure.
     158 */
     159function wp_cache_flush_group( $group )
     160{
     161    global $wp_object_cache;
     162
     163    return $wp_object_cache->flush_group( $group );
    126164}
    127165
     
    196234
    197235    if ( ! defined( 'WP_REDIS_PREFIX' ) ) {
    198         define( 'WP_REDIS_PREFIX', get_cache_key_salt());
     236        define( 'WP_REDIS_PREFIX', get_cache_key_salt());
    199237    }
    200238
     
    204242
    205243    if ( ! ( $wp_object_cache instanceof WP_Object_Cache ) ) {
    206         $fail_gracefully = ! defined( 'WP_REDIS_GRACEFUL' ) || WP_REDIS_GRACEFUL;
    207 
    208         // We need to override this WordPress global in order to inject our cache.
     244        $fail_gracefully = defined( 'WP_REDIS_GRACEFUL' ) && WP_REDIS_GRACEFUL;
     245
    209246        // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
    210247        $wp_object_cache = new WP_Object_Cache( $fail_gracefully );
     
    382419     * List of global groups.
    383420     *
    384      * @var array
     421     * @var array<string>
    385422     */
    386423    public $global_groups = [
     
    416453     * @var array
    417454     */
    418     public $ignored_groups = [
    419         'counts',
    420         'plugins',
    421         'themes',
    422     ];
     455    public $ignored_groups = [];
    423456
    424457    /**
     
    476509     * @param bool $fail_gracefully Handles and logs errors if true throws exceptions otherwise.
    477510     */
    478     public function __construct( $fail_gracefully = true ) {
     511    public function __construct( $fail_gracefully = false ) {
    479512        global $blog_id, $table_prefix;
    480513
     
    497530        $this->cache_group_types();
    498531
    499         if ( defined( 'WP_REDIS_TRACE' ) && WP_REDIS_TRACE && function_exists( '_doing_it_wrong' ) ) {
    500             _doing_it_wrong( __FUNCTION__ , 'Tracing feature was removed.' , '2.1.2' );
     532        if ( function_exists( '_doing_it_wrong' ) ) {
     533            if ( defined( 'WP_REDIS_TRACE' ) && WP_REDIS_TRACE ) {
     534                _doing_it_wrong( __FUNCTION__ , 'Tracing feature was removed.' , '2.1.2' );
     535            }
    501536        }
    502537
     
    525560
    526561            if ( defined( 'WP_REDIS_CLUSTER' ) ) {
    527                 $connectionID = is_string( WP_REDIS_CLUSTER )
     562                $connectionId = is_string( WP_REDIS_CLUSTER )
    528563                    ? WP_REDIS_CLUSTER
    529564                    : current( $this->build_cluster_connection_array() );
    530565
    531566                $this->diagnostics[ 'ping' ] = $client === 'predis'
    532                     ? $this->redis->getClientFor( $connectionID )->ping()
    533                     : $this->redis->ping( $connectionID );
     567                    ? $this->redis->getClientBy( 'id', $connectionId )->ping()
     568                    : $this->redis->ping( $connectionId );
    534569            } else {
    535570                $this->diagnostics[ 'ping' ] = $this->redis->ping();
     
    600635            'port' => 6379,
    601636            'database' => 0,
    602             'timeout' => 1,
    603             'read_timeout' => 1,
     637            'timeout' => 5,
     638            'read_timeout' => 5,
    604639            'retry_interval' => null,
    605640            'persistent' => false,
     
    677712            ];
    678713
     714            if ( version_compare( $version, '3.1.3', '>=' ) ) {
     715                $args['read_timeout'] = $parameters['read_timeout'];
     716            }
     717
    679718            if ( strcasecmp( 'tls', $parameters['scheme'] ) === 0 ) {
    680719                $args['host'] = sprintf(
     
    683722                    str_replace( 'tls://', '', $parameters['host'] )
    684723                );
     724
     725                if ( version_compare( $version, '5.3.0', '>=' ) && defined( 'WP_REDIS_SSL_CONTEXT' ) && ! empty( WP_REDIS_SSL_CONTEXT ) ) {
     726                    $args['others']['stream'] = WP_REDIS_SSL_CONTEXT;
     727                }
    685728            }
    686729
     
    688731                $args['host'] = $parameters['path'];
    689732                $args['port'] = -1;
    690             }
    691 
    692             if ( version_compare( $version, '3.1.3', '>=' ) ) {
    693                 $args['read_timeout'] = $parameters['read_timeout'];
    694733            }
    695734
     
    718757        if ( defined( 'WP_REDIS_SERIALIZER' ) && ! empty( WP_REDIS_SERIALIZER ) ) {
    719758            $this->redis->setOption( Redis::OPT_SERIALIZER, WP_REDIS_SERIALIZER );
     759
     760            if ( function_exists( '_doing_it_wrong' ) ) {
     761                _doing_it_wrong( __FUNCTION__ , 'The `WP_REDIS_SERIALIZER` configuration constant has been deprecated, use `WP_REDIS_IGBINARY` instead.', '2.3.1' );
     762            }
    720763        }
    721764    }
     
    747790            ];
    748791
     792            $args['read_timeout'] = $parameters['read_timeout'];
     793
    749794            if ( strcasecmp( 'tls', $parameters['scheme'] ) === 0 ) {
    750795                $args['host'] = sprintf(
     
    753798                    str_replace( 'tls://', '', $parameters['host'] )
    754799                );
     800
     801                if ( defined( 'WP_REDIS_SSL_CONTEXT' ) && ! empty( WP_REDIS_SSL_CONTEXT ) ) {
     802                    $args['others']['stream'] = WP_REDIS_SSL_CONTEXT;
     803                }
    755804            }
    756805
     
    759808                $args['port'] = -1;
    760809            }
    761 
    762             $args['read_timeout'] = $parameters['read_timeout'];
    763810
    764811            call_user_func_array( [ $this->redis, 'connect' ], array_values( $args ) );
     
    786833        if ( defined( 'WP_REDIS_SERIALIZER' ) && ! empty( WP_REDIS_SERIALIZER ) ) {
    787834            $this->redis->setOption( Relay\Relay::OPT_SERIALIZER, WP_REDIS_SERIALIZER );
     835
     836            if ( function_exists( '_doing_it_wrong' ) ) {
     837                _doing_it_wrong( __FUNCTION__ , 'The `WP_REDIS_SERIALIZER` configuration constant has been deprecated, use `WP_REDIS_IGBINARY` instead.', '2.3.1' );
     838            }
    788839        }
    789840    }
     
    801852        // Load bundled Predis library.
    802853        if ( ! class_exists( 'Predis\Client' ) ) {
    803             $predis = sprintf(
    804                 '%s/redis-cache/dependencies/predis/predis/autoload.php',
    805                 defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins'
    806             );
    807 
    808             if ( is_readable( $predis ) ) {
    809                 require_once $predis;
     854            $predis = '/dependencies/predis/predis/autoload.php';
     855
     856            $pluginDir = defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR . '/redis-cache' : null;
     857            $contentDir = defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR . '/plugins/redis-cache' : null;
     858            $pluginPath = defined( 'WP_REDIS_PLUGIN_PATH' ) ? WP_REDIS_PLUGIN_PATH : null;
     859
     860            if ( $pluginDir && is_readable( $pluginDir . $predis ) ) {
     861                require_once $pluginDir . $predis;
     862            } elseif ( $contentDir && is_readable( $contentDir . $predis ) ) {
     863                require_once $contentDir . $predis;
     864            } elseif ( $pluginPath && is_readable( $pluginPath . $predis ) ) {
     865                require_once $pluginPath . $predis;
    810866            } else {
    811867                throw new Exception(
     
    836892        }
    837893
     894        if ( strcasecmp( 'unix', $parameters['scheme'] ) === 0 ) {
     895            unset($parameters['host'], $parameters['port']);
     896        }
     897
    838898        if ( isset( $parameters['read_timeout'] ) && $parameters['read_timeout'] ) {
    839899            $parameters['read_write_timeout'] = $parameters['read_timeout'];
     
    847907
    848908                if ( isset( $parameters['password'] ) ) {
    849                     $options['parameters']['password'] = WP_REDIS_PASSWORD;
     909                    if ( is_array( $parameters['password'] ) ) {
     910                        $options['parameters']['username'] = WP_REDIS_PASSWORD[0];
     911                        $options['parameters']['password'] = WP_REDIS_PASSWORD[1];
     912                    } else {
     913                        $options['parameters']['password'] = WP_REDIS_PASSWORD;
     914                    }
    850915                }
    851916            }
     917        }
     918
     919        if ( isset( $parameters['password'] ) ) {
     920            if ( is_array( $parameters['password'] ) ) {
     921                $parameters['username'] = array_shift( $parameters['password'] );
     922                $parameters['password'] = implode( '', $parameters['password'] );
     923            }
     924
     925            if ( defined( 'WP_REDIS_USERNAME' ) ) {
     926                $parameters['username'] = WP_REDIS_USERNAME;
     927            }
     928        }
     929
     930        if ( defined( 'WP_REDIS_SSL_CONTEXT' ) && ! empty( WP_REDIS_SSL_CONTEXT ) ) {
     931            $parameters['ssl'] = WP_REDIS_SSL_CONTEXT;
    852932        }
    853933
     
    9211001            if ( is_array( WP_REDIS_SERVERS ) && count( WP_REDIS_SERVERS ) > 1 ) {
    9221002                throw new Exception(
    923                     'Multipe sentinel servers are not supported by the bundled Credis library. Please review your Redis Cache configuration.'
     1003                    'Multiple sentinel servers are not supported by the bundled Credis library. Please review your Redis Cache configuration.'
    9241004                );
    9251005            }
     
    10681148
    10691149        if ( defined( 'WP_REDIS_CLUSTER' ) ) {
    1070             $connectionID = is_string( WP_REDIS_CLUSTER )
     1150            $connectionId = is_string( WP_REDIS_CLUSTER )
    10711151                ? 'SERVER'
    10721152                : current( $this->build_cluster_connection_array() );
    10731153
    10741154            $info = $this->determine_client() === 'predis'
    1075                 ? $this->redis->getClientFor( $connectionID )->info()
    1076                 : $this->redis->info( $connectionID );
     1155                ? $this->redis->getClientBy( 'id', $connectionId )->info()
     1156                : $this->redis->info( $connectionId );
    10771157        } else {
    10781158            $info = $this->redis->info();
     
    11811261        $orig_exp = $expire;
    11821262        $expire = $this->validate_expiration( $expire );
     1263        $derived_keys = [];
    11831264
    11841265        foreach ( $data as $key => $value ) {
     
    12241305                return (bool) $this->parse_redis_response( $response );
    12251306            }, $tx->{$method}() );
     1307
     1308            if ( count( $results ) !== count( $keys ) ) {
     1309                $tx->discard();
     1310
     1311                return array_fill_keys( $keys, false );
     1312            }
    12261313
    12271314            $results = array_combine( $keys, $results );
     
    13711458     * @return  bool               Returns TRUE on success or FALSE on failure.
    13721459     */
    1373     public function delete( $key, $group = 'default' ) {
     1460    public function delete( $key, $group = 'default', $deprecated = false ) {
    13741461        $result = false;
    13751462
     
    14691556                return (bool) $this->parse_redis_response( $response );
    14701557            }, $tx->{$method}() );
     1558
     1559            if ( count( $results ) !== count( $keys ) ) {
     1560                $tx->discard();
     1561
     1562                return array_fill_keys( $keys, false );
     1563            }
    14711564
    14721565            $execute_time = microtime( true ) - $start_time;
     
    15091602     * only keys prefixed with the `WP_REDIS_PREFIX` are flushed.
    15101603     *
    1511      * @param   int $delay      Number of seconds to wait before invalidating the items.
    1512      * @return  bool            Returns TRUE on success or FALSE on failure.
    1513      */
    1514     public function flush( $delay = 0 ) {
    1515         $delay = abs( (int) $delay );
    1516 
    1517         if ( $delay ) {
    1518             sleep( $delay );
    1519         }
    1520 
     1604     * @return bool True on success, false on failure.
     1605     */
     1606    public function flush() {
    15211607        $results = [];
    15221608        $this->cache = [];
     
    15831669                 * @since 1.3.5
    15841670                 * @param null|array $results      Array of flush results.
    1585                  * @param int        $delay        Given number of seconds to waited before invalidating the items.
     1671                 * @param int        $deprecated   Unused. Default 0.
    15861672                 * @param bool       $seletive     Whether a selective flush took place.
    15871673                 * @param string     $salt         The defined key prefix.
    15881674                 * @param float      $execute_time Execution time for the request in seconds.
    15891675                 */
    1590                 do_action( 'redis_object_cache_flush', $results, $delay, $selective, $salt, $execute_time );
     1676                do_action( 'redis_object_cache_flush', $results, 0, $selective, $salt, $execute_time );
    15911677            }
    15921678        }
     
    15941680        if ( empty( $results ) ) {
    15951681            return false;
     1682        }
     1683
     1684        foreach ( $results as $result ) {
     1685            if ( ! $result ) {
     1686                return false;
     1687            }
     1688        }
     1689
     1690        return true;
     1691    }
     1692
     1693    /**
     1694     * Removes all cache items in a group.
     1695     *
     1696     * @param string $group Name of group to remove from cache.
     1697     * @return bool Returns TRUE on success or FALSE on failure.
     1698     */
     1699    public function flush_group( $group )
     1700    {
     1701        $san_group = $this->sanitize_key_part( $group );
     1702
     1703        if ( is_multisite() && ! $this->is_global_group( $san_group ) ) {
     1704            $salt = str_replace( "{$this->blog_prefix}:{$san_group}", "*:{$san_group}", $this->fast_build_key( '*', $san_group ) );
     1705        } else {
     1706            $salt = $this->fast_build_key( '*', $san_group );
     1707        }
     1708
     1709        foreach ( $this->cache as $key => $value ) {
     1710            if ( strpos( $key, "{$san_group}:" ) === 0 || strpos( $key, ":{$san_group}:" ) !== false ) {
     1711                unset( $this->cache[ $key ] );
     1712            }
     1713        }
     1714
     1715        if ( in_array( $san_group, $this->unflushable_groups ) ) {
     1716            return false;
     1717        }
     1718
     1719        if ( ! $this->redis_status() ) {
     1720            return false;
     1721        }
     1722
     1723        $results = [];
     1724
     1725        $start_time = microtime( true );
     1726        $script = $this->lua_flush_closure( $salt, false );
     1727
     1728        try {
     1729            if ( defined( 'WP_REDIS_CLUSTER' ) ) {
     1730                foreach ( $this->redis->_masters() as $master ) {
     1731                    $redis = new Redis;
     1732                    $redis->connect( $master[0], $master[1] );
     1733                    $results[] = $this->parse_redis_response( $script() );
     1734                    unset( $redis );
     1735                }
     1736            } else {
     1737                $results[] = $this->parse_redis_response( $script() );
     1738            }
     1739        } catch ( Exception $exception ) {
     1740            $this->handle_exception( $exception );
     1741
     1742            return false;
     1743        }
     1744
     1745        if ( function_exists( 'do_action' ) ) {
     1746            $execute_time = microtime( true ) - $start_time;
     1747
     1748            /**
     1749             * Fires on every group cache flush
     1750             *
     1751             * @param null|array $results Array of flush results.
     1752             * @param string $salt The defined key prefix.
     1753             * @param float $execute_time Execution time for the request in seconds.
     1754             * @since 2.2.3
     1755             */
     1756            do_action( 'redis_object_cache_flush_group', $results, $salt, $execute_time );
    15961757        }
    15971758
     
    16441805     *
    16451806     * @param   string $salt  The salt to be used to differentiate.
     1807     * @param   bool $escape ...
    16461808     * @return  callable      Generated callable executing the lua script.
    16471809     */
    1648     protected function lua_flush_closure( $salt ) {
    1649         $salt = $this->glob_quote( $salt );
     1810    protected function lua_flush_closure( $salt, $escape = true ) {
     1811        $salt = $escape ? $this->glob_quote( $salt ) : $salt;
    16501812
    16511813        return function () use ( $salt ) {
    16521814            $script = <<<LUA
    1653             local cur = 0
    1654             local i = 0
    1655             local tmp
    1656             repeat
    1657                 tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
    1658                 cur = tonumber(tmp[1])
    1659                 if tmp[2] then
    1660                     for _, v in pairs(tmp[2]) do
    1661                         redis.call('del', v)
    1662                         i = i + 1
     1815                local cur = 0
     1816                local i = 0
     1817                local tmp
     1818                repeat
     1819                    tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
     1820                    cur = tonumber(tmp[1])
     1821                    if tmp[2] then
     1822                        for _, v in pairs(tmp[2]) do
     1823                            redis.call('del', v)
     1824                            i = i + 1
     1825                        end
    16631826                    end
    1664                 end
    1665             until 0 == cur
    1666             return i
     1827                until 0 == cur
     1828                return i
    16671829LUA;
    16681830
     
    16971859
    16981860            $script = <<<LUA
    1699             local cur = 0
    1700             local i = 0
    1701             local d, tmp
    1702             repeat
    1703                 tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
    1704                 cur = tonumber(tmp[1])
    1705                 if tmp[2] then
    1706                     for _, v in pairs(tmp[2]) do
    1707                         d = true
    1708                         for _, s in pairs(KEYS) do
    1709                             d = d and not v:find(s, {$salt_length})
    1710                             if not d then break end
    1711                         end
    1712                         if d then
    1713                             redis.call('del', v)
    1714                             i = i + 1
     1861                local cur = 0
     1862                local i = 0
     1863                local d, tmp
     1864                repeat
     1865                    tmp = redis.call('SCAN', cur, 'MATCH', '{$salt}*')
     1866                    cur = tonumber(tmp[1])
     1867                    if tmp[2] then
     1868                        for _, v in pairs(tmp[2]) do
     1869                            d = true
     1870                            for _, s in pairs(KEYS) do
     1871                                d = d and not v:find(s, {$salt_length})
     1872                                if not d then break end
     1873                            end
     1874                            if d then
     1875                                redis.call('del', v)
     1876                                i = i + 1
     1877                            end
    17151878                        end
    17161879                    end
    1717                 end
    1718             until 0 == cur
    1719             return i
     1880                until 0 == cur
     1881                return i
    17201882LUA;
    17211883            if ( version_compare( $this->redis_version(), '5', '<' ) && version_compare( $this->redis_version(), '3.2', '>=' ) ) {
     
    17451907     */
    17461908    public function get( $key, $group = 'default', $force = false, &$found = null ) {
    1747         $start_time = microtime( true );
    1748 
    17491909        $san_key = $this->sanitize_key_part( $key );
    17501910        $san_group = $this->sanitize_key_part( $group );
     
    17631923            return false;
    17641924        }
     1925
     1926        $start_time = microtime( true );
    17651927
    17661928        try {
     
    21192281            }, $tx->{$method}() );
    21202282
     2283            if ( count( $results ) !== count( $keys ) ) {
     2284                $tx->discard();
     2285
     2286                return array_fill_keys( $keys, false );
     2287            }
     2288
    21212289            $results = array_combine( $keys, $results );
    21222290
     
    22772445    public function stats() {
    22782446        ?>
    2279         <p>
    2280             <strong>Redis Status:</strong>
    2281             <?php echo $this->redis_status() ? 'Connected' : 'Not connected'; ?>
    2282             <br />
    2283             <strong>Redis Client:</strong>
    2284             <?php echo $this->diagnostics['client'] ?: 'Unknown'; ?>
    2285             <br />
    2286             <strong>Cache Hits:</strong>
    2287             <?php echo (int) $this->cache_hits; ?>
    2288             <br />
    2289             <strong>Cache Misses:</strong>
    2290             <?php echo (int) $this->cache_misses; ?>
    2291             <br />
    2292             <strong>Cache Size:</strong>
    2293             <?php echo number_format( strlen( serialize( $this->cache ) ) / 1024, 2 ); ?> KB
    2294         </p>
     2447    <p>
     2448        <strong>Redis Status:</strong>
     2449        <?php echo $this->redis_status() ? 'Connected' : 'Not connected'; ?>
     2450        <br />
     2451        <strong>Redis Client:</strong>
     2452        <?php echo $this->diagnostics['client'] ?: 'Unknown'; ?>
     2453        <br />
     2454        <strong>Cache Hits:</strong>
     2455        <?php echo (int) $this->cache_hits; ?>
     2456        <br />
     2457        <strong>Cache Misses:</strong>
     2458        <?php echo (int) $this->cache_misses; ?>
     2459        <br />
     2460        <strong>Cache Size:</strong>
     2461        <?php echo number_format_i18n( strlen( serialize( $this->cache ) ) / 1024, 2 ); ?> KB
     2462    </p>
    22952463        <?php
    22962464    }
     
    26842852                    return false;
    26852853                }
    2686             // Or else fall through.
    2687             // No break!
     2854                // Or else fall through.
     2855                // No break!
    26882856            case 'a':
    26892857            case 'O':
     
    27132881        $this->ignored_groups = array_unique( array_merge( $this->ignored_groups, $this->global_groups ) );
    27142882
    2715         if ( ! $this->fail_gracefully ) {
    2716             throw $exception;
    2717         }
    2718 
    2719         $this->errors[] = $exception->getMessage();
    2720 
    27212883        error_log( $exception ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
    27222884
    27232885        if ( function_exists( 'do_action' ) ) {
    27242886            /**
    2725              * Fires on every cache error
     2887             * Fires when an object cache related error occurs.
    27262888             *
    27272889             * @since 1.5.0
    2728              * @param \Exception $exception The exception triggered.
     2890             * @param \Exception $exception The exception.
     2891             * @param string     $message   The exception message.
    27292892             */
    2730             do_action( 'redis_object_cache_error', $exception );
    2731         }
     2893            do_action( 'redis_object_cache_error', $exception, $exception->getMessage() );
     2894        }
     2895
     2896        if ( ! $this->fail_gracefully ) {
     2897            $this->show_error_and_die( $exception );
     2898        }
     2899
     2900        $this->errors[] = $exception->getMessage();
     2901    }
     2902
     2903    /**
     2904     * Show Redis connection error screen, or load custom `/redis-error.php`.
     2905     *
     2906     * @return void
     2907     */
     2908    protected function show_error_and_die( Exception $exception ) {
     2909        wp_load_translations_early();
     2910
     2911        add_filter( 'pre_determine_locale', function () {
     2912            return defined( 'WPLANG' ) ? WPLANG : 'en_US';
     2913        } );
     2914
     2915        // Load custom DB error template, if present.
     2916        if ( file_exists( WP_CONTENT_DIR . '/redis-error.php' ) ) {
     2917            require_once WP_CONTENT_DIR . '/redis-error.php';
     2918            die();
     2919        }
     2920
     2921        $verbose = wp_installing()
     2922            || defined( 'WP_ADMIN' )
     2923            || ( defined( 'WP_DEBUG' ) && WP_DEBUG );
     2924
     2925        $message = '<h1>' . __( 'Error establishing a Redis connection', 'redis-cache' ) . "</h1>\n";
     2926
     2927        if ( $verbose ) {
     2928            $message .= "<p><code>" . $exception->getMessage() . "</code></p>\n";
     2929
     2930            $message .= '<p>' . sprintf(
     2931                // translators: %s = Formatted wp-config.php file name.
     2932                __( 'WordPress is unable to establish a connection to Redis. This means that the connection information in your %s file are incorrect, or that the Redis server is not reachable.', 'redis-cache' ),
     2933                '<code>wp-config.php</code>'
     2934            ) . "</p>\n";
     2935
     2936            $message .= "<ul>\n";
     2937            $message .= '<li>' . __( 'Is the correct Redis host and port set?', 'redis-cache' ) . "</li>\n";
     2938            $message .= '<li>' . __( 'Is the Redis server running?', 'redis-cache' ) . "</li>\n";
     2939            $message .= "</ul>\n";
     2940
     2941            $message .= '<p>' . sprintf(
     2942                // translators: %s = Link to installation instructions.
     2943                __( 'If you need help, please read the <a href="%s">installation instructions</a>.', 'redis-cache' ),
     2944                'https://github.com/rhubarbgroup/redis-cache/blob/develop/INSTALL.md'
     2945            ) . "</p>\n";
     2946        }
     2947
     2948        $message .= '<p>' . sprintf(
     2949            // translators: %1$s = Formatted object-cache.php file name, %2$s = Formatted wp-content directory name.
     2950            __( 'To disable Redis, delete the %1$s file in the %2$s directory.', 'redis-cache' ),
     2951            '<code>object-cache.php</code>',
     2952            '<code>/wp-content/</code>'
     2953        ) . "</p>\n";
     2954
     2955        wp_die( $message );
    27322956    }
    27332957
  • spinupwp/trunk/readme.txt

    r2812614 r3029656  
    33Tags: cache, caching, performance
    44Requires at least: 4.7
    5 Tested up to: 6.1
     5Tested up to: 6.4
    66Requires PHP: 7.1
    7 Stable tag: 1.5.1
     7Stable tag: 1.6
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    8787== Changelog ==
    8888
     89= 1.6 (2024-01-31) =
     90* New: Add "Purge this URL" option to our Cache menu in the WordPress nav bar.
     91* New: Cache key customization. /props quimcastella
     92* Improvement: Increase default cache purge timeout limit from 1 to 5 seconds.
     93* Improvement: PHP 8.1 compatibility. /props afragen
     94* Bug Fix: Page cache not cleared when clearing object cache fails.
     95
    8996= 1.5.1 (2022-11-05) =
    9097* Ensure SpinupWP page caching is correctly detected in Site Health
  • spinupwp/trunk/src/Cache.php

    r2774192 r3029656  
    5252        }
    5353
     54        if ( $this->is_page_cache_enabled() && ! is_admin() ) {
     55            $this->admin_bar->add_item( __( 'Purge this URL', 'spinupwp' ), 'purge-url' );
     56        }
     57
    5458        add_action( 'spinupwp_purge_object_cache', array( $this, 'purge_object_cache' ) );
    5559        add_action( 'spinupwp_purge_page_cache', array( $this, 'purge_page_cache' ) );
     60        add_action( 'spinupwp_purge_url', array( $this, 'purge_url' ) );
    5661        add_action( 'admin_init', array( $this, 'handle_manual_purge_action' ) );
    5762        add_action( 'transition_post_status', array( $this, 'purge_post_on_update' ), 10, 3 );
     
    7479        $action = filter_input( INPUT_GET, 'spinupwp_action' );
    7580
    76         if ( ! $action || ! in_array( $action, array( 'purge-all', 'purge-object', 'purge-page' ) ) ) {
     81        if ( ! $action || ! in_array( $action, array( 'purge-all', 'purge-object', 'purge-page', 'purge-url' ) ) ) {
    7782            return;
    7883        }
     
    8388
    8489        if ( 'purge-all' === $action ) {
    85             $purge = $this->purge_object_cache() && $this->purge_page_cache();
     90            $purge_object_cache = $this->purge_object_cache();
     91            $purge_page_cache = $this->purge_page_cache();
     92           
     93            $purge = $purge_object_cache && $purge_page_cache;
    8694            $type  = 'all';
    8795        }
     
    95103            $purge = $this->purge_page_cache();
    96104            $type  = 'page';
     105        }
     106       
     107        if ( 'purge-url' === $action ) {
     108            $url = $_SERVER['HTTP_REFERER'];
     109            $purge = $this->purge_url($url);
     110            $type  = 'url';
    97111        }
    98112
     
    288302     */
    289303    public function purge_url( $url ) {
    290         $path   = $this->get_cache_path_for_url( $url );
    291         $result = $this->delete( $path );
    292 
    293         do_action( 'spinupwp_url_purged', $url, $result );
    294 
    295         return $result;
    296     }
    297 
    298     /**
    299      * Get's the cache file path for a given URL.
    300      *
     304        $cache_paths = $this->get_cache_paths_for_url( $url );
     305       
     306        $all_deleted = true;
     307        foreach ($cache_paths as $path) {
     308            $deleted =  $this->delete( $path );
     309            do_action( 'spinupwp_url_purged', $url, $deleted );
     310            $all_deleted &= $deleted;
     311        }
     312       
     313        return $all_deleted;
     314    }
     315
     316    /**
     317     * Gets the cache file paths for a given URL.
     318     *
    301319     * Must be using the default Nginx cache options (levels=1:2)
    302      * and (fastcgi_cache_key "$scheme$request_method$host$request_uri").
    303320     * https://www.digitalocean.com/community/tutorials/how-to-setup-fastcgi-caching-with-nginx-on-your-vps#purging-the-cache
    304321     *
    305322     * @param string $url
    306323     *
    307      * @return string
    308      */
    309     private function get_cache_path_for_url( $url ) {
     324     * @return array
     325     */
     326    private function get_cache_paths_for_url( $url ) {
     327        $cache_keys = $this->get_cache_keys_for_url( $url );
     328       
     329        $cache_paths = array();
     330        foreach ($cache_keys as $key) {
     331            $hashed_key = md5($key);
     332            $path = substr( $hashed_key, - 1 ) . '/' . substr( $hashed_key, - 3, 2 ) . '/' . $hashed_key;
     333            $cache_paths[] = trailingslashit( $this->cache_path ) . $path;
     334        }
     335       
     336        return $cache_paths;
     337    }
     338
     339    /**
     340     * Gets the cache keys for a given URL.
     341     *
     342     * It defaults to a single key: (fastcgi_cache_key "$scheme$request_method$host$request_uri"),
     343     * but it can be modified with spinupwp_cache_key_components filter.
     344     * This must match the Nginx configuration.
     345     *
     346     * @param string $url
     347     *
     348     * @return array
     349     */
     350    private function get_cache_keys_for_url( $url ) {
     351        // Default cache key
    310352        $parsed_url = parse_url( trailingslashit( $url ) );
    311         $cache_key  = md5( $parsed_url['scheme'] . 'GET' . $parsed_url['host'] . $parsed_url['path'] );
    312         $cache_path = substr( $cache_key, - 1 ) . '/' . substr( $cache_key, - 3, 2 ) . '/' . $cache_key;
    313 
    314         return trailingslashit( $this->cache_path ) . $cache_path;
     353        $cache_keys = array($parsed_url['scheme'] . 'GET' . $parsed_url['host'] . $parsed_url['path']);
     354
     355        // Allow the cache keys to be modified
     356        $cache_keys = apply_filters('spinupwp_cache_keys_for_url', $cache_keys, $url);
     357       
     358        return $cache_keys;
    315359    }
    316360
     
    324368     */
    325369    private function delete( $path, $recursive = false ) {
    326         if ( file_exists( $path ) && is_writable( $path ) ) {
     370        if ( null !== $path && file_exists( $path ) && is_writable( $path ) ) {
    327371            require_once( ABSPATH . '/wp-admin/includes/file.php' );
    328372
Note: See TracChangeset for help on using the changeset viewer.