From 006f4c043eb2def1d4c0a2d7b5a6b8253f377579 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 00:37:11 +0000 Subject: [PATCH 1/6] No static methods --- src/wp-admin/edit-form-blocks.php | 4 +- src/wp-admin/site-editor.php | 6 +- src/wp-content/object-cache00.php | 2341 +++++++++++++++++ src/wp-includes/block-editor.php | 3 +- src/wp-includes/block-patterns.php | 5 +- src/wp-includes/block-supports/layout.php | 6 +- src/wp-includes/block-template-utils.php | 15 +- .../class-wp-theme-json-resolver.php | 284 +- .../global-styles-and-settings.php | 19 +- ...class-wp-rest-global-styles-controller.php | 6 +- .../class-wp-rest-themes-controller.php | 5 +- src/wp-includes/script-loader.php | 15 +- src/wp-includes/theme-templates.php | 3 +- src/wp-settings.php | 8 + 14 files changed, 2553 insertions(+), 167 deletions(-) create mode 100644 src/wp-content/object-cache00.php diff --git a/src/wp-admin/edit-form-blocks.php b/src/wp-admin/edit-form-blocks.php index f43c835168c1d..b0c3f41846511 100644 --- a/src/wp-admin/edit-form-blocks.php +++ b/src/wp-admin/edit-form-blocks.php @@ -20,7 +20,7 @@ * @global string $title * @global array $wp_meta_boxes */ -global $post_type, $post_type_object, $post, $title, $wp_meta_boxes; +global $post_type, $post_type_object, $post, $title, $wp_meta_boxes, $wp_theme_json_resolver; $block_editor_context = new WP_Block_Editor_Context( array( 'post' => $post ) ); @@ -203,7 +203,7 @@ static function( $classes ) { 'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), ), - 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), + 'supportsLayout' => $wp_theme_json_resolver->theme_has_support(), 'supportsTemplateMode' => current_theme_supports( 'block-templates' ), // Whether or not to load the 'postcustom' meta box is stored as a user meta diff --git a/src/wp-admin/site-editor.php b/src/wp-admin/site-editor.php index 64ed4b9c27cad..d97bce333163c 100644 --- a/src/wp-admin/site-editor.php +++ b/src/wp-admin/site-editor.php @@ -6,7 +6,7 @@ * @subpackage Administration */ -global $editor_styles; +global $editor_styles, $wp_theme_json_resolver; /** WordPress Administration Bootstrap */ require_once __DIR__ . '/admin.php'; @@ -74,7 +74,7 @@ static function( $classes ) { 'styles' => get_block_editor_theme_styles(), 'defaultTemplateTypes' => $indexed_template_types, 'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(), - 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), + 'supportsLayout' => $wp_theme_json_resolver->theme_has_support(), 'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ), '__unstableHomeTemplate' => $home_template, ); @@ -100,7 +100,7 @@ static function( $classes ) { } } -$active_global_styles_id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); +$active_global_styles_id = $wp_theme_json_resolver->get_user_global_styles_post_id(); $active_theme = wp_get_theme()->get_stylesheet(); $preload_paths = array( array( '/wp/v2/media', 'OPTIONS' ), diff --git a/src/wp-content/object-cache00.php b/src/wp-content/object-cache00.php new file mode 100644 index 0000000000000..c1fe9755a66e3 --- /dev/null +++ b/src/wp-content/object-cache00.php @@ -0,0 +1,2341 @@ +add( $key, $value, $group, $expiration ); +} + +/** + * Adds a value to cache on a specific server. + * + * Using a server_key value, the object can be stored on a specified server as opposed + * to a random server in the stack. Note that this method will add the key/value to the + * _cache object as part of the runtime cache. It will add it to an array for the + * specified server_key. + * + * @link https://www.php.net/manual/en/memcached.addbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_add_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->addByKey( $server_key, $key, $value, $group, $expiration ); +} + +/** + * Adds multiple values to the cache in one call, if the cache keys don't already exist. + * + * @param array $items Array of keys and values to be added. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expiration Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if cache key and group already exist. + */ +function wp_cache_add_multiple( array $items, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->addMultiple( $items, $group, $expiration ); +} + +/** + * Adds a single server to the list of Memcached servers. + * + * @link https://www.php.net/manual/en/memcached.addserver.php + * + * @param string $host The hostname of the memcache server. + * @param int $port The port on which memcache is running. + * @param int $weight The weight of the server relative to the total weight + * of all the servers in the pool. + * @return bool True on success, false on failure. + */ +function wp_cache_add_server( $host, $port, $weight = 0 ) { + global $wp_object_cache; + return $wp_object_cache->addServer( $host, $port, $weight ); +} + +/** + * Adds an array of servers to the pool. + * + * Each individual server in the array must include a domain and port, with an optional + * weight value: $servers = array( array( '127.0.0.1', 11211, 0 ) ); + * + * @link https://www.php.net/manual/en/memcached.addservers.php + * + * @param array $servers Array of server to register. + * @return bool True on success, false on failure. + */ +function wp_cache_add_servers( $servers ) { + global $wp_object_cache; + return $wp_object_cache->addServers( $servers ); +} + +/** + * Appends data to an existing item. + * + * This method should throw an error if it is used with compressed data. + * This is an expected behavior. Memcached casts the value to be appended to the initial value + * to the type of the initial value. Be careful as this leads to unexpected behavior at times. + * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce + * similar results and improve consistency. It is recommended that appends only occur with data of + * the same type. + * + * @link https://www.php.net/manual/en/memcached.append.php + * + * @param string $key The key under which to store the value. + * @param mixed $value Must be string as appending mixed values is not well-defined. + * @param string $group The group value appended to the $key. + * @return bool True on success, false on failure. + */ +function wp_cache_append( $key, $value, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->append( $key, $value, $group ); +} + +/** + * Appends data to an existing item by server key. + * + * This method should throw an error if it is used with compressed data. + * This is an expected behavior. Memcached casts the value to be appended to the initial value + * to the type of the initial value. Be careful as this leads to unexpected behavior at times. + * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce + * similar results and improve consistency. It is recommended that appends only occur with data of + * the same type. + * + * @link https://www.php.net/manual/en/memcached.appendbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value Must be string as appending mixed values is not well-defined. + * @param string $group The group value appended to the $key. + * @return bool True on success, false on failure. + */ +function wp_cache_append_by_key( $server_key, $key, $value, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->appendByKey( $server_key, $key, $value, $group ); +} + +/** + * Performs a "check and set" to store data. + * + * The set will be successful only if the no other request has updated the value + * since it was fetched by this request. + * + * @link https://www.php.net/manual/en/memcached.cas.php + * + * @param float $cas_token Unique value associated with the existing item. Generated by memcached. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_cas( $cas_token, $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->cas( $cas_token, $key, $value, $group, $expiration ); +} + +/** + * Performs a "check and set" to store data with a server key. + * + * The set will be successful only if the no other request has updated the value + * since it was fetched by this request. + * + * @link https://www.php.net/manual/en/memcached.casbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param float $cas_token Unique value associated with the existing item. Generated by memcached. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_cas_by_key( $cas_token, $server_key, $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->casByKey( $cas_token, $server_key, $key, $value, $group, $expiration ); +} + +/** + * Closes the cache. + * + * This function has ceased to do anything since WordPress 2.5. + * The functionality was removed along with the rest of the persistent cache. + * This does not mean that plugins can't implement this function when they need + * to make sure that the cache is cleaned up after WordPress no longer needs it. + * + * @since 2.0.0 + * + * @return bool Always returns true. + */ +function wp_cache_close() { + return true; +} + +/** + * Decrements a numeric item's value. + * + * @link https://www.php.net/manual/en/memcached.decrement.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to decrement the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ +function wp_cache_decrement( $key, $offset = 1, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->decrement( $key, $offset, $group ); +} + +/** + * Decrements a numeric item's value. + * + * This is the same as wp_cache_decrement(), but kept for backward compatibility. + * The original WordPress caching backends use wp_cache_decr(). + * + * @link https://www.php.net/manual/en/memcached.decrement.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to decrement the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ +function wp_cache_decr( $key, $offset = 1, $group = '' ) { + return wp_cache_decrement( $key, $offset, $group ); +} + +/** + * Removes the item from the cache. + * + * Removes an item from memcached with identified by $key after $time seconds. + * The $time parameter allows an object to be queued for deletion without + * immediately deleting. Between the time that it is queued and the time it's deleted, + * add, replace, and get will fail, but set will succeed. + * + * @link https://www.php.net/manual/en/memcached.delete.php + * + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param int $time The amount of time the server will wait to delete the item in seconds. + * @return bool True on success, false on failure. + */ +function wp_cache_delete( $key, $group = '', $time = 0 ) { + global $wp_object_cache; + return $wp_object_cache->delete( $key, $group, $time ); +} + +/** + * Removes the item from the cache by server key. + * + * Removes an item from memcached with identified by $key after $time seconds. + * The $time parameter allows an object to be queued for deletion without + * immediately deleting. Between the time that it is queued and the time it's deleted, + * add, replace, and get will fail, but set will succeed. + * + * @link https://www.php.net/manual/en/memcached.deletebykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param int $time The amount of time the server will wait to delete the item in seconds. + * @return bool True on success, false on failure. + */ +function wp_cache_delete_by_key( $server_key, $key, $group = '', $time = 0 ) { + global $wp_object_cache; + return $wp_object_cache->deleteByKey( $server_key, $key, $group, $time ); +} + +/** + * Deletes multiple values from the cache in one call. + * + * @param array $keys Array of keys under which the cache to deleted. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if the contents were not deleted. + */ +function wp_cache_delete_multiple( array $keys, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->deleteMultiple( $keys, $group ); +} + +/** + * Fetches the next result. + * + * @link https://www.php.net/manual/en/memcached.fetch.php + * + * @return array|false The next result on success, false on failure. + */ +function wp_cache_fetch() { + global $wp_object_cache; + return $wp_object_cache->fetch(); +} + +/** + * Fetches all remaining results from the last request. + * + * @link https://www.php.net/manual/en/memcached.fetchall.php + * + * @return array|false The results on success, false on failure. + */ +function wp_cache_fetch_all() { + global $wp_object_cache; + return $wp_object_cache->fetchAll(); +} + +/** + * Invalidates all items in the cache. + * + * @link https://www.php.net/manual/en/memcached.flush.php + * + * @param int $delay Number of seconds to wait before invalidating the items. + * @return bool True on success, false on failure. + */ +function wp_cache_flush( $delay = 0 ) { + global $wp_object_cache; + return $wp_object_cache->flush( $delay ); +} + +/** + * Determines whether the object cache implementation supports a particular feature. + * + * @since 6.1.0 + * + * @param string $feature Name of the feature to check for. Possible values include: + * 'add_multiple', 'set_multiple', 'get_multiple', 'delete_multiple', + * 'flush_runtime', 'flush_group'. + * @return bool True if the feature is supported, false otherwise. + */ +function wp_cache_supports( $feature ) { + return false; +} + +/** + * Retrieves object from cache. + * + * Gets an object from cache based on $key and $group. In order to fully support + * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function + * if either of those values are set. In that case, the request is made directly + * to the memcached server for proper handling of the callback and/or token. + * + * Note that the $deprecated and $found args are only here for compatibility + * with the native wp_cache_get() function. + * + * @link https://www.php.net/manual/en/memcached.get.php + * + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param bool $force Whether or not to force a cache invalidation. + * @param null|bool $found Variable passed by reference to determine if the value was found or not. + * @param null|string $cache_cb Read-through caching callback. + * @param null|float $cas_token The variable to store the CAS token in. + * @return bool|mixed Cached object value. + */ +function wp_cache_get( $key, $group = '', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { + global $wp_object_cache; + + if ( func_num_args() > 4 ) { + return $wp_object_cache->get( $key, $group, $force, $found, '', false, $cache_cb, $cas_token ); + } else { + return $wp_object_cache->get( $key, $group, $force, $found ); + } +} + +/** + * Retrieves object from cache from specified server. + * + * Gets an object from cache based on $key, $group, and $server_key. In order to fully support + * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function + * if either of those values are set. In that case, the request is made directly + * to the memcached server for proper handling of the callback and/or token. + * + * @link https://www.php.net/manual/en/memcached.getbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param bool $force Whether or not to force a cache invalidation. + * @param null|bool $found Variable passed by reference to determine if the value was found or not. + * @param null|string $cache_cb Read-through caching callback. + * @param null|float $cas_token The variable to store the CAS token in. + * @return bool|mixed Cached object value. + */ +function wp_cache_get_by_key( $server_key, $key, $group = '', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { + global $wp_object_cache; + + if ( func_num_args() > 5 ) { + return $wp_object_cache->getByKey( $server_key, $key, $group, $force, $found, $cache_cb, $cas_token ); + } else { + return $wp_object_cache->getByKey( $server_key, $key, $group, $force, $found ); + } +} + +/** + * Requests multiple keys without blocking. + * + * @link https://www.php.net/manual/en/memcached.getdelayed.php + * + * @param string|array $keys Array or string of key(s) to request. + * @param string|array $groups Array or string of group(s) for the key(s). + * See buildKeys for more on how these are handled. + * @param bool $with_cas Whether to request CAS token values also. + * @param null $value_cb The result callback or null. + * @return bool True on success, false on failure. + */ +function wp_cache_get_delayed( $keys, $groups = '', $with_cas = false, $value_cb = null ) { + global $wp_object_cache; + return $wp_object_cache->getDelayed( $keys, $groups, $with_cas, $value_cb ); +} + +/** + * Requests multiple keys without blocking from a specified server. + * + * @link https://www.php.net/manual/en/memcached.getdelayed.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string|array $keys Array or string of key(s) to request. + * @param string|array $groups Array or string of group(s) for the key(s). + * See buildKeys for more on how these are handled. + * @param bool $with_cas Whether to request CAS token values also. + * @param null $value_cb The result callback or null. + * @return bool True on success, false on failure. + */ +function wp_cache_get_delayed_by_key( $server_key, $keys, $groups = '', $with_cas = false, $value_cb = null ) { + global $wp_object_cache; + return $wp_object_cache->getDelayedByKey( $server_key, $keys, $groups, $with_cas, $value_cb ); +} + +/** + * Gets multiple values from memcached in one request. + * + * See the buildKeys method definition to understand the $keys/$groups parameters. + * + * @link https://www.php.net/manual/en/memcached.getmulti.php + * + * @param array $keys Array of keys to retrieve. + * @param string|array $groups If string, used for all keys. + * If arrays, corresponds with the $keys array. + * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. + * @param int $flags The flags for the get operation. + * @return bool|array The array of found items on success, false on failure. + */ +function wp_cache_get_multi( $keys, $groups = '', &$cas_tokens = null, $flags = null ) { + global $wp_object_cache; + + if ( func_num_args() > 2 ) { + return $wp_object_cache->getMulti( $keys, $groups, '', $cas_tokens, $flags ); + } else { + return $wp_object_cache->getMulti( $keys, $groups ); + } +} + +/** + * Gets multiple values from memcached in one request by specified server key. + * + * See the buildKeys method definition to understand the $keys/$groups parameters. + * + * @link https://www.php.net/manual/en/memcached.getmultibykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param array $keys Array of keys to retrieve. + * @param string|array $groups If string, used for all keys. + * If arrays, corresponds with the $keys array. + * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. + * @param int $flags The flags for the get operation. + * @return bool|array The array of found items on success, false on failure. + */ +function wp_cache_get_multi_by_key( $server_key, $keys, $groups = '', &$cas_tokens = null, $flags = null ) { + global $wp_object_cache; + + if ( func_num_args() > 3 ) { + return $wp_object_cache->getMultiByKey( $server_key, $keys, $groups, $cas_tokens, $flags ); + } else { + return $wp_object_cache->getMultiByKey( $server_key, $keys, $groups ); + } +} + +/** + * Retrieves multiple values from the cache in one call. + * + * @param array $keys Array of keys under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param bool $force Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @return array Array of return values, grouped by key. Each value is either + * the cache contents on success, or false on failure. + */ +function wp_cache_get_multiple( $keys, $group = '', $force = false ) { + global $wp_object_cache; + return $wp_object_cache->getMultiple( $keys, $group, $force ); +} + +/** + * Retrieves a Memcached option value. + * + * @link https://www.php.net/manual/en/memcached.getoption.php + * + * @param int $option One of the Memcached::OPT_* constants. + * @return mixed The value of the requested option on success, false on failure. + */ +function wp_cache_get_option( $option ) { + global $wp_object_cache; + return $wp_object_cache->getOption( $option ); +} + +/** + * Returns the result code of the last option. + * + * @link https://www.php.net/manual/en/memcached.getresultcode.php + * + * @return int Result code of the last Memcached operation. + */ +function wp_cache_get_result_code() { + global $wp_object_cache; + return $wp_object_cache->getResultCode(); +} + +/** + * Return the message describing the result of the last operation. + * + * @link https://www.php.net/manual/en/memcached.getresultmessage.php + * + * @return string Message describing the result of the last Memcached operation. + */ +function wp_cache_get_result_message() { + global $wp_object_cache; + return $wp_object_cache->getResultMessage(); +} + +/** + * Gets server information by key. + * + * @link https://www.php.net/manual/en/memcached.getserverbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @return array Array with host, post, and weight on success, fales on failure. + */ +function wp_cache_get_server_by_key( $server_key ) { + global $wp_object_cache; + return $wp_object_cache->getServerByKey( $server_key ); +} + +/** + * Gets the list of servers in the pool. + * + * @link https://www.php.net/manual/en/memcached.getserverlist.php + * + * @return array The list of all servers in the server pool. + */ +function wp_cache_get_server_list() { + global $wp_object_cache; + return $wp_object_cache->getServerList(); +} + +/** + * Gets server pool statistics. + * + * @link https://www.php.net/manual/en/memcached.getstats.php + * + * @return array Array of server statistics, one entry per server. + */ +function wp_cache_get_stats() { + global $wp_object_cache; + return $wp_object_cache->getStats(); +} + +/** + * Gets server pool memcached version information. + * + * @link https://www.php.net/manual/en/memcached.getversion.php + * + * @return array Array of server versions, one entry per server. + */ +function wp_cache_get_version() { + global $wp_object_cache; + return $wp_object_cache->getVersion(); +} + +/** + * Increments a numeric item's value. + * + * @link https://www.php.net/manual/en/memcached.increment.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to increment the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ +function wp_cache_increment( $key, $offset = 1, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->increment( $key, $offset, $group ); +} + +/** + * Increments a numeric item's value. + * + * This is the same as wp_cache_increment(), but kept for backward compatibility. + * The original WordPress caching backends use wp_cache_incr(). + * + * @link https://www.php.net/manual/en/memcached.increment.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to increment the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ +function wp_cache_incr( $key, $offset = 1, $group = '' ) { + return wp_cache_increment( $key, $offset, $group ); +} + +/** + * Prepends data to an existing item. + * + * This method should throw an error if it is used with compressed data. This is an expected behavior. + * Memcached casts the value to be prepended to the initial value to the type of the initial value. + * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 + * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" + * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been + * mimicked in the internal cache to produce similar results and improve consistency. It is recommended + * that prepends only occur with data of the same type. + * + * @link https://www.php.net/manual/en/memcached.prepend.php + * + * @param string $key The key under which to store the value. + * @param string $value Must be string as prepending mixed values is not well-defined. + * @param string $group The group value prepended to the $key. + * @return bool True on success, false on failure. + */ +function wp_cache_prepend( $key, $value, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->prepend( $key, $value, $group ); +} + +/** + * Appends data to an existing item by server key. + * + * This method should throw an error if it is used with compressed data. This is an expected behavior. + * Memcached casts the value to be prepended to the initial value to the type of the initial value. + * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 + * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" + * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been + * mimicked in the internal cache to produce similar results and improve consistency. It is recommended + * that prepends only occur with data of the same type. + * + * @link https://www.php.net/manual/en/memcached.prependbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $value Must be string as prepending mixed values is not well-defined. + * @param string $group The group value prepended to the $key. + * @return bool True on success, false on failure. + */ +function wp_cache_prepend_by_key( $server_key, $key, $value, $group = '' ) { + global $wp_object_cache; + return $wp_object_cache->prependByKey( $server_key, $key, $value, $group ); +} + +/** + * Replaces a value in cache. + * + * This method is similar to "add"; however, is does not successfully set a value + * if the object's key is not already set in cache. + * + * @link https://www.php.net/manual/en/memcached.replace.php + * + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_replace( $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->replace( $key, $value, $group, $expiration ); +} + +/** + * Replaces a value in cache on a specific server. + * + * This method is similar to "addByKey"; however, is does not successfully set a value + * if the object's key is not already set in cache. + * + * @link https://www.php.net/manual/en/memcached.addbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_replace_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->replaceByKey( $server_key, $key, $value, $group, $expiration ); +} + +/** + * Sets a value in cache. + * + * The value is set whether or not this key already exists in memcached. + * + * @link https://www.php.net/manual/en/memcached.set.php + * + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_set( $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->set( $key, $value, $group, $expiration ); +} + +/** + * Sets a value in cache. + * + * The value is set whether or not this key already exists in memcached. + * + * @link https://www.php.net/manual/en/memcached.set.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_set_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->setByKey( $server_key, $key, $value, $group, $expiration ); +} + +/** + * Sets multiple values to cache at once. + * + * By sending an array of $items to this function, all values are saved at once to + * memcached, reducing the need for multiple requests to memcached. The $items array + * keys and values are what are stored to memcached. The keys in the $items array + * are merged with the $groups array/string value via buildKeys to determine the + * final key for the object. + * + * @param array $items An array of key/value pairs to store on the server. + * @param string|array $groups Group(s) to merge with key(s) in $items. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_set_multi( $items, $groups = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->setMulti( $items, $groups, $expiration ); +} + +/** + * Sets multiple values to cache at once on specified server. + * + * By sending an array of $items to this function, all values are saved at once to + * memcached, reducing the need for multiple requests to memcached. The $items array + * keys and values are what are stored to memcached. The keys in the $items array + * are merged with the $groups array/string value via buildKeys to determine the + * final key for the object. + * + * @param string $server_key The key identifying the server to store the value on. + * @param array $items An array of key/value pairs to store on the server. + * @param string|array $groups Group(s) to merge with key(s) in $items. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ +function wp_cache_set_multi_by_key( $server_key, $items, $groups = 'default', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->setMultiByKey( $server_key, $items, $groups, $expiration ); +} + +/** + * Sets multiple values to the cache in one call. + * + * Differs from wp_cache_add_multiple() in that it will always write data. + * + * @param array $items Array of keys and values to be set. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expiration Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false on failure. + */ +function wp_cache_set_multiple( array $items, $group = '', $expiration = 0 ) { + global $wp_object_cache; + return $wp_object_cache->setMultiple( $items, $group, $expiration ); +} + +/** + * Sets a Memcached option. + * + * @link https://www.php.net/manual/en/memcached.setoption.php + * + * @param int $option Option name. + * @param mixed $value Option value. + * @return bool True on success, false on failure. + */ +function wp_cache_set_option( $option, $value ) { + global $wp_object_cache; + return $wp_object_cache->setOption( $option, $value ); +} + +/** + * Switches blog prefix, which changes the cache that is accessed. + * + * @param int $blog_id Blog to switch to. + * @return void + */ +function wp_cache_switch_to_blog( $blog_id ) { + global $wp_object_cache; + return $wp_object_cache->switch_to_blog( $blog_id ); +} + + +/** + * Sets up Object Cache Global and assigns it. + * + * @global WP_Object_Cache $wp_object_cache WordPress Object Cache + * @return void + */ +function wp_cache_init() { + global $wp_object_cache; + $wp_object_cache = new WP_Object_Cache(); +} + +/** + * Adds a group or set of groups to the list of non-persistent groups. + * + * @param string|array $groups A group or an array of groups to add. + * @return void + */ +function wp_cache_add_global_groups( $groups ) { + global $wp_object_cache; + $wp_object_cache->add_global_groups( $groups ); +} + +/** + * Adds a group or set of groups to the list of non-Memcached groups. + * + * @param string|array $groups A group or an array of groups to add. + * @return void + */ +function wp_cache_add_non_persistent_groups( $groups ) { + global $wp_object_cache; + $wp_object_cache->add_non_persistent_groups( $groups ); +} + +// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid +class WP_Object_Cache { + + /** + * Holds the Memcached object. + * + * @var Memcached + */ + public $m; + + /** + * Hold the Memcached server details. + * + * @var array + */ + public $servers; + + /** + * Holds the non-Memcached objects. + * + * @var array + */ + public $cache = array(); + + /** + * List of global groups. + * + * @var array + */ + public $global_groups = array(); + + /** + * List of groups not saved to Memcached. + * + * @var array + */ + public $no_mc_groups = array(); + + /** + * Prefix used for global groups. + * + * @var string + */ + public $global_prefix = ''; + + /** + * Prefix used for non-global groups. + * + * @var string + */ + public $blog_prefix = ''; + + /** + * Instantiates the Memcached class. + * + * Instantiates the Memcached class and returns adds the servers specified + * in the $memcached_servers global array. + * + * @link https://www.php.net/manual/en/memcached.construct.php + * + * @param null $persistent_id To create an instance that persists between requests, + * use persistent_id to specify a unique ID for the instance. + */ + public function __construct( $persistent_id = null ) { + global $memcached_servers, $blog_id, $table_prefix; + + if ( is_null( $persistent_id ) || ! is_string( $persistent_id ) ) { + $this->m = new Memcached(); + } else { + $this->m = new Memcached( $persistent_id ); + } + + if ( isset( $memcached_servers ) ) { + $this->servers = $memcached_servers; + } else { + $this->servers = array( array( 'memcached', 11211 ) ); + } + + $this->addServers( $this->servers ); + + /** + * This approach is borrowed from Sivel and Boren. Use the salt for easy cache invalidation + * and for multi single WP installations on the same server. + */ + if ( ! defined( 'WP_CACHE_KEY_SALT' ) ) { + define( 'WP_CACHE_KEY_SALT', '' ); + } + + // Assign global and blog prefixes for use with keys. + if ( function_exists( 'is_multisite' ) ) { + $this->global_prefix = ( is_multisite() || defined( 'CUSTOM_USER_TABLE' ) && defined( 'CUSTOM_USER_META_TABLE' ) ) ? '' : $table_prefix; + $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':'; + } + + // Setup cacheable values for handling expiration times. + $this->thirty_days = 60 * 60 * 24 * 30; + $this->now = time(); + } + + /** + * Adds a value to cache. + * + * If the specified key already exists, the value is not stored and the function + * returns false. + * + * @link https://www.php.net/manual/en/memcached.add.php + * + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function add( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { + /* + * Ensuring that wp_suspend_cache_addition is defined before calling, because sometimes an advanced-cache.php + * file will load object-cache.php before wp-includes/functions.php is loaded. In those cases, if wp_cache_add + * is called in advanced-cache.php before any more of WordPress is loaded, we get a fatal error because + * wp_suspend_cache_addition will not be defined until wp-includes/functions.php is loaded. + */ + if ( function_exists( 'wp_suspend_cache_addition' ) && wp_suspend_cache_addition() ) { + return false; + } + + $derived_key = $this->buildKey( $key, $group ); + $expiration = $this->sanitize_expiration( $expiration ); + + // If group is a non-Memcached group, save to runtime cache, not Memcached. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + + // Add does not set the value if the key exists; mimic that here. + if ( isset( $this->cache[ $derived_key ] ) ) { + return false; + } + + $this->add_to_internal_cache( $derived_key, $value ); + + return true; + } + + // Save to Memcached. + if ( $by_key ) { + $result = $this->m->addByKey( $server_key, $derived_key, $value, $expiration ); + } else { + $result = $this->m->add( $derived_key, $value, $expiration ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $value ); + } + + return $result; + } + + /** + * Adds a value to cache on a specific server. + * + * Using a server_key value, the object can be stored on a specified server as opposed + * to a random server in the stack. Note that this method will add the key/value to the + * _cache object as part of the runtime cache. It will add it to an array for the + * specified server_key. + * + * @link https://www.php.net/manual/en/memcached.addbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function addByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { + return $this->add( $key, $value, $group, $expiration, $server_key, true ); + } + + /** + * Adds multiple values to cache. + * + * @param array $items Array of keys and values to be added. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expiration Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if cache key and group already exist. + */ + public function addMultiple( array $items, $group = '', $expiration = 0 ) { + $values = array(); + + foreach ( $items as $key => $value ) { + $values[ $key ] = $this->add( $key, $value, $group, $expiration ); + } + + return $values; + } + + /** + * Adds a single server to the list of Memcached servers. + * + * @link https://www.php.net/manual/en/memcached.addserver.php + * + * @param string $host The hostname of the memcache server. + * @param int $port The port on which memcache is running. + * @param int $weight The weight of the server relative to the total weight + * of all the servers in the pool. + * @return bool True on success, false on failure. + */ + public function addServer( $host, $port, $weight = 0 ) { + $host = is_string( $host ) ? $host : '127.0.0.1'; + $port = is_numeric( $port ) && $port > 0 ? $port : 11211; + $weight = is_numeric( $weight ) && $weight > 0 ? $weight : 1; + + return $this->m->addServer( $host, $port, $weight ); + } + + /** + * Adds an array of servers to the pool. + * + * Each individual server in the array must include a domain and port, with an optional + * weight value: $servers = array( array( '127.0.0.1', 11211, 0 ) ); + * + * @link https://www.php.net/manual/en/memcached.addservers.php + * + * @param array $servers Array of server to register. + * @return bool True on success, false on failure. + */ + public function addServers( $servers ) { + if ( ! is_object( $this->m ) ) { + return false; + } + + return $this->m->addServers( $servers ); + } + + /** + * Appends data to an existing item. + * + * This method should throw an error if it is used with compressed data. + * This is an expected behavior. Memcached casts the value to be appended to the initial value + * to the type of the initial value. Be careful as this leads to unexpected behavior at times. + * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce + * similar results and improve consistency. It is recommended that appends only occur with data of + * the same type. + * + * @link https://www.php.net/manual/en/memcached.append.php + * + * @param string $key The key under which to store the value. + * @param mixed $value Must be string as appending mixed values is not well-defined. + * @param string $group The group value appended to the $key. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function append( $key, $value, $group = 'default', $server_key = '', $by_key = false ) { + if ( ! is_string( $value ) && ! is_int( $value ) && ! is_float( $value ) ) { + return false; + } + + $derived_key = $this->buildKey( $key, $group ); + + // If group is a non-Memcached group, append to runtime cache value, not Memcached. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + if ( ! isset( $this->cache[ $derived_key ] ) ) { + return false; + } + + $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'app' ); + $this->add_to_internal_cache( $derived_key, $combined ); + return true; + } + + // Append to Memcached value. + if ( $by_key ) { + $result = $this->m->appendByKey( $server_key, $derived_key, $value ); + } else { + $result = $this->m->append( $derived_key, $value ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'app' ); + $this->add_to_internal_cache( $derived_key, $combined ); + } + + return $result; + } + + /** + * Appends data to an existing item by server key. + * + * This method should throw an error if it is used with compressed data. + * This is an expected behavior. Memcached casts the value to be appended to the initial value + * to the type of the initial value. Be careful as this leads to unexpected behavior at times. + * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce + * similar results and improve consistency. It is recommended that appends only occur with data of + * the same type. + * + * @link https://www.php.net/manual/en/memcached.appendbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value Must be string as appending mixed values is not well-defined. + * @param string $group The group value appended to the $key. + * @return bool True on success, false on failure. + */ + public function appendByKey( $server_key, $key, $value, $group = 'default' ) { + return $this->append( $key, $value, $group, $server_key, true ); + } + + /** + * Performs a "check and set" to store data. + * + * The set will be successful only if the no other request has updated the value + * since it was fetched by this request. + * + * @link https://www.php.net/manual/en/memcached.cas.php + * + * @param float $cas_token Unique value associated with the existing item. Generated by memcached. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function cas( $cas_token, $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { + $derived_key = $this->buildKey( $key, $group ); + $expiration = $this->sanitize_expiration( $expiration ); + + /** + * If group is a non-Memcached group, save to runtime cache, not Memcached. Note + * that since check and set cannot be emulated in the run time cache, this value + * operation is treated as a normal "add" for no_mc_groups. + */ + if ( in_array( $group, $this->no_mc_groups, true ) ) { + $this->add_to_internal_cache( $derived_key, $value ); + return true; + } + + // Save to Memcached. + if ( $by_key ) { + $result = $this->m->casByKey( $cas_token, $server_key, $derived_key, $value, $expiration ); + } else { + $result = $this->m->cas( $cas_token, $derived_key, $value, $expiration ); + } + + // Store in runtime cache if cas was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $value ); + } + + return $result; + } + + /** + * Performs a "check and set" to store data with a server key. + * + * The set will be successful only if the no other request has updated the value + * since it was fetched by this request. + * + * @link https://www.php.net/manual/en/memcached.casbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param float $cas_token Unique value associated with the existing item. Generated by memcached. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function casByKey( $cas_token, $server_key, $key, $value, $group = 'default', $expiration = 0 ) { + return $this->cas( $cas_token, $key, $value, $group, $expiration, $server_key, true ); + } + + /** + * Decrements a numeric item's value. + * + * @link https://www.php.net/manual/en/memcached.decrement.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to decrement the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ + public function decrement( $key, $offset = 1, $group = 'default' ) { + $derived_key = $this->buildKey( $key, $group ); + + // Decrement values in no_mc_groups. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + + // Only decrement if the key already exists and value is 0 or greater (mimics memcached behavior). + if ( isset( $this->cache[ $derived_key ] ) && $this->cache[ $derived_key ] >= 0 ) { + + // If numeric, subtract; otherwise, consider it 0 and do nothing. + if ( is_numeric( $this->cache[ $derived_key ] ) ) { + $this->cache[ $derived_key ] -= (int) $offset; + } else { + $this->cache[ $derived_key ] = 0; + } + + // Returned value cannot be less than 0. + if ( $this->cache[ $derived_key ] < 0 ) { + $this->cache[ $derived_key ] = 0; + } + + return $this->cache[ $derived_key ]; + } else { + return false; + } + } + + $result = $this->m->decrement( $derived_key, $offset ); + + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $result ); + } + + return $result; + } + + /** + * Decrements a numeric item's value. + * + * Alias for $this->decrement(). Other caching backends use this abbreviated form + * of the function. It *may* cause breakage somewhere, so it is nice to have. + * This function will also allow the core unit tests to pass. + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to decrement the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ + public function decr( $key, $offset = 1, $group = 'default' ) { + return $this->decrement( $key, $offset, $group ); + } + + /** + * Removes the item from the cache. + * + * Removes an item from memcached with identified by $key after $time seconds. + * The $time parameter allows an object to be queued for deletion without + * immediately deleting. Between the time that it is queued and the time it's deleted, + * add, replace, and get will fail, but set will succeed. + * + * @link https://www.php.net/manual/en/memcached.delete.php + * + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param int $time The amount of time the server will wait to delete the item in seconds. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function delete( $key, $group = 'default', $time = 0, $server_key = '', $by_key = false ) { + $derived_key = $this->buildKey( $key, $group ); + + // Remove from no_mc_groups array. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + if ( isset( $this->cache[ $derived_key ] ) ) { + unset( $this->cache[ $derived_key ] ); + } + + return true; + } + + if ( $by_key ) { + $result = $this->m->deleteByKey( $server_key, $derived_key, $time ); + } else { + $result = $this->m->delete( $derived_key, $time ); + } + + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + unset( $this->cache[ $derived_key ] ); + } + + return $result; + } + + /** + * Removes the item from the cache by server key. + * + * Removes an item from memcached with identified by $key after $time seconds. + * The $time parameter allows an object to be queued for deletion without + * immediately deleting. Between the time that it is queued and the time it's deleted, + * add, replace, and get will fail, but set will succeed. + * + * @link https://www.php.net/manual/en/memcached.deletebykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param int $time The amount of time the server will wait to delete the item in seconds. + * @return bool True on success, false on failure. + */ + public function deleteByKey( $server_key, $key, $group = 'default', $time = 0 ) { + return $this->delete( $key, $group, $time, $server_key, true ); + } + + /** + * Removes multiple items from the cache. + * + * @param array $keys Array of keys under which the cache to deleted. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if the contents were not deleted. + */ + public function deleteMultiple( $keys, $group ) { + $values = array(); + + foreach ( $keys as $key ) { + $values[ $key ] = $this->delete( $key, $group ); + } + + return $values; + } + + /** + * Fetches the next result. + * + * @link https://www.php.net/manual/en/memcached.fetch.php + * + * @return array|false The next result on success, false on failure. + */ + public function fetch() { + return $this->m->fetch(); + } + + /** + * Fetches all remaining results from the last request. + * + * @link https://www.php.net/manual/en/memcached.fetchall.php + * + * @return array|false The results on success, false on failure. + */ + public function fetchAll() { + return $this->m->fetchAll(); + } + + /** + * Invalidates all items in the cache. + * + * @link https://www.php.net/manual/en/memcached.flush.php + * + * @param int $delay Number of seconds to wait before invalidating the items. + * @return bool True on success, false on failure. + */ + public function flush( $delay = 0 ) { + $result = $this->m->flush( $delay ); + + // Only reset the runtime cache if memcached was properly flushed. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->cache = array(); + } + + return $result; + } + + /** + * Retrieves object from cache. + * + * Gets an object from cache based on $key and $group. In order to fully support + * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function + * if either of those values are set. In that case, the request is made directly + * to the memcached server for proper handling of the callback and/or token. + * Note that the $cas_token variable cannot be directly passed to the function. + * The variable needs to be first defined with a non-null value. + * + * If using the $cache_cb argument, the new value will always have an expiration + * of time of 0 (forever). This is a limitation of the Memcached PECL extension. + * + * @link https://www.php.net/manual/en/memcached.get.php + * + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param bool $force Whether or not to force a cache invalidation. + * @param null|bool $found Variable passed by reference to determine if the value was found or not. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @param null|callable $cache_cb Read-through caching callback. + * @param null|float $cas_token The variable to store the CAS token in. + * @return bool|mixed Cached object value. + */ + public function get( $key, $group = 'default', $force = false, &$found = null, $server_key = '', $by_key = false, $cache_cb = null, &$cas_token = null ) { + $derived_key = $this->buildKey( $key, $group ); + + // Assume object is not found. + $found = false; + + // If either $cache_db, or $cas_token is set, must hit Memcached and bypass runtime cache. + if ( func_num_args() > 6 && ! in_array( $group, $this->no_mc_groups, true ) ) { + if ( $by_key ) { + $value = $this->m->getByKey( $server_key, $derived_key, $cache_cb, $cas_token ); + } else { + $value = $this->m->get( $derived_key, $cache_cb, $cas_token ); + } + } else { + if ( isset( $this->cache[ $derived_key ] ) ) { + $found = true; + return is_object( $this->cache[ $derived_key ] ) ? clone $this->cache[ $derived_key ] : $this->cache[ $derived_key ]; + } elseif ( in_array( $group, $this->no_mc_groups, true ) ) { + return false; + } else { + if ( $by_key ) { + $value = $this->m->getByKey( $server_key, $derived_key ); + } else { + $value = $this->m->get( $derived_key ); + } + } + } + + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $value ); + $found = true; + } + + return is_object( $value ) ? clone $value : $value; + } + + /** + * Retrieves object from cache from specified server. + * + * Gets an object from cache based on $key and $group, and $server_key. In order to fully support + * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function + * if either of those values are set. In that case, the request is made directly + * to the memcached server for proper handling of the callback and/or token. + * Note that the $cas_token variable cannot be directly passed to the function. + * The variable needs to be first defined with a non-null value. + * + * If using the $cache_cb argument, the new value will always have an expiration + * of time of 0 (forever). This is a limitation of the Memcached PECL extension. + * + * @link https://www.php.net/manual/en/memcached.getbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @param bool $force Whether or not to force a cache invalidation. + * @param null|bool $found Variable passed by reference to determine if the value was found or not. + * @param null|string $cache_cb Read-through caching callback. + * @param null|float $cas_token The variable to store the CAS token in. + * @return bool|mixed Cached object value. + */ + public function getByKey( $server_key, $key, $group = 'default', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { + /** + * Need to be careful how "get" is called. If you send $cache_cb, and $cas_token, it will hit memcached. + * Only send those args if they were sent to this function. + */ + if ( func_num_args() > 5 ) { + return $this->get( $key, $group, $force, $found, $server_key, true, $cache_cb, $cas_token ); + } else { + return $this->get( $key, $group, $force, $found, $server_key, true ); + } + } + + /** + * Requests multiple keys without blocking. + * + * @link https://www.php.net/manual/en/memcached.getdelayed.php + * + * @param string|array $keys Array or string of key(s) to request. + * @param string|array $groups Array or string of group(s) for the key(s). + * See buildKeys for more on how these are handled. + * @param bool $with_cas Whether to request CAS token values also. + * @param null $value_cb The result callback or null. + * @return bool True on success, false on failure. + */ + public function getDelayed( $keys, $groups = 'default', $with_cas = false, $value_cb = null ) { + $derived_keys = $this->buildKeys( $keys, $groups ); + return $this->m->getDelayed( $derived_keys, $with_cas, $value_cb ); + } + + /** + * Requests multiple keys without blocking from a specified server. + * + * @link https://www.php.net/manual/en/memcached.getdelayed.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string|array $keys Array or string of key(s) to request. + * @param string|array $groups Array or string of group(s) for the key(s). + * See buildKeys for more on how these are handled. + * @param bool $with_cas Whether to request CAS token values also. + * @param null $value_cb The result callback or null. + * @return bool True on success, false on failure. + */ + public function getDelayedByKey( $server_key, $keys, $groups = 'default', $with_cas = false, $value_cb = null ) { + $derived_keys = $this->buildKeys( $keys, $groups ); + return $this->m->getDelayedByKey( $server_key, $derived_keys, $with_cas, $value_cb ); + } + + /** + * Gets multiple values from memcached in one request. + * + * See the buildKeys method definition to understand the $keys/$groups parameters. + * + * @link https://www.php.net/manual/en/memcached.getmulti.php + * + * @param array $keys Array of keys to retrieve. + * @param string|array $groups If string, used for all keys. + * If arrays, corresponds with the $keys array. + * @param string $server_key The key identifying the server to store the value on. + * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. + * @param int $flags The flags for the get operation. + * @return bool|array The array of found items on success, false on failure. + */ + public function getMulti( $keys, $groups = 'default', $server_key = '', &$cas_tokens = null, $flags = null ) { + $derived_keys = $this->buildKeys( $keys, $groups ); + + /** + * If either $cas_tokens, or $flags is set, must hit Memcached and bypass runtime cache. + * Note that this will purposely ignore no_mc_groups values as they cannot handle CAS tokens + * or the special flags; however, if the groups of groups contains a no_mc_group, this is bypassed. + */ + if ( func_num_args() > 3 && ! $this->contains_no_mc_group( $groups ) ) { + if ( ! empty( $server_key ) ) { + $values = $this->m->getMultiByKey( $server_key, $derived_keys, $cas_tokens, $flags ); + } else { + $values = $this->m->getMulti( $derived_keys, $cas_tokens, $flags ); + } + } else { + $values = array(); + $need_to_get = array(); + + // Pull out values from runtime cache, or mark for retrieval. + foreach ( $derived_keys as $key ) { + if ( isset( $this->cache[ $key ] ) ) { + $values[ $key ] = $this->cache[ $key ]; + } else { + $need_to_get[ $key ] = $key; + } + } + + // Get those keys not found in the runtime cache. + if ( ! empty( $need_to_get ) ) { + if ( ! empty( $server_key ) ) { + $result = $this->m->getMultiByKey( $server_key, array_keys( $need_to_get ) ); + } else { + $result = $this->m->getMulti( array_keys( $need_to_get ) ); + } + } + + // Merge with values found in runtime cache. + if ( isset( $result ) && Memcached::RES_SUCCESS === $this->getResultCode() ) { + $values = array_merge( $values, $result ); + } + + // If order should be preserved, reorder now. + if ( ! empty( $need_to_get ) && Memcached::GET_PRESERVE_ORDER === $flags ) { + $ordered_values = array(); + + foreach ( $derived_keys as $key ) { + if ( isset( $values[ $key ] ) ) { + $ordered_values[ $key ] = $values[ $key ]; + } + } + + $values = $ordered_values; + unset( $ordered_values ); + } + } + + // Add the values to the runtime cache. + $this->cache = array_merge( $this->cache, $values ); + + return $values; + } + + /** + * Gets multiple values from memcached in one request by specified server key. + * + * See the buildKeys method definition to understand the $keys/$groups parameters. + * + * @link https://www.php.net/manual/en/memcached.getmultibykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param array $keys Array of keys to retrieve. + * @param string|array $groups If string, used for all keys. + * If arrays, corresponds with the $keys array. + * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. + * @param int $flags The flags for the get operation. + * @return bool|array The array of found items on success, false on failure. + */ + public function getMultiByKey( $server_key, $keys, $groups = 'default', &$cas_tokens = null, $flags = null ) { + /** + * Need to be careful how "getMulti" is called. If you send $cache_cb, and $cas_token, it will hit memcached. + * Only send those args if they were sent to this function. + */ + if ( func_num_args() > 3 ) { + return $this->getMulti( $keys, $groups, $server_key, $cas_tokens, $flags ); + } else { + return $this->getMulti( $keys, $groups, $server_key ); + } + } + + /** + * Get multiple items from the cache. + * + * @param array $keys Array of keys under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param bool $force Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @return array Array of return values, grouped by key. Each value is either + * the cache contents on success, or false on failure. + */ + public function getMultiple( $keys, $group = '', $force = false ) { + $values = array(); + + foreach ( $keys as $key ) { + $found = null; + $value = $this->get( $key, $group, $force, $found ); + $values[ $key ] = $found ? $value : false; + } + + return $values; + } + + /** + * Retrieves a Memcached option value. + * + * @link https://www.php.net/manual/en/memcached.getoption.php + * + * @param int $option One of the Memcached::OPT_* constants. + * @return mixed The value of the requested option on success, false on failure. + */ + public function getOption( $option ) { + return $this->m->getOption( $option ); + } + + /** + * Returns the result code of the last option. + * + * @link https://www.php.net/manual/en/memcached.getresultcode.php + * + * @return int Result code of the last Memcached operation. + */ + public function getResultCode() { + return $this->m->getResultCode(); + } + + /** + * Return the message describing the result of the last operation. + * + * @link https://www.php.net/manual/en/memcached.getresultmessage.php + * + * @return string Message describing the result of the last Memcached operation. + */ + public function getResultMessage() { + return $this->m->getResultMessage(); + } + + /** + * Gets server information by key. + * + * @link https://www.php.net/manual/en/memcached.getserverbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @return array Array with host, post, and weight on success, false on failure. + */ + public function getServerByKey( $server_key ) { + return $this->m->getServerByKey( $server_key ); + } + + /** + * Gets the list of servers in the pool. + * + * @link https://www.php.net/manual/en/memcached.getserverlist.php + * + * @return array The list of all servers in the server pool. + */ + public function getServerList() { + return $this->m->getServerList(); + } + + /** + * Gets server pool statistics. + * + * @link https://www.php.net/manual/en/memcached.getstats.php + * + * @return array Array of server statistics, one entry per server. + */ + public function getStats() { + return $this->m->getStats(); + } + + /** + * Gets server pool memcached version information. + * + * @link https://www.php.net/manual/en/memcached.getversion.php + * + * @return array Array of server versions, one entry per server. + */ + public function getVersion() { + return $this->m->getVersion(); + } + + /** + * Increments a numeric item's value. + * + * @link https://www.php.net/manual/en/memcached.increment.php + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to increment the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ + public function increment( $key, $offset = 1, $group = 'default' ) { + $derived_key = $this->buildKey( $key, $group ); + + // Increment values in no_mc_groups. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + + // Only increment if the key already exists and the number is currently 0 or greater (mimics memcached behavior). + if ( isset( $this->cache[ $derived_key ] ) && $this->cache[ $derived_key ] >= 0 ) { + + // If numeric, add; otherwise, consider it 0 and do nothing. + if ( is_numeric( $this->cache[ $derived_key ] ) ) { + $this->cache[ $derived_key ] += (int) $offset; + } else { + $this->cache[ $derived_key ] = 0; + } + + // Returned value cannot be less than 0. + if ( $this->cache[ $derived_key ] < 0 ) { + $this->cache[ $derived_key ] = 0; + } + + return $this->cache[ $derived_key ]; + } else { + return false; + } + } + + $result = $this->m->increment( $derived_key, $offset ); + + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $result ); + } + + return $result; + } + + /** + * Alias for $this->incr(). + * + * Certain plugins expect an "incr" method on the $wp_object_cache object (e.g., Batcache). + * Since the original version of this library matched names to the memcached methods, + * the "incr" method was missing. Adding this method restores compatibility with plugins + * expecting an "incr" method. + * + * @param string $key The key under which to store the value. + * @param int $offset The amount by which to increment the item's value. + * @param string $group The group value appended to the $key. + * @return int|bool Item's new value on success, false on failure. + */ + public function incr( $key, $offset = 1, $group = 'default' ) { + return $this->increment( $key, $offset, $group ); + } + + /** + * Prepends data to an existing item. + * + * This method should throw an error if it is used with compressed data. This is an expected behavior. + * Memcached casts the value to be prepended to the initial value to the type of the initial value. + * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 + * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" + * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been + * mimicked in the internal cache to produce similar results and improve consistency. It is recommended + * that prepends only occur with data of the same type. + * + * @link https://www.php.net/manual/en/memcached.prepend.php + * + * @param string $key The key under which to store the value. + * @param string $value Must be string as prepending mixed values is not well-defined. + * @param string $group The group value prepended to the $key. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function prepend( $key, $value, $group = 'default', $server_key = '', $by_key = false ) { + if ( ! is_string( $value ) && ! is_int( $value ) && ! is_float( $value ) ) { + return false; + } + + $derived_key = $this->buildKey( $key, $group ); + + // If group is a non-Memcached group, prepend to runtime cache value, not Memcached. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + if ( ! isset( $this->cache[ $derived_key ] ) ) { + return false; + } + + $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'pre' ); + $this->add_to_internal_cache( $derived_key, $combined ); + return true; + } + + // Append to Memcached value. + if ( $by_key ) { + $result = $this->m->prependByKey( $server_key, $derived_key, $value ); + } else { + $result = $this->m->prepend( $derived_key, $value ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'pre' ); + $this->add_to_internal_cache( $derived_key, $combined ); + } + + return $result; + } + + /** + * Appends data to an existing item by server key. + * + * This method should throw an error if it is used with compressed data. This is an expected behavior. + * Memcached casts the value to be prepended to the initial value to the type of the initial value. + * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 + * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" + * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been + * mimicked in the internal cache to produce similar results and improve consistency. It is recommended + * that prepends only occur with data of the same type. + * + * @link https://www.php.net/manual/en/memcached.prependbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param string $value Must be string as prepending mixed values is not well-defined. + * @param string $group The group value prepended to the $key. + * @return bool True on success, false on failure. + */ + public function prependByKey( $server_key, $key, $value, $group = 'default' ) { + return $this->prepend( $key, $value, $group, $server_key, true ); + } + + /** + * Replaces a value in cache. + * + * This method is similar to "add"; however, is does not successfully set a value + * if the object's key is not already set in cache. + * + * @link https://www.php.net/manual/en/memcached.replace.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function replace( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { + $derived_key = $this->buildKey( $key, $group ); + $expiration = $this->sanitize_expiration( $expiration ); + + // If group is a non-Memcached group, save to runtime cache, not Memcached. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + + // Replace won't save unless the key already exists; mimic this behavior here. + if ( ! isset( $this->cache[ $derived_key ] ) ) { + return false; + } + + $this->cache[ $derived_key ] = $value; + return true; + } + + // Save to Memcached. + if ( $by_key ) { + $result = $this->m->replaceByKey( $server_key, $derived_key, $value, $expiration ); + } else { + $result = $this->m->replace( $derived_key, $value, $expiration ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $value ); + } + + return $result; + } + + /** + * Replaces a value in cache on a specific server. + * + * This method is similar to "addByKey"; however, is does not successfully set a value + * if the object's key is not already set in cache. + * + * @link https://www.php.net/manual/en/memcached.addbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function replaceByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { + return $this->replace( $key, $value, $group, $expiration, $server_key, true ); + } + + /** + * Sets a value in cache. + * + * The value is set whether or not this key already exists in memcached. + * + * @link https://www.php.net/manual/en/memcached.set.php + * + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function set( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { + $derived_key = $this->buildKey( $key, $group ); + $expiration = $this->sanitize_expiration( $expiration ); + + // If group is a non-Memcached group, save to runtime cache, not Memcached. + if ( in_array( $group, $this->no_mc_groups, true ) ) { + $this->add_to_internal_cache( $derived_key, $value ); + return true; + } + + // Save to Memcached. + if ( $by_key ) { + $result = $this->m->setByKey( $server_key, $derived_key, $value, $expiration ); + } else { + $result = $this->m->set( $derived_key, $value, $expiration ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->add_to_internal_cache( $derived_key, $value ); + } + + return $result; + } + + /** + * Sets a value in cache on a specific server. + * + * The value is set whether or not this key already exists in memcached. + * + * @link https://www.php.net/manual/en/memcached.setbykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param string $key The key under which to store the value. + * @param mixed $value The value to store. + * @param string $group The group value appended to the $key. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function setByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { + return $this->set( $key, $value, $group, $expiration, $server_key, true ); + } + + /** + * Sets multiple values to cache at once. + * + * By sending an array of $items to this function, all values are saved at once to + * memcached, reducing the need for multiple requests to memcached. The $items array + * keys and values are what are stored to memcached. The keys in the $items array + * are merged with the $groups array/string value via buildKeys to determine the + * final key for the object. + * + * @link https://www.php.net/manual/en/memcached.setmulti.php + * + * @param array $items An array of key/value pairs to store on the server. + * @param string|array $groups Group(s) to merge with key(s) in $items. + * @param int $expiration The expiration time, defaults to 0. + * @param string $server_key The key identifying the server to store the value on. + * @param bool $by_key True to store in internal cache by key; false to not store by key. + * @return bool True on success, false on failure. + */ + public function setMulti( $items, $groups = 'default', $expiration = 0, $server_key = '', $by_key = false ) { + // Build final keys and replace $items keys with the new keys. + $derived_keys = $this->buildKeys( array_keys( $items ), $groups ); + $expiration = $this->sanitize_expiration( $expiration ); + $derived_items = array_combine( $derived_keys, $items ); + + // Do not add to memcached if in no_mc_groups. + foreach ( $derived_items as $derived_key => $value ) { + + // Get the individual item's group. + $key_pieces = explode( ':', $derived_key ); + + // If group is a non-Memcached group, save to runtime cache, not Memcached. + if ( in_array( $key_pieces[1], $this->no_mc_groups, true ) ) { + $this->add_to_internal_cache( $derived_key, $value ); + unset( $derived_items[ $derived_key ] ); + } + } + + // Save to memcached. + if ( $by_key ) { + $result = $this->m->setMultiByKey( $server_key, $derived_items, $expiration ); + } else { + $result = $this->m->setMulti( $derived_items, $expiration ); + } + + // Store in runtime cache if add was successful. + if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { + $this->cache = array_merge( $this->cache, $derived_items ); + } + + return $result; + } + + /** + * Sets multiple values to cache at once on specified server. + * + * By sending an array of $items to this function, all values are saved at once to + * memcached, reducing the need for multiple requests to memcached. The $items array + * keys and values are what are stored to memcached. The keys in the $items array + * are merged with the $groups array/string value via buildKeys to determine the + * final key for the object. + * + * @link https://www.php.net/manual/en/memcached.setmultibykey.php + * + * @param string $server_key The key identifying the server to store the value on. + * @param array $items An array of key/value pairs to store on the server. + * @param string|array $groups Group(s) to merge with key(s) in $items. + * @param int $expiration The expiration time, defaults to 0. + * @return bool True on success, false on failure. + */ + public function setMultiByKey( $server_key, $items, $groups = 'default', $expiration = 0 ) { + return $this->setMulti( $items, $groups, $expiration, $server_key, true ); + } + + /** + * Sets multiple values in cache. + * + * @param array $items Array of keys and values to be set. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expiration Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false on failure. + */ + public function setMultiple( array $items, $group = '', $expiration = 0 ) { + $values = array(); + + foreach ( $items as $key => $value ) { + $values[ $key ] = $this->set( $key, $value, $group, $expiration ); + } + + return $values; + } + + /** + * Sets a Memcached option. + * + * @link https://www.php.net/manual/en/memcached.setoption.php + * + * @param int $option Option name. + * @param mixed $value Option value. + * @return bool True on success, false on failure. + */ + public function setOption( $option, $value ) { + return $this->m->setOption( $option, $value ); + } + + /** + * Builds a key for the cached object using the blog_id, key, and group values. + * + * This function is inspired by the original WP Memcached Object cache. + * + * @author Ryan Boren + * @link http://wordpress.org/extend/plugins/memcached/ + * + * @param string $key The key under which to store the value. + * @param string $group The group value appended to the $key. + * @return string + */ + public function buildKey( $key, $group = 'default' ) { + if ( empty( $group ) ) { + $group = 'default'; + } + + if ( false !== array_search( $group, $this->global_groups, true ) ) { + $prefix = $this->global_prefix; + } else { + $prefix = $this->blog_prefix; + } + + return preg_replace( '/\s+/', '', WP_CACHE_KEY_SALT . "$prefix$group:$key" ); + } + + /** + * Creates an array of keys from passed key(s) and group(s). + * + * This function takes a string or array of key(s) and group(s) and combines them into a single dimensional + * array that merges the keys and groups. If the same number of keys and groups exist, the final keys will + * append $groups[n] to $keys[n]. If there are more keys than groups and the $groups parameter is an array, + * $keys[n] will be combined with $groups[n] until $groups runs out of values. 'default' will be used for remaining + * values. If $keys is an array and $groups is a string, all final values will append $groups to $keys[n]. + * If both values are strings, they will be combined into a single string. Note that if more $groups are received + * than $keys, the method will return an empty array. This method is primarily a helper method for methods + * that call memcached with an array of keys. + * + * @param string|array $keys Key(s) to merge with group(s). + * @param string|array $groups Group(s) to merge with key(s). + * @return array Array that combines keys and groups into a single set of memcached keys. + */ + public function buildKeys( $keys, $groups = 'default' ) { + $derived_keys = array(); + + // If strings sent, convert to arrays for proper handling. + if ( ! is_array( $groups ) ) { + $groups = (array) $groups; + } + + if ( ! is_array( $keys ) ) { + $keys = (array) $keys; + } + + // If we have equal numbers of keys and groups, merge $keys[n] and $group[n]. + if ( count( $keys ) === count( $groups ) ) { + for ( $i = 0; $i < count( $keys ); $i++ ) { + $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[ $i ] ); + } + + // If more keys are received than groups, merge $keys[n] and $group[n] + // until no more groups are left; remaining groups are 'default'. + } elseif ( count( $keys ) > count( $groups ) ) { + for ( $i = 0; $i < count( $keys ); $i++ ) { + if ( isset( $groups[ $i ] ) ) { + $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[ $i ] ); + } elseif ( count( $groups ) === 1 ) { + $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[0] ); + } else { + $derived_keys[] = $this->buildKey( $keys[ $i ], 'default' ); + } + } + } + + return $derived_keys; + } + + /** + * Ensures that a proper expiration time is set. + * + * Memcached treats any value over 30 days as a timestamp. If a developer sets the expiration + * for greater than 30 days or less than the current timestamp, the timestamp is in the past + * and the value isn't cached. This function detects values in that range and corrects them. + * + * @param string|int $expiration The dirty expiration time. + * @return string|int The sanitized expiration time. + */ + public function sanitize_expiration( $expiration ) { + if ( $expiration > $this->thirty_days && $expiration <= $this->now ) { + $expiration = $expiration + $this->now; + } + + return $expiration; + } + + /** + * Concatenates two values and casts to type of the first value. + * + * This is used in append and prepend operations to match how these functions are handled + * by memcached. In both cases, whichever value is the original value in the combined value + * will dictate the type of the combined value. + * + * @param mixed $original Original value that dictates the combined type. + * @param mixed $pended Value to combine with original value. + * @param string $direction Either 'pre' or 'app'. + * @return mixed Combined value casted to the type of the first value. + */ + public function combine_values( $original, $pended, $direction ) { + $type = gettype( $original ); + + // Combine the values based on direction of the "pend". + if ( 'pre' === $direction ) { + $combined = $pended . $original; + } else { + $combined = $original . $pended; + } + + // Cast type of combined value. + settype( $combined, $type ); + + return $combined; + } + + /** + * Simple wrapper for saving object to the internal cache. + * + * @param string $derived_key Key to save value under. + * @param mixed $value Object value. + */ + public function add_to_internal_cache( $derived_key, $value ) { + if ( is_object( $value ) ) { + $value = clone $value; + } + + $this->cache[ $derived_key ] = $value; + } + + /** + * Determines if a no_mc_group exists in a group of groups. + * + * @param mixed $groups The groups to search. + * @return bool True if a no_mc_group is present; false if a no_mc_group is not present. + */ + public function contains_no_mc_group( $groups ) { + if ( is_scalar( $groups ) ) { + return in_array( $groups, $this->no_mc_groups, true ); + } + + if ( ! is_array( $groups ) ) { + return false; + } + + foreach ( $groups as $group ) { + if ( in_array( $group, $this->no_mc_groups, true ) ) { + return true; + } + } + + return false; + } + + /** + * Adds global groups. + * + * This function comes straight from the original WP Memcached Object cache. + * + * @author Ryan Boren + * @link http://wordpress.org/extend/plugins/memcached/ + * + * @param array $groups Array of groups. + * @return void + */ + public function add_global_groups( $groups ) { + if ( ! is_array( $groups ) ) { + $groups = (array) $groups; + } + + $this->global_groups = array_merge( $this->global_groups, $groups ); + $this->global_groups = array_unique( $this->global_groups ); + } + + /** + * Adds non-persistent groups. + * + * This function comes straight from the original WP Memcached Object cache. + * + * @author Ryan Boren + * @link http://wordpress.org/extend/plugins/memcached/ + * + * @param array $groups Array of groups. + * @return void + */ + public function add_non_persistent_groups( $groups ) { + if ( ! is_array( $groups ) ) { + $groups = (array) $groups; + } + + $this->no_mc_groups = array_merge( $this->no_mc_groups, $groups ); + $this->no_mc_groups = array_unique( $this->no_mc_groups ); + } + + /** + * Gets a value specifically from the internal, run-time cache, not memcached. + * + * @param int|string $key Key value. + * @param int|string $group Group that the value belongs to. + * @return bool|mixed Value on success, false on failure. + */ + public function get_from_runtime_cache( $key, $group ) { + $derived_key = $this->buildKey( $key, $group ); + + if ( isset( $this->cache[ $derived_key ] ) ) { + return $this->cache[ $derived_key ]; + } + + return false; + } + + /** + * Switches blog prefix, which changes the cache that is accessed. + * + * @param int $blog_id Blog to switch to. + * @return void + */ + public function switch_to_blog( $blog_id ) { + global $table_prefix; + $blog_id = (int) $blog_id; + $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':'; + } +} +// phpcs:enable diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 1c67e6cc7af27..a8a971fc0f45f 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -382,6 +382,7 @@ function _wp_get_iframed_editor_assets() { * @return array The contextualized block editor settings. */ function get_block_editor_settings( array $custom_settings, $block_editor_context ) { + global $wp_theme_json_resolver; $editor_settings = array_merge( get_default_block_editor_settings(), array( @@ -412,7 +413,7 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex } } - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( $wp_theme_json_resolver->theme_has_support() ) { $block_classes = array( 'css' => 'styles', '__unstableType' => 'theme', diff --git a/src/wp-includes/block-patterns.php b/src/wp-includes/block-patterns.php index 074ed33c84b44..22f5ef3707d9d 100644 --- a/src/wp-includes/block-patterns.php +++ b/src/wp-includes/block-patterns.php @@ -134,16 +134,17 @@ function _load_remote_featured_patterns() { * @access private */ function _register_remote_theme_patterns() { + global $wp_theme_json_resolver; /** This filter is documented in wp-includes/block-patterns.php */ if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) { return; } - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! $wp_theme_json_resolver->theme_has_support() ) { return; } - $pattern_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_patterns(); + $pattern_settings = $wp_theme_json_resolver->get_theme_data()->get_patterns(); if ( empty( $pattern_settings ) ) { return; } diff --git a/src/wp-includes/block-supports/layout.php b/src/wp-includes/block-supports/layout.php index 7a882a9bab386..8c765a29985e3 100644 --- a/src/wp-includes/block-supports/layout.php +++ b/src/wp-includes/block-supports/layout.php @@ -457,6 +457,7 @@ function wp_render_layout_support_flag( $block_content, $block ) { * @return string Filtered block content. */ function wp_restore_group_inner_container( $block_content, $block ) { + global $wp_theme_json_resolver; $tag_name = isset( $block['attrs']['tagName'] ) ? $block['attrs']['tagName'] : 'div'; $group_with_inner_container_regex = sprintf( '/(^\s*<%1$s\b[^>]*wp-block-group(\s|")[^>]*>)(\s*]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/U', @@ -464,7 +465,7 @@ function wp_restore_group_inner_container( $block_content, $block ) { ); if ( - WP_Theme_JSON_Resolver::theme_has_support() || + $wp_theme_json_resolver->theme_has_support() || 1 === preg_match( $group_with_inner_container_regex, $block_content ) || ( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] ) ) { @@ -500,6 +501,7 @@ static function( $matches ) { * @return string Filtered block content. */ function wp_restore_image_outer_container( $block_content, $block ) { + global $wp_theme_json_resolver; $image_with_align = " /# 1) everything up to the class attribute contents ( @@ -527,7 +529,7 @@ function wp_restore_image_outer_container( $block_content, $block ) { )/iUx"; if ( - WP_Theme_JSON_Resolver::theme_has_support() || + $wp_theme_json_resolver->theme_has_support() || 0 === preg_match( $image_with_align, $block_content, $matches ) ) { return $block_content; diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index 5db20bf08c463..28a07a793a06a 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -347,11 +347,12 @@ function _get_block_templates_files( $template_type ) { * @return array Template item. */ function _add_block_template_info( $template_item ) { - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( ! $wp_theme_json_resolver->theme_has_support() ) { return $template_item; } - $theme_data = WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates(); + $theme_data = $wp_theme_json_resolver->get_theme_data()->get_custom_templates(); if ( isset( $theme_data[ $template_item['slug'] ] ) ) { $template_item['title'] = $theme_data[ $template_item['slug'] ]['title']; $template_item['postTypes'] = $theme_data[ $template_item['slug'] ]['postTypes']; @@ -370,8 +371,9 @@ function _add_block_template_info( $template_item ) { * @return array Template info. */ function _add_block_template_part_area_info( $template_info ) { - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { - $theme_data = WP_Theme_JSON_Resolver::get_theme_data()->get_template_parts(); + global $wp_theme_json_resolver; + if ( $wp_theme_json_resolver->theme_has_support() ) { + $theme_data = $wp_theme_json_resolver->get_theme_data()->get_template_parts(); } if ( isset( $theme_data[ $template_info['slug'] ]['area'] ) ) { @@ -1199,6 +1201,7 @@ function wp_is_theme_directory_ignored( $path ) { * @return WP_Error|string Path of the ZIP file or error on failure. */ function wp_generate_block_templates_export_file() { + global $wp_theme_json_resolver; if ( ! class_exists( 'ZipArchive' ) ) { return new WP_Error( 'missing_zip_package', __( 'Zip Export not supported.' ) ); } @@ -1259,9 +1262,9 @@ function wp_generate_block_templates_export_file() { } // Load theme.json into the zip file. - $tree = WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) ); + $tree = $wp_theme_json_resolver->get_theme_data( array(), array( 'with_supports' => false ) ); // Merge with user data. - $tree->merge( WP_Theme_JSON_Resolver::get_user_data() ); + $tree->merge( $wp_theme_json_resolver->get_user_data() ); $theme_json_raw = $tree->get_data(); // If a version is defined, add a schema. diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index ee153eb657abe..f52a630d60d81 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -26,7 +26,7 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var array */ - protected static $blocks_cache = array( + protected $blocks_cache = array( 'core' => array(), 'blocks' => array(), 'theme' => array(), @@ -39,7 +39,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - protected static $core = null; + protected $core = null; /** * Container for data coming from the blocks. @@ -47,7 +47,7 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var WP_Theme_JSON */ - protected static $blocks = null; + protected $blocks = null; /** * Container for data coming from the theme. @@ -55,7 +55,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - protected static $theme = null; + protected $theme = null; /** * Whether or not the theme supports theme.json. @@ -63,7 +63,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var bool */ - protected static $theme_has_support = null; + protected $theme_has_support = null; /** * Container for data coming from the user. @@ -71,7 +71,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var WP_Theme_JSON */ - protected static $user = null; + protected $user = null; /** * Stores the ID of the custom post type @@ -80,7 +80,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var int */ - protected static $user_custom_post_type_id = null; + protected $user_custom_post_type_id = null; /** * Container to keep loaded i18n schema for `theme.json`. @@ -89,7 +89,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 Renamed from `$theme_json_i18n` to `$i18n_schema`. * @var array */ - protected static $i18n_schema = null; + protected $i18n_schema = null; /** * `theme.json` file cache. @@ -97,28 +97,30 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var array */ - protected static $theme_json_file_cache = array(); + protected $theme_json_file_cache = array(); /** * Processes a file that adheres to the theme.json schema * and returns an array with its contents, or a void array if none found. * + * @param string $file_path Path to file. Empty if no file. + * + * @return array Contents that adhere to the theme.json schema. * @since 5.8.0 * @since 6.1.0 Added caching. * - * @param string $file_path Path to file. Empty if no file. - * @return array Contents that adhere to the theme.json schema. */ - protected static function read_json_file( $file_path ) { + protected function read_json_file( $file_path ) { if ( $file_path ) { - if ( array_key_exists( $file_path, static::$theme_json_file_cache ) ) { - return static::$theme_json_file_cache[ $file_path ]; + if ( array_key_exists( $file_path, $this->theme_json_file_cache ) ) { + return $this->theme_json_file_cache[ $file_path ]; } $decoded_file = wp_json_file_decode( $file_path, array( 'associative' => true ) ); if ( is_array( $decoded_file ) ) { - static::$theme_json_file_cache[ $file_path ] = $decoded_file; - return static::$theme_json_file_cache[ $file_path ]; + $this->theme_json_file_cache[ $file_path ] = $decoded_file; + + return $this->theme_json_file_cache[ $file_path ]; } } @@ -128,13 +130,14 @@ protected static function read_json_file( $file_path ) { /** * Returns a data structure used in theme.json translation. * - * @since 5.8.0 + * @return array An array of theme.json fields that are translatable and the keys that are translatable. * @deprecated 5.9.0 * - * @return array An array of theme.json fields that are translatable and the keys that are translatable. + * @since 5.8.0 */ - public static function get_fields_to_translate() { + public function get_fields_to_translate() { _deprecated_function( __METHOD__, '5.9.0' ); + return array(); } @@ -142,63 +145,66 @@ public static function get_fields_to_translate() { * Given a theme.json structure modifies it in place to update certain values * by its translated strings according to the language set by the user. * - * @since 5.8.0 - * - * @param array $theme_json The theme.json to translate. - * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * @param array $theme_json The theme.json to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. * Default 'default'. + * * @return array Returns the modified $theme_json_structure. + * @since 5.8.0 + * */ - protected static function translate( $theme_json, $domain = 'default' ) { - if ( null === static::$i18n_schema ) { - $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); - static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema; + protected function translate( $theme_json, $domain = 'default' ) { + if ( null === $this->i18n_schema ) { + $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); + $this->i18n_schema = null === $i18n_schema ? array() : $i18n_schema; } - return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain ); + return translate_settings_using_i18n_schema( $this->i18n_schema, $theme_json, $domain ); } /** * Returns core's origin config. * + * @return WP_Theme_JSON Entity that holds core data. * @since 5.8.0 * - * @return WP_Theme_JSON Entity that holds core data. */ - public static function get_core_data() { - if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) { - return static::$core; + public function get_core_data() { + if ( null !== $this->core && $this->has_same_registered_blocks( 'core' ) ) { + return $this->core; } - $config = static::read_json_file( __DIR__ . '/theme.json' ); - $config = static::translate( $config ); + $config = $this->read_json_file( __DIR__ . '/theme.json' ); + $config = $this->translate( $config ); /** * Filters the default data provided by WordPress for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ - $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data( $config, 'default' ) ); - $config = $theme_json->get_data(); - static::$core = new WP_Theme_JSON( $config, 'default' ); + $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data( $config, 'default' ) ); + $config = $theme_json->get_data(); + $this->core = new WP_Theme_JSON( $config, 'default' ); - return static::$core; + return $this->core; } /** * Checks whether the registered blocks were already processed for this origin. * - * @since 6.1.0 - * * @param string $origin Data source for which to cache the blocks. * Valid values are 'core', 'blocks', 'theme', and 'user'. + * * @return bool True on success, false otherwise. + * @since 6.1.0 + * */ - protected static function has_same_registered_blocks( $origin ) { + protected function has_same_registered_blocks( $origin ) { // Bail out if the origin is invalid. - if ( ! isset( static::$blocks_cache[ $origin ] ) ) { + if ( ! isset( $this->blocks_cache[ $origin ] ) ) { return false; } @@ -206,13 +212,13 @@ protected static function has_same_registered_blocks( $origin ) { $blocks = $registry->get_all_registered(); // Is there metadata for all currently registered blocks? - $block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] ); + $block_diff = array_diff_key( $blocks, $this->blocks_cache[ $origin ] ); if ( empty( $block_diff ) ) { return true; } foreach ( $blocks as $block_name => $block_type ) { - static::$blocks_cache[ $origin ][ $block_name ] = true; + $this->blocks_cache[ $origin ][ $block_name ] = true; } return false; @@ -226,67 +232,68 @@ protected static function has_same_registered_blocks( $origin ) { * is present in theme.json and in theme supports, * the theme.json takes precedence. * - * @since 5.8.0 - * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. - * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. - * * @param array $deprecated Deprecated. Not used. * @param array $options { * Options arguments. * - * @type bool $with_supports Whether to include theme supports in the data. Default true. + * @type bool $with_supports Whether to include theme supports in the data. Default true. * } * @return WP_Theme_JSON Entity that holds theme data. + * @since 5.8.0 + * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. + * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. + * */ - public static function get_theme_data( $deprecated = array(), $options = array() ) { + public function get_theme_data( $deprecated = array(), $options = array() ) { if ( ! empty( $deprecated ) ) { _deprecated_argument( __METHOD__, '5.9.0' ); } $options = wp_parse_args( $options, array( 'with_supports' => true ) ); - if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) { - $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) ); - $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); + if ( null === $this->theme || ! $this->has_same_registered_blocks( 'theme' ) ) { + $theme_json_data = $this->read_json_file( $this->get_file_path_from_theme( 'theme.json' ) ); + $theme_json_data = $this->translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); /** * Filters the data provided by the theme for global styles and settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) ); $theme_json_data = $theme_json->get_data(); - static::$theme = new WP_Theme_JSON( $theme_json_data ); + $this->theme = new WP_Theme_JSON( $theme_json_data ); } if ( wp_get_theme()->parent() ) { // Get parent theme.json. - $parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) ); - $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) ); + $parent_theme_json_data = $this->read_json_file( $this->get_file_path_from_theme( 'theme.json', true ) ); + $parent_theme_json_data = $this->translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) ); $parent_theme = new WP_Theme_JSON( $parent_theme_json_data ); /* * Merge the child theme.json into the parent theme.json. * The child theme takes precedence over the parent. */ - $parent_theme->merge( static::$theme ); - static::$theme = $parent_theme; + $parent_theme->merge( $this->theme ); + $this->theme = $parent_theme; } if ( ! $options['with_supports'] ) { - return static::$theme; + return $this->theme; } /* * We want the presets and settings declared in theme.json * to override the ones declared via theme supports. * So we take theme supports, transform it to theme.json shape - * and merge the static::$theme upon that. + * and merge the $this->theme upon that. */ $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() ); - if ( ! static::theme_has_support() ) { + if ( ! $this->theme_has_support() ) { if ( ! isset( $theme_support_data['settings']['color'] ) ) { $theme_support_data['settings']['color'] = array(); } @@ -315,29 +322,30 @@ public static function get_theme_data( $deprecated = array(), $options = array() $theme_support_data['settings']['color']['defaultDuotone'] = false; } $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); - $with_theme_supports->merge( static::$theme ); + $with_theme_supports->merge( $this->theme ); + return $with_theme_supports; } /** * Gets the styles for blocks from the block.json file. * + * @return WP_Theme_JSON * @since 6.1.0 * - * @return WP_Theme_JSON */ - public static function get_block_data() { + public function get_block_data() { $registry = WP_Block_Type_Registry::get_instance(); $blocks = $registry->get_all_registered(); - if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) { - return static::$blocks; + if ( null !== $this->blocks && $this->has_same_registered_blocks( 'blocks' ) ) { + return $this->blocks; } $config = array( 'version' => 2 ); foreach ( $blocks as $block_name => $block_type ) { if ( isset( $block_type->supports['__experimentalStyle'] ) ) { - $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] ); + $config['styles']['blocks'][ $block_name ] = $this->remove_json_comments( $block_type->supports['__experimentalStyle'] ); } if ( @@ -353,28 +361,31 @@ public static function get_block_data() { /** * Filters the data provided by the blocks for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_blocks', new WP_Theme_JSON_Data( $config, 'blocks' ) ); $config = $theme_json->get_data(); - static::$blocks = new WP_Theme_JSON( $config, 'blocks' ); - return static::$blocks; + $this->blocks = new WP_Theme_JSON( $config, 'blocks' ); + + return $this->blocks; } /** * When given an array, this will remove any keys with the name `//`. * * @param array $array The array to filter. + * * @return array The filtered array. */ - private static function remove_json_comments( $array ) { + private function remove_json_comments( $array ) { unset( $array['//'] ); foreach ( $array as $k => $v ) { if ( is_array( $v ) ) { - $array[ $k ] = static::remove_json_comments( $v ); + $array[ $k ] = $this->remove_json_comments( $v ); } } @@ -387,19 +398,20 @@ private static function remove_json_comments( $array ) { * * This can also create and return a new draft custom post type. * - * @since 5.9.0 - * - * @param WP_Theme $theme The theme object. If empty, it + * @param WP_Theme $theme The theme object. If empty, it * defaults to the active theme. - * @param bool $create_post Optional. Whether a new custom post + * @param bool $create_post Optional. Whether a new custom post * type should be created if none are * found. Default false. - * @param array $post_status_filter Optional. Filter custom post type by + * @param array $post_status_filter Optional. Filter custom post type by * post status. Default `array( 'publish' )`, * so it only fetches published posts. + * * @return array Custom Post Type for the user's origin config. + * @since 5.9.0 + * */ - public static function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) { + public function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) { if ( ! $theme instanceof WP_Theme ) { $theme = wp_get_theme(); } @@ -432,7 +444,8 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post array( 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', 'post_status' => 'publish', - 'post_title' => 'Custom Styles', // Do not make string translatable, see https://core.trac.wordpress.org/ticket/54518. + 'post_title' => 'Custom Styles', + // Do not make string translatable, see https://core.trac.wordpress.org/ticket/54518. 'post_type' => $post_type_filter, 'post_name' => sprintf( 'wp-global-styles-%s', urlencode( $stylesheet ) ), 'tax_input' => array( @@ -452,17 +465,17 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post /** * Returns the user's origin config. * + * @return WP_Theme_JSON Entity that holds styles for user data. * @since 5.9.0 * - * @return WP_Theme_JSON Entity that holds styles for user data. */ - public static function get_user_data() { - if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) { - return static::$user; + public function get_user_data() { + if ( null !== $this->user && $this->has_same_registered_blocks( 'user' ) ) { + return $this->user; } $config = array(); - $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() ); + $user_cpt = $this->get_user_data_from_wp_global_styles( wp_get_theme() ); if ( array_key_exists( 'post_content', $user_cpt ) ) { $decoded_data = json_decode( $user_cpt['post_content'], true ); @@ -473,12 +486,14 @@ public static function get_user_data() { /** * Filters the data provided by the user for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); $config = $theme_json->get_data(); + return new WP_Theme_JSON( $config, 'custom' ); } @@ -495,11 +510,11 @@ public static function get_user_data() { } /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */ - $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); - $config = $theme_json->get_data(); - static::$user = new WP_Theme_JSON( $config, 'custom' ); + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); + $config = $theme_json->get_data(); + $this->user = new WP_Theme_JSON( $config, 'custom' ); - return static::$user; + return $this->user; } /** @@ -521,26 +536,27 @@ public static function get_user_data() { * for the paragraph block, and the theme has done it as well, * the user preference wins. * - * @since 5.8.0 - * @since 5.9.0 Added user data, removed the `$settings` parameter, - * added the `$origin` parameter. - * @since 6.1.0 Added block data and generation of spacingSizes array. - * * @param string $origin Optional. To what level should we merge data. * Valid values are 'theme' or 'custom'. Default 'custom'. + * * @return WP_Theme_JSON + * @since 6.1.0 Added block data and generation of spacingSizes array. + * + * @since 5.8.0 + * @since 5.9.0 Added user data, removed the `$settings` parameter, + * added the `$origin` parameter. */ - public static function get_merged_data( $origin = 'custom' ) { + public function get_merged_data( $origin = 'custom' ) { if ( is_array( $origin ) ) { _deprecated_argument( __FUNCTION__, '5.9.0' ); } - $result = static::get_core_data(); - $result->merge( static::get_block_data() ); - $result->merge( static::get_theme_data() ); + $result = $this->get_core_data(); + $result->merge( $this->get_block_data() ); + $result->merge( $this->get_theme_data() ); if ( 'custom' === $origin ) { - $result->merge( static::get_user_data() ); + $result->merge( $this->get_user_data() ); } // Generate the default spacingSizes array based on the merged spacingScale settings. @@ -553,41 +569,41 @@ public static function get_merged_data( $origin = 'custom' ) { * Returns the ID of the custom post type * that stores user data. * + * @return integer|null * @since 5.9.0 * - * @return integer|null */ - public static function get_user_global_styles_post_id() { - if ( null !== static::$user_custom_post_type_id ) { - return static::$user_custom_post_type_id; + public function get_user_global_styles_post_id() { + if ( null !== $this->user_custom_post_type_id ) { + return $this->user_custom_post_type_id; } - $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme(), true ); + $user_cpt = $this->get_user_data_from_wp_global_styles( wp_get_theme(), true ); if ( array_key_exists( 'ID', $user_cpt ) ) { - static::$user_custom_post_type_id = $user_cpt['ID']; + $this->user_custom_post_type_id = $user_cpt['ID']; } - return static::$user_custom_post_type_id; + return $this->user_custom_post_type_id; } /** * Determines whether the active theme has a theme.json file. * - * @since 5.8.0 + * @return bool * @since 5.9.0 Added a check in the parent theme. * - * @return bool + * @since 5.8.0 */ - public static function theme_has_support() { - if ( ! isset( static::$theme_has_support ) ) { - static::$theme_has_support = ( - is_readable( static::get_file_path_from_theme( 'theme.json' ) ) || - is_readable( static::get_file_path_from_theme( 'theme.json', true ) ) + public function theme_has_support() { + if ( ! isset( $this->theme_has_support ) ) { + $this->theme_has_support = ( + is_readable( $this->get_file_path_from_theme( 'theme.json' ) ) || + is_readable( $this->get_file_path_from_theme( 'theme.json', true ) ) ); } - return static::$theme_has_support; + return $this->theme_has_support; } /** @@ -595,14 +611,15 @@ public static function theme_has_support() { * * If it isn't, returns an empty string, otherwise returns the whole file path. * - * @since 5.8.0 - * @since 5.9.0 Adapted to work with child themes, added the `$template` argument. - * * @param string $file_name Name of the file. - * @param bool $template Optional. Use template theme directory. Default false. + * @param bool $template Optional. Use template theme directory. Default false. + * * @return string The whole file path or empty if the file doesn't exist. + * @since 5.9.0 Adapted to work with child themes, added the `$template` argument. + * + * @since 5.8.0 */ - protected static function get_file_path_from_theme( $file_name, $template = false ) { + protected function get_file_path_from_theme( $file_name, $template = false ) { $path = $template ? get_template_directory() : get_stylesheet_directory(); $candidate = $path . '/' . $file_name; @@ -618,30 +635,30 @@ protected static function get_file_path_from_theme( $file_name, $template = fals * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables * to reset. */ - public static function clean_cached_data() { - static::$core = null; - static::$blocks = null; - static::$blocks_cache = array( + public function clean_cached_data() { + $this->core = null; + $this->blocks = null; + $this->blocks_cache = array( 'core' => array(), 'blocks' => array(), 'theme' => array(), 'user' => array(), ); - static::$theme = null; - static::$user = null; - static::$user_custom_post_type_id = null; - static::$theme_has_support = null; - static::$i18n_schema = null; + $this->theme = null; + $this->user = null; + $this->user_custom_post_type_id = null; + $this->theme_has_support = null; + $this->i18n_schema = null; } /** * Returns the style variations defined by the theme. * + * @return array * @since 6.0.0 * - * @return array */ - public static function get_style_variations() { + public function get_style_variations() { $variations = array(); $base_directory = get_stylesheet_directory() . '/styles'; if ( is_dir( $base_directory ) ) { @@ -651,7 +668,7 @@ public static function get_style_variations() { foreach ( $nested_html_files as $path => $file ) { $decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) ); if ( is_array( $decoded_file ) ) { - $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); + $translated = $this->translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); $variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data(); if ( empty( $variation['title'] ) ) { $variation['title'] = basename( $path, '.json' ); @@ -660,6 +677,7 @@ public static function get_style_variations() { } } } + return $variations; } diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index b6c8c91b464c0..93e711bc7cfc3 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -24,6 +24,7 @@ * @return array The settings to retrieve. */ function wp_get_global_settings( $path = array(), $context = array() ) { + global $wp_theme_json_resolver; if ( ! empty( $context['block_name'] ) ) { $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); } @@ -33,7 +34,7 @@ function wp_get_global_settings( $path = array(), $context = array() ) { $origin = 'theme'; } - $settings = WP_Theme_JSON_Resolver::get_merged_data( $origin )->get_settings(); + $settings = $wp_theme_json_resolver->get_merged_data( $origin )->get_settings(); return _wp_array_get( $settings, $path, $settings ); } @@ -57,6 +58,7 @@ function wp_get_global_settings( $path = array(), $context = array() ) { * @return array The styles to retrieve. */ function wp_get_global_styles( $path = array(), $context = array() ) { + global $wp_theme_json_resolver; if ( ! empty( $context['block_name'] ) ) { $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); } @@ -66,7 +68,7 @@ function wp_get_global_styles( $path = array(), $context = array() ) { $origin = 'theme'; } - $styles = WP_Theme_JSON_Resolver::get_merged_data( $origin )->get_raw_data()['styles']; + $styles = $wp_theme_json_resolver->get_merged_data( $origin )->get_raw_data()['styles']; return _wp_array_get( $styles, $path, $styles ); } @@ -83,6 +85,7 @@ function wp_get_global_styles( $path = array(), $context = array() ) { * @return string Stylesheet. */ function wp_get_global_stylesheet( $types = array() ) { + global $wp_theme_json_resolver; // Return cached value if it can be used and exists. // It's cached by theme to make sure that theme switching clears the cache. $can_use_cached = ( @@ -100,9 +103,9 @@ function wp_get_global_stylesheet( $types = array() ) { } } - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $tree = $wp_theme_json_resolver->get_merged_data(); - $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); + $supports_theme_json = $wp_theme_json_resolver->theme_has_support(); if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { @@ -168,6 +171,7 @@ function wp_get_global_stylesheet( $types = array() ) { * @return string */ function wp_get_global_styles_svg_filters() { + global $wp_theme_json_resolver; // Return cached value if it can be used and exists. // It's cached by theme to make sure that theme switching clears the cache. $can_use_cached = ( @@ -184,14 +188,14 @@ function wp_get_global_styles_svg_filters() { } } - $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); + $supports_theme_json = $wp_theme_json_resolver->theme_has_support(); $origins = array( 'default', 'theme', 'custom' ); if ( ! $supports_theme_json ) { $origins = array( 'default' ); } - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $tree = $wp_theme_json_resolver->get_merged_data(); $svgs = $tree->get_svg_filters( $origins ); if ( $can_use_cached ) { @@ -208,7 +212,8 @@ function wp_get_global_styles_svg_filters() { * @since 6.1.0 */ function wp_add_global_styles_for_blocks() { - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + global $wp_theme_json_resolver; + $tree = $wp_theme_json_resolver->get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); foreach ( $block_nodes as $metadata ) { $block_css = $tree->get_styles_for_block( $metadata ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php index f1a9d2482a3eb..f867302d745c0 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php @@ -564,6 +564,7 @@ public function get_theme_item_permissions_check( $request ) { * @return WP_REST_Response|WP_Error */ public function get_theme_item( $request ) { + global $wp_theme_json_resolver; if ( wp_get_theme()->get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( @@ -573,7 +574,7 @@ public function get_theme_item( $request ) { ); } - $theme = WP_Theme_JSON_Resolver::get_merged_data( 'theme' ); + $theme = $wp_theme_json_resolver->get_merged_data( 'theme' ); $data = array(); $fields = $this->get_fields_for_response( $request ); @@ -638,6 +639,7 @@ public function get_theme_items_permissions_check( $request ) { // phpcs:ignore * @return WP_REST_Response|WP_Error */ public function get_theme_items( $request ) { + global $wp_theme_json_resolver; if ( wp_get_theme()->get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( @@ -647,7 +649,7 @@ public function get_theme_items( $request ) { ); } - $variations = WP_Theme_JSON_Resolver::get_style_variations(); + $variations = $wp_theme_json_resolver->get_style_variations(); $response = rest_ensure_response( $variations ); return $response; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php index 71dbcb61931f8..4ab08b250bfa7 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php @@ -356,6 +356,7 @@ public function prepare_item_for_response( $item, $request ) { * @return array Links for the given block type. */ protected function prepare_links( $theme ) { + global $wp_theme_json_resolver; $links = array( 'self' => array( 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $theme->get_stylesheet() ) ), @@ -367,9 +368,9 @@ protected function prepare_links( $theme ) { if ( $this->is_same_theme( $theme, wp_get_theme() ) ) { // This creates a record for the active theme if not existent. - $id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); + $id = $wp_theme_json_resolver->get_user_global_styles_post_id(); } else { - $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme ); + $user_cpt = $wp_theme_json_resolver->get_user_data_from_wp_global_styles( $theme ); $id = isset( $user_cpt['ID'] ) ? $user_cpt['ID'] : null; } diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index fd1bf4b6fa93b..68b96e7b4f8c5 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -1468,7 +1468,7 @@ function wp_default_scripts( $scripts ) { * @param WP_Styles $styles */ function wp_default_styles( $styles ) { - global $editor_styles; + global $editor_styles, $wp_theme_json_resolver; // Include an unmodified $wp_version. require ABSPATH . WPINC . '/version.php'; @@ -1618,7 +1618,7 @@ function wp_default_styles( $styles ) { ); // Only load the default layout and margin styles for themes without theme.json file. - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! $wp_theme_json_resolver->theme_has_support() ) { $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; } @@ -3201,12 +3201,13 @@ function _wp_theme_json_webfonts_handler() { * @return array Array of defined webfonts. */ $fn_get_webfonts_from_theme_json = static function() { + $wp_theme_json_resolver = new WP_Theme_JSON_Resolver(); // Get settings from theme.json. - $settings = WP_Theme_JSON_Resolver::get_merged_data()->get_settings(); + $settings = $wp_theme_json_resolver->get_merged_data()->get_settings(); // If in the editor, add webfonts defined in variations. if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { - $variations = WP_Theme_JSON_Resolver::get_style_variations(); + $variations = $wp_theme_json_resolver->get_style_variations(); foreach ( $variations as $variation ) { // Skip if fontFamilies are not defined in the variation. if ( empty( $variation['settings']['typography']['fontFamilies'] ) ) { @@ -3665,7 +3666,8 @@ function _wp_theme_json_webfonts_handler() { * @since 6.1.0 */ function wp_enqueue_classic_theme_styles() { - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( ! $wp_theme_json_resolver->theme_has_support() ) { $suffix = wp_scripts_get_suffix(); wp_register_style( 'classic-theme-styles', '/' . WPINC . "/css/classic-themes$suffix.css", array(), true ); wp_enqueue_style( 'classic-theme-styles' ); @@ -3683,7 +3685,8 @@ function wp_enqueue_classic_theme_styles() { * @return array A filtered array of editor settings. */ function wp_add_editor_classic_theme_styles( $editor_settings ) { - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( $wp_theme_json_resolver->theme_has_support() ) { return $editor_settings; } $suffix = wp_scripts_get_suffix(); diff --git a/src/wp-includes/theme-templates.php b/src/wp-includes/theme-templates.php index 16bd5e2d77212..03f8e39af00d0 100644 --- a/src/wp-includes/theme-templates.php +++ b/src/wp-includes/theme-templates.php @@ -209,7 +209,8 @@ function the_block_template_skip_link() { * @since 5.8.0 */ function wp_enable_block_templates() { - if ( wp_is_block_theme() || WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( wp_is_block_theme() || $wp_theme_json_resolver->theme_has_support() ) { add_theme_support( 'block-templates' ); } } diff --git a/src/wp-settings.php b/src/wp-settings.php index d80d79bb82d6b..1ef0d2a8c9705 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -525,6 +525,14 @@ */ $GLOBALS['wp'] = new WP(); +/** + * WordPress Object + * + * @global WP_Theme_JSON_Resolver $wp_theme_json_resolver Current WordPress environment instance. + * @since 2.0.0 + */ +$GLOBALS['wp_theme_json_resolver'] = new WP_Theme_JSON_Resolver(); + /** * WordPress Widget Factory Object * From 5b6170be9308b98ebde1d34a2e2dec1badf4f9be Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 00:47:54 +0000 Subject: [PATCH 2/6] filters as well. --- src/wp-includes/default-filters.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index e9ca31f5f7908..3982583cc3eeb 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -346,8 +346,11 @@ add_action( 'init', '_register_core_block_patterns_and_categories' ); add_action( 'init', 'check_theme_switched', 99 ); add_action( 'init', array( 'WP_Block_Supports', 'init' ), 22 ); -add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); -add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); + +global $wp_theme_json_resolver; + +add_action( 'switch_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); +add_action( 'start_previewing_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); add_action( 'after_switch_theme', '_wp_menus_changed' ); add_action( 'after_switch_theme', '_wp_sidebars_changed' ); add_action( 'wp_print_styles', 'print_emoji_styles' ); From d9e7d1e29c4981a16dc33baf52511ba8aa0d107d Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 10:12:26 +0000 Subject: [PATCH 3/6] Add cache. --- .../class-wp-theme-json-resolver.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index f52a630d60d81..e87730d94dbed 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -56,6 +56,7 @@ class WP_Theme_JSON_Resolver { * @var WP_Theme_JSON */ protected $theme = null; + protected $data = null; /** * Whether or not the theme supports theme.json. @@ -551,18 +552,19 @@ public function get_merged_data( $origin = 'custom' ) { _deprecated_argument( __FUNCTION__, '5.9.0' ); } - $result = $this->get_core_data(); - $result->merge( $this->get_block_data() ); - $result->merge( $this->get_theme_data() ); - - if ( 'custom' === $origin ) { - $result->merge( $this->get_user_data() ); + if( $this->data ){ + return $this->data; } + $this->data = $this->get_core_data(); + $this->data->merge( $this->get_block_data() ); + $this->data->merge( $this->get_theme_data() ); + $this->data->merge( $this->get_user_data() ); + // Generate the default spacingSizes array based on the merged spacingScale settings. - $result->set_spacing_sizes(); + $this->data->set_spacing_sizes(); - return $result; + return $this->data; } /** @@ -637,6 +639,7 @@ protected function get_file_path_from_theme( $file_name, $template = false ) { */ public function clean_cached_data() { $this->core = null; + $this->data = null; $this->blocks = null; $this->blocks_cache = array( 'core' => array(), From a0bacb5d9f10cabdbfc19b8fec71d2676f9ceee7 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 10:14:17 +0000 Subject: [PATCH 4/6] Remove test file --- src/wp-content/object-cache00.php | 2341 ----------------------------- 1 file changed, 2341 deletions(-) delete mode 100644 src/wp-content/object-cache00.php diff --git a/src/wp-content/object-cache00.php b/src/wp-content/object-cache00.php deleted file mode 100644 index c1fe9755a66e3..0000000000000 --- a/src/wp-content/object-cache00.php +++ /dev/null @@ -1,2341 +0,0 @@ -add( $key, $value, $group, $expiration ); -} - -/** - * Adds a value to cache on a specific server. - * - * Using a server_key value, the object can be stored on a specified server as opposed - * to a random server in the stack. Note that this method will add the key/value to the - * _cache object as part of the runtime cache. It will add it to an array for the - * specified server_key. - * - * @link https://www.php.net/manual/en/memcached.addbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_add_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->addByKey( $server_key, $key, $value, $group, $expiration ); -} - -/** - * Adds multiple values to the cache in one call, if the cache keys don't already exist. - * - * @param array $items Array of keys and values to be added. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param int $expiration Optional. When to expire the cache contents, in seconds. - * Default 0 (no expiration). - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false if cache key and group already exist. - */ -function wp_cache_add_multiple( array $items, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->addMultiple( $items, $group, $expiration ); -} - -/** - * Adds a single server to the list of Memcached servers. - * - * @link https://www.php.net/manual/en/memcached.addserver.php - * - * @param string $host The hostname of the memcache server. - * @param int $port The port on which memcache is running. - * @param int $weight The weight of the server relative to the total weight - * of all the servers in the pool. - * @return bool True on success, false on failure. - */ -function wp_cache_add_server( $host, $port, $weight = 0 ) { - global $wp_object_cache; - return $wp_object_cache->addServer( $host, $port, $weight ); -} - -/** - * Adds an array of servers to the pool. - * - * Each individual server in the array must include a domain and port, with an optional - * weight value: $servers = array( array( '127.0.0.1', 11211, 0 ) ); - * - * @link https://www.php.net/manual/en/memcached.addservers.php - * - * @param array $servers Array of server to register. - * @return bool True on success, false on failure. - */ -function wp_cache_add_servers( $servers ) { - global $wp_object_cache; - return $wp_object_cache->addServers( $servers ); -} - -/** - * Appends data to an existing item. - * - * This method should throw an error if it is used with compressed data. - * This is an expected behavior. Memcached casts the value to be appended to the initial value - * to the type of the initial value. Be careful as this leads to unexpected behavior at times. - * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce - * similar results and improve consistency. It is recommended that appends only occur with data of - * the same type. - * - * @link https://www.php.net/manual/en/memcached.append.php - * - * @param string $key The key under which to store the value. - * @param mixed $value Must be string as appending mixed values is not well-defined. - * @param string $group The group value appended to the $key. - * @return bool True on success, false on failure. - */ -function wp_cache_append( $key, $value, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->append( $key, $value, $group ); -} - -/** - * Appends data to an existing item by server key. - * - * This method should throw an error if it is used with compressed data. - * This is an expected behavior. Memcached casts the value to be appended to the initial value - * to the type of the initial value. Be careful as this leads to unexpected behavior at times. - * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce - * similar results and improve consistency. It is recommended that appends only occur with data of - * the same type. - * - * @link https://www.php.net/manual/en/memcached.appendbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value Must be string as appending mixed values is not well-defined. - * @param string $group The group value appended to the $key. - * @return bool True on success, false on failure. - */ -function wp_cache_append_by_key( $server_key, $key, $value, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->appendByKey( $server_key, $key, $value, $group ); -} - -/** - * Performs a "check and set" to store data. - * - * The set will be successful only if the no other request has updated the value - * since it was fetched by this request. - * - * @link https://www.php.net/manual/en/memcached.cas.php - * - * @param float $cas_token Unique value associated with the existing item. Generated by memcached. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_cas( $cas_token, $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->cas( $cas_token, $key, $value, $group, $expiration ); -} - -/** - * Performs a "check and set" to store data with a server key. - * - * The set will be successful only if the no other request has updated the value - * since it was fetched by this request. - * - * @link https://www.php.net/manual/en/memcached.casbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param float $cas_token Unique value associated with the existing item. Generated by memcached. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_cas_by_key( $cas_token, $server_key, $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->casByKey( $cas_token, $server_key, $key, $value, $group, $expiration ); -} - -/** - * Closes the cache. - * - * This function has ceased to do anything since WordPress 2.5. - * The functionality was removed along with the rest of the persistent cache. - * This does not mean that plugins can't implement this function when they need - * to make sure that the cache is cleaned up after WordPress no longer needs it. - * - * @since 2.0.0 - * - * @return bool Always returns true. - */ -function wp_cache_close() { - return true; -} - -/** - * Decrements a numeric item's value. - * - * @link https://www.php.net/manual/en/memcached.decrement.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to decrement the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ -function wp_cache_decrement( $key, $offset = 1, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->decrement( $key, $offset, $group ); -} - -/** - * Decrements a numeric item's value. - * - * This is the same as wp_cache_decrement(), but kept for backward compatibility. - * The original WordPress caching backends use wp_cache_decr(). - * - * @link https://www.php.net/manual/en/memcached.decrement.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to decrement the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ -function wp_cache_decr( $key, $offset = 1, $group = '' ) { - return wp_cache_decrement( $key, $offset, $group ); -} - -/** - * Removes the item from the cache. - * - * Removes an item from memcached with identified by $key after $time seconds. - * The $time parameter allows an object to be queued for deletion without - * immediately deleting. Between the time that it is queued and the time it's deleted, - * add, replace, and get will fail, but set will succeed. - * - * @link https://www.php.net/manual/en/memcached.delete.php - * - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param int $time The amount of time the server will wait to delete the item in seconds. - * @return bool True on success, false on failure. - */ -function wp_cache_delete( $key, $group = '', $time = 0 ) { - global $wp_object_cache; - return $wp_object_cache->delete( $key, $group, $time ); -} - -/** - * Removes the item from the cache by server key. - * - * Removes an item from memcached with identified by $key after $time seconds. - * The $time parameter allows an object to be queued for deletion without - * immediately deleting. Between the time that it is queued and the time it's deleted, - * add, replace, and get will fail, but set will succeed. - * - * @link https://www.php.net/manual/en/memcached.deletebykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param int $time The amount of time the server will wait to delete the item in seconds. - * @return bool True on success, false on failure. - */ -function wp_cache_delete_by_key( $server_key, $key, $group = '', $time = 0 ) { - global $wp_object_cache; - return $wp_object_cache->deleteByKey( $server_key, $key, $group, $time ); -} - -/** - * Deletes multiple values from the cache in one call. - * - * @param array $keys Array of keys under which the cache to deleted. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false if the contents were not deleted. - */ -function wp_cache_delete_multiple( array $keys, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->deleteMultiple( $keys, $group ); -} - -/** - * Fetches the next result. - * - * @link https://www.php.net/manual/en/memcached.fetch.php - * - * @return array|false The next result on success, false on failure. - */ -function wp_cache_fetch() { - global $wp_object_cache; - return $wp_object_cache->fetch(); -} - -/** - * Fetches all remaining results from the last request. - * - * @link https://www.php.net/manual/en/memcached.fetchall.php - * - * @return array|false The results on success, false on failure. - */ -function wp_cache_fetch_all() { - global $wp_object_cache; - return $wp_object_cache->fetchAll(); -} - -/** - * Invalidates all items in the cache. - * - * @link https://www.php.net/manual/en/memcached.flush.php - * - * @param int $delay Number of seconds to wait before invalidating the items. - * @return bool True on success, false on failure. - */ -function wp_cache_flush( $delay = 0 ) { - global $wp_object_cache; - return $wp_object_cache->flush( $delay ); -} - -/** - * Determines whether the object cache implementation supports a particular feature. - * - * @since 6.1.0 - * - * @param string $feature Name of the feature to check for. Possible values include: - * 'add_multiple', 'set_multiple', 'get_multiple', 'delete_multiple', - * 'flush_runtime', 'flush_group'. - * @return bool True if the feature is supported, false otherwise. - */ -function wp_cache_supports( $feature ) { - return false; -} - -/** - * Retrieves object from cache. - * - * Gets an object from cache based on $key and $group. In order to fully support - * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function - * if either of those values are set. In that case, the request is made directly - * to the memcached server for proper handling of the callback and/or token. - * - * Note that the $deprecated and $found args are only here for compatibility - * with the native wp_cache_get() function. - * - * @link https://www.php.net/manual/en/memcached.get.php - * - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param bool $force Whether or not to force a cache invalidation. - * @param null|bool $found Variable passed by reference to determine if the value was found or not. - * @param null|string $cache_cb Read-through caching callback. - * @param null|float $cas_token The variable to store the CAS token in. - * @return bool|mixed Cached object value. - */ -function wp_cache_get( $key, $group = '', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { - global $wp_object_cache; - - if ( func_num_args() > 4 ) { - return $wp_object_cache->get( $key, $group, $force, $found, '', false, $cache_cb, $cas_token ); - } else { - return $wp_object_cache->get( $key, $group, $force, $found ); - } -} - -/** - * Retrieves object from cache from specified server. - * - * Gets an object from cache based on $key, $group, and $server_key. In order to fully support - * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function - * if either of those values are set. In that case, the request is made directly - * to the memcached server for proper handling of the callback and/or token. - * - * @link https://www.php.net/manual/en/memcached.getbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param bool $force Whether or not to force a cache invalidation. - * @param null|bool $found Variable passed by reference to determine if the value was found or not. - * @param null|string $cache_cb Read-through caching callback. - * @param null|float $cas_token The variable to store the CAS token in. - * @return bool|mixed Cached object value. - */ -function wp_cache_get_by_key( $server_key, $key, $group = '', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { - global $wp_object_cache; - - if ( func_num_args() > 5 ) { - return $wp_object_cache->getByKey( $server_key, $key, $group, $force, $found, $cache_cb, $cas_token ); - } else { - return $wp_object_cache->getByKey( $server_key, $key, $group, $force, $found ); - } -} - -/** - * Requests multiple keys without blocking. - * - * @link https://www.php.net/manual/en/memcached.getdelayed.php - * - * @param string|array $keys Array or string of key(s) to request. - * @param string|array $groups Array or string of group(s) for the key(s). - * See buildKeys for more on how these are handled. - * @param bool $with_cas Whether to request CAS token values also. - * @param null $value_cb The result callback or null. - * @return bool True on success, false on failure. - */ -function wp_cache_get_delayed( $keys, $groups = '', $with_cas = false, $value_cb = null ) { - global $wp_object_cache; - return $wp_object_cache->getDelayed( $keys, $groups, $with_cas, $value_cb ); -} - -/** - * Requests multiple keys without blocking from a specified server. - * - * @link https://www.php.net/manual/en/memcached.getdelayed.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string|array $keys Array or string of key(s) to request. - * @param string|array $groups Array or string of group(s) for the key(s). - * See buildKeys for more on how these are handled. - * @param bool $with_cas Whether to request CAS token values also. - * @param null $value_cb The result callback or null. - * @return bool True on success, false on failure. - */ -function wp_cache_get_delayed_by_key( $server_key, $keys, $groups = '', $with_cas = false, $value_cb = null ) { - global $wp_object_cache; - return $wp_object_cache->getDelayedByKey( $server_key, $keys, $groups, $with_cas, $value_cb ); -} - -/** - * Gets multiple values from memcached in one request. - * - * See the buildKeys method definition to understand the $keys/$groups parameters. - * - * @link https://www.php.net/manual/en/memcached.getmulti.php - * - * @param array $keys Array of keys to retrieve. - * @param string|array $groups If string, used for all keys. - * If arrays, corresponds with the $keys array. - * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. - * @param int $flags The flags for the get operation. - * @return bool|array The array of found items on success, false on failure. - */ -function wp_cache_get_multi( $keys, $groups = '', &$cas_tokens = null, $flags = null ) { - global $wp_object_cache; - - if ( func_num_args() > 2 ) { - return $wp_object_cache->getMulti( $keys, $groups, '', $cas_tokens, $flags ); - } else { - return $wp_object_cache->getMulti( $keys, $groups ); - } -} - -/** - * Gets multiple values from memcached in one request by specified server key. - * - * See the buildKeys method definition to understand the $keys/$groups parameters. - * - * @link https://www.php.net/manual/en/memcached.getmultibykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param array $keys Array of keys to retrieve. - * @param string|array $groups If string, used for all keys. - * If arrays, corresponds with the $keys array. - * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. - * @param int $flags The flags for the get operation. - * @return bool|array The array of found items on success, false on failure. - */ -function wp_cache_get_multi_by_key( $server_key, $keys, $groups = '', &$cas_tokens = null, $flags = null ) { - global $wp_object_cache; - - if ( func_num_args() > 3 ) { - return $wp_object_cache->getMultiByKey( $server_key, $keys, $groups, $cas_tokens, $flags ); - } else { - return $wp_object_cache->getMultiByKey( $server_key, $keys, $groups ); - } -} - -/** - * Retrieves multiple values from the cache in one call. - * - * @param array $keys Array of keys under which the cache contents are stored. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param bool $force Optional. Whether to force an update of the local cache - * from the persistent cache. Default false. - * @return array Array of return values, grouped by key. Each value is either - * the cache contents on success, or false on failure. - */ -function wp_cache_get_multiple( $keys, $group = '', $force = false ) { - global $wp_object_cache; - return $wp_object_cache->getMultiple( $keys, $group, $force ); -} - -/** - * Retrieves a Memcached option value. - * - * @link https://www.php.net/manual/en/memcached.getoption.php - * - * @param int $option One of the Memcached::OPT_* constants. - * @return mixed The value of the requested option on success, false on failure. - */ -function wp_cache_get_option( $option ) { - global $wp_object_cache; - return $wp_object_cache->getOption( $option ); -} - -/** - * Returns the result code of the last option. - * - * @link https://www.php.net/manual/en/memcached.getresultcode.php - * - * @return int Result code of the last Memcached operation. - */ -function wp_cache_get_result_code() { - global $wp_object_cache; - return $wp_object_cache->getResultCode(); -} - -/** - * Return the message describing the result of the last operation. - * - * @link https://www.php.net/manual/en/memcached.getresultmessage.php - * - * @return string Message describing the result of the last Memcached operation. - */ -function wp_cache_get_result_message() { - global $wp_object_cache; - return $wp_object_cache->getResultMessage(); -} - -/** - * Gets server information by key. - * - * @link https://www.php.net/manual/en/memcached.getserverbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @return array Array with host, post, and weight on success, fales on failure. - */ -function wp_cache_get_server_by_key( $server_key ) { - global $wp_object_cache; - return $wp_object_cache->getServerByKey( $server_key ); -} - -/** - * Gets the list of servers in the pool. - * - * @link https://www.php.net/manual/en/memcached.getserverlist.php - * - * @return array The list of all servers in the server pool. - */ -function wp_cache_get_server_list() { - global $wp_object_cache; - return $wp_object_cache->getServerList(); -} - -/** - * Gets server pool statistics. - * - * @link https://www.php.net/manual/en/memcached.getstats.php - * - * @return array Array of server statistics, one entry per server. - */ -function wp_cache_get_stats() { - global $wp_object_cache; - return $wp_object_cache->getStats(); -} - -/** - * Gets server pool memcached version information. - * - * @link https://www.php.net/manual/en/memcached.getversion.php - * - * @return array Array of server versions, one entry per server. - */ -function wp_cache_get_version() { - global $wp_object_cache; - return $wp_object_cache->getVersion(); -} - -/** - * Increments a numeric item's value. - * - * @link https://www.php.net/manual/en/memcached.increment.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to increment the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ -function wp_cache_increment( $key, $offset = 1, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->increment( $key, $offset, $group ); -} - -/** - * Increments a numeric item's value. - * - * This is the same as wp_cache_increment(), but kept for backward compatibility. - * The original WordPress caching backends use wp_cache_incr(). - * - * @link https://www.php.net/manual/en/memcached.increment.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to increment the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ -function wp_cache_incr( $key, $offset = 1, $group = '' ) { - return wp_cache_increment( $key, $offset, $group ); -} - -/** - * Prepends data to an existing item. - * - * This method should throw an error if it is used with compressed data. This is an expected behavior. - * Memcached casts the value to be prepended to the initial value to the type of the initial value. - * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 - * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" - * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been - * mimicked in the internal cache to produce similar results and improve consistency. It is recommended - * that prepends only occur with data of the same type. - * - * @link https://www.php.net/manual/en/memcached.prepend.php - * - * @param string $key The key under which to store the value. - * @param string $value Must be string as prepending mixed values is not well-defined. - * @param string $group The group value prepended to the $key. - * @return bool True on success, false on failure. - */ -function wp_cache_prepend( $key, $value, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->prepend( $key, $value, $group ); -} - -/** - * Appends data to an existing item by server key. - * - * This method should throw an error if it is used with compressed data. This is an expected behavior. - * Memcached casts the value to be prepended to the initial value to the type of the initial value. - * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 - * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" - * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been - * mimicked in the internal cache to produce similar results and improve consistency. It is recommended - * that prepends only occur with data of the same type. - * - * @link https://www.php.net/manual/en/memcached.prependbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $value Must be string as prepending mixed values is not well-defined. - * @param string $group The group value prepended to the $key. - * @return bool True on success, false on failure. - */ -function wp_cache_prepend_by_key( $server_key, $key, $value, $group = '' ) { - global $wp_object_cache; - return $wp_object_cache->prependByKey( $server_key, $key, $value, $group ); -} - -/** - * Replaces a value in cache. - * - * This method is similar to "add"; however, is does not successfully set a value - * if the object's key is not already set in cache. - * - * @link https://www.php.net/manual/en/memcached.replace.php - * - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_replace( $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->replace( $key, $value, $group, $expiration ); -} - -/** - * Replaces a value in cache on a specific server. - * - * This method is similar to "addByKey"; however, is does not successfully set a value - * if the object's key is not already set in cache. - * - * @link https://www.php.net/manual/en/memcached.addbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_replace_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->replaceByKey( $server_key, $key, $value, $group, $expiration ); -} - -/** - * Sets a value in cache. - * - * The value is set whether or not this key already exists in memcached. - * - * @link https://www.php.net/manual/en/memcached.set.php - * - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_set( $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->set( $key, $value, $group, $expiration ); -} - -/** - * Sets a value in cache. - * - * The value is set whether or not this key already exists in memcached. - * - * @link https://www.php.net/manual/en/memcached.set.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_set_by_key( $server_key, $key, $value, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->setByKey( $server_key, $key, $value, $group, $expiration ); -} - -/** - * Sets multiple values to cache at once. - * - * By sending an array of $items to this function, all values are saved at once to - * memcached, reducing the need for multiple requests to memcached. The $items array - * keys and values are what are stored to memcached. The keys in the $items array - * are merged with the $groups array/string value via buildKeys to determine the - * final key for the object. - * - * @param array $items An array of key/value pairs to store on the server. - * @param string|array $groups Group(s) to merge with key(s) in $items. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_set_multi( $items, $groups = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->setMulti( $items, $groups, $expiration ); -} - -/** - * Sets multiple values to cache at once on specified server. - * - * By sending an array of $items to this function, all values are saved at once to - * memcached, reducing the need for multiple requests to memcached. The $items array - * keys and values are what are stored to memcached. The keys in the $items array - * are merged with the $groups array/string value via buildKeys to determine the - * final key for the object. - * - * @param string $server_key The key identifying the server to store the value on. - * @param array $items An array of key/value pairs to store on the server. - * @param string|array $groups Group(s) to merge with key(s) in $items. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ -function wp_cache_set_multi_by_key( $server_key, $items, $groups = 'default', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->setMultiByKey( $server_key, $items, $groups, $expiration ); -} - -/** - * Sets multiple values to the cache in one call. - * - * Differs from wp_cache_add_multiple() in that it will always write data. - * - * @param array $items Array of keys and values to be set. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param int $expiration Optional. When to expire the cache contents, in seconds. - * Default 0 (no expiration). - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false on failure. - */ -function wp_cache_set_multiple( array $items, $group = '', $expiration = 0 ) { - global $wp_object_cache; - return $wp_object_cache->setMultiple( $items, $group, $expiration ); -} - -/** - * Sets a Memcached option. - * - * @link https://www.php.net/manual/en/memcached.setoption.php - * - * @param int $option Option name. - * @param mixed $value Option value. - * @return bool True on success, false on failure. - */ -function wp_cache_set_option( $option, $value ) { - global $wp_object_cache; - return $wp_object_cache->setOption( $option, $value ); -} - -/** - * Switches blog prefix, which changes the cache that is accessed. - * - * @param int $blog_id Blog to switch to. - * @return void - */ -function wp_cache_switch_to_blog( $blog_id ) { - global $wp_object_cache; - return $wp_object_cache->switch_to_blog( $blog_id ); -} - - -/** - * Sets up Object Cache Global and assigns it. - * - * @global WP_Object_Cache $wp_object_cache WordPress Object Cache - * @return void - */ -function wp_cache_init() { - global $wp_object_cache; - $wp_object_cache = new WP_Object_Cache(); -} - -/** - * Adds a group or set of groups to the list of non-persistent groups. - * - * @param string|array $groups A group or an array of groups to add. - * @return void - */ -function wp_cache_add_global_groups( $groups ) { - global $wp_object_cache; - $wp_object_cache->add_global_groups( $groups ); -} - -/** - * Adds a group or set of groups to the list of non-Memcached groups. - * - * @param string|array $groups A group or an array of groups to add. - * @return void - */ -function wp_cache_add_non_persistent_groups( $groups ) { - global $wp_object_cache; - $wp_object_cache->add_non_persistent_groups( $groups ); -} - -// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid -class WP_Object_Cache { - - /** - * Holds the Memcached object. - * - * @var Memcached - */ - public $m; - - /** - * Hold the Memcached server details. - * - * @var array - */ - public $servers; - - /** - * Holds the non-Memcached objects. - * - * @var array - */ - public $cache = array(); - - /** - * List of global groups. - * - * @var array - */ - public $global_groups = array(); - - /** - * List of groups not saved to Memcached. - * - * @var array - */ - public $no_mc_groups = array(); - - /** - * Prefix used for global groups. - * - * @var string - */ - public $global_prefix = ''; - - /** - * Prefix used for non-global groups. - * - * @var string - */ - public $blog_prefix = ''; - - /** - * Instantiates the Memcached class. - * - * Instantiates the Memcached class and returns adds the servers specified - * in the $memcached_servers global array. - * - * @link https://www.php.net/manual/en/memcached.construct.php - * - * @param null $persistent_id To create an instance that persists between requests, - * use persistent_id to specify a unique ID for the instance. - */ - public function __construct( $persistent_id = null ) { - global $memcached_servers, $blog_id, $table_prefix; - - if ( is_null( $persistent_id ) || ! is_string( $persistent_id ) ) { - $this->m = new Memcached(); - } else { - $this->m = new Memcached( $persistent_id ); - } - - if ( isset( $memcached_servers ) ) { - $this->servers = $memcached_servers; - } else { - $this->servers = array( array( 'memcached', 11211 ) ); - } - - $this->addServers( $this->servers ); - - /** - * This approach is borrowed from Sivel and Boren. Use the salt for easy cache invalidation - * and for multi single WP installations on the same server. - */ - if ( ! defined( 'WP_CACHE_KEY_SALT' ) ) { - define( 'WP_CACHE_KEY_SALT', '' ); - } - - // Assign global and blog prefixes for use with keys. - if ( function_exists( 'is_multisite' ) ) { - $this->global_prefix = ( is_multisite() || defined( 'CUSTOM_USER_TABLE' ) && defined( 'CUSTOM_USER_META_TABLE' ) ) ? '' : $table_prefix; - $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':'; - } - - // Setup cacheable values for handling expiration times. - $this->thirty_days = 60 * 60 * 24 * 30; - $this->now = time(); - } - - /** - * Adds a value to cache. - * - * If the specified key already exists, the value is not stored and the function - * returns false. - * - * @link https://www.php.net/manual/en/memcached.add.php - * - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function add( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { - /* - * Ensuring that wp_suspend_cache_addition is defined before calling, because sometimes an advanced-cache.php - * file will load object-cache.php before wp-includes/functions.php is loaded. In those cases, if wp_cache_add - * is called in advanced-cache.php before any more of WordPress is loaded, we get a fatal error because - * wp_suspend_cache_addition will not be defined until wp-includes/functions.php is loaded. - */ - if ( function_exists( 'wp_suspend_cache_addition' ) && wp_suspend_cache_addition() ) { - return false; - } - - $derived_key = $this->buildKey( $key, $group ); - $expiration = $this->sanitize_expiration( $expiration ); - - // If group is a non-Memcached group, save to runtime cache, not Memcached. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - - // Add does not set the value if the key exists; mimic that here. - if ( isset( $this->cache[ $derived_key ] ) ) { - return false; - } - - $this->add_to_internal_cache( $derived_key, $value ); - - return true; - } - - // Save to Memcached. - if ( $by_key ) { - $result = $this->m->addByKey( $server_key, $derived_key, $value, $expiration ); - } else { - $result = $this->m->add( $derived_key, $value, $expiration ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $value ); - } - - return $result; - } - - /** - * Adds a value to cache on a specific server. - * - * Using a server_key value, the object can be stored on a specified server as opposed - * to a random server in the stack. Note that this method will add the key/value to the - * _cache object as part of the runtime cache. It will add it to an array for the - * specified server_key. - * - * @link https://www.php.net/manual/en/memcached.addbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function addByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { - return $this->add( $key, $value, $group, $expiration, $server_key, true ); - } - - /** - * Adds multiple values to cache. - * - * @param array $items Array of keys and values to be added. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param int $expiration Optional. When to expire the cache contents, in seconds. - * Default 0 (no expiration). - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false if cache key and group already exist. - */ - public function addMultiple( array $items, $group = '', $expiration = 0 ) { - $values = array(); - - foreach ( $items as $key => $value ) { - $values[ $key ] = $this->add( $key, $value, $group, $expiration ); - } - - return $values; - } - - /** - * Adds a single server to the list of Memcached servers. - * - * @link https://www.php.net/manual/en/memcached.addserver.php - * - * @param string $host The hostname of the memcache server. - * @param int $port The port on which memcache is running. - * @param int $weight The weight of the server relative to the total weight - * of all the servers in the pool. - * @return bool True on success, false on failure. - */ - public function addServer( $host, $port, $weight = 0 ) { - $host = is_string( $host ) ? $host : '127.0.0.1'; - $port = is_numeric( $port ) && $port > 0 ? $port : 11211; - $weight = is_numeric( $weight ) && $weight > 0 ? $weight : 1; - - return $this->m->addServer( $host, $port, $weight ); - } - - /** - * Adds an array of servers to the pool. - * - * Each individual server in the array must include a domain and port, with an optional - * weight value: $servers = array( array( '127.0.0.1', 11211, 0 ) ); - * - * @link https://www.php.net/manual/en/memcached.addservers.php - * - * @param array $servers Array of server to register. - * @return bool True on success, false on failure. - */ - public function addServers( $servers ) { - if ( ! is_object( $this->m ) ) { - return false; - } - - return $this->m->addServers( $servers ); - } - - /** - * Appends data to an existing item. - * - * This method should throw an error if it is used with compressed data. - * This is an expected behavior. Memcached casts the value to be appended to the initial value - * to the type of the initial value. Be careful as this leads to unexpected behavior at times. - * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce - * similar results and improve consistency. It is recommended that appends only occur with data of - * the same type. - * - * @link https://www.php.net/manual/en/memcached.append.php - * - * @param string $key The key under which to store the value. - * @param mixed $value Must be string as appending mixed values is not well-defined. - * @param string $group The group value appended to the $key. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function append( $key, $value, $group = 'default', $server_key = '', $by_key = false ) { - if ( ! is_string( $value ) && ! is_int( $value ) && ! is_float( $value ) ) { - return false; - } - - $derived_key = $this->buildKey( $key, $group ); - - // If group is a non-Memcached group, append to runtime cache value, not Memcached. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - if ( ! isset( $this->cache[ $derived_key ] ) ) { - return false; - } - - $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'app' ); - $this->add_to_internal_cache( $derived_key, $combined ); - return true; - } - - // Append to Memcached value. - if ( $by_key ) { - $result = $this->m->appendByKey( $server_key, $derived_key, $value ); - } else { - $result = $this->m->append( $derived_key, $value ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'app' ); - $this->add_to_internal_cache( $derived_key, $combined ); - } - - return $result; - } - - /** - * Appends data to an existing item by server key. - * - * This method should throw an error if it is used with compressed data. - * This is an expected behavior. Memcached casts the value to be appended to the initial value - * to the type of the initial value. Be careful as this leads to unexpected behavior at times. - * Due to how memcached treats types, the behavior has been mimicked in the internal cache to produce - * similar results and improve consistency. It is recommended that appends only occur with data of - * the same type. - * - * @link https://www.php.net/manual/en/memcached.appendbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value Must be string as appending mixed values is not well-defined. - * @param string $group The group value appended to the $key. - * @return bool True on success, false on failure. - */ - public function appendByKey( $server_key, $key, $value, $group = 'default' ) { - return $this->append( $key, $value, $group, $server_key, true ); - } - - /** - * Performs a "check and set" to store data. - * - * The set will be successful only if the no other request has updated the value - * since it was fetched by this request. - * - * @link https://www.php.net/manual/en/memcached.cas.php - * - * @param float $cas_token Unique value associated with the existing item. Generated by memcached. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function cas( $cas_token, $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { - $derived_key = $this->buildKey( $key, $group ); - $expiration = $this->sanitize_expiration( $expiration ); - - /** - * If group is a non-Memcached group, save to runtime cache, not Memcached. Note - * that since check and set cannot be emulated in the run time cache, this value - * operation is treated as a normal "add" for no_mc_groups. - */ - if ( in_array( $group, $this->no_mc_groups, true ) ) { - $this->add_to_internal_cache( $derived_key, $value ); - return true; - } - - // Save to Memcached. - if ( $by_key ) { - $result = $this->m->casByKey( $cas_token, $server_key, $derived_key, $value, $expiration ); - } else { - $result = $this->m->cas( $cas_token, $derived_key, $value, $expiration ); - } - - // Store in runtime cache if cas was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $value ); - } - - return $result; - } - - /** - * Performs a "check and set" to store data with a server key. - * - * The set will be successful only if the no other request has updated the value - * since it was fetched by this request. - * - * @link https://www.php.net/manual/en/memcached.casbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param float $cas_token Unique value associated with the existing item. Generated by memcached. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function casByKey( $cas_token, $server_key, $key, $value, $group = 'default', $expiration = 0 ) { - return $this->cas( $cas_token, $key, $value, $group, $expiration, $server_key, true ); - } - - /** - * Decrements a numeric item's value. - * - * @link https://www.php.net/manual/en/memcached.decrement.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to decrement the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ - public function decrement( $key, $offset = 1, $group = 'default' ) { - $derived_key = $this->buildKey( $key, $group ); - - // Decrement values in no_mc_groups. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - - // Only decrement if the key already exists and value is 0 or greater (mimics memcached behavior). - if ( isset( $this->cache[ $derived_key ] ) && $this->cache[ $derived_key ] >= 0 ) { - - // If numeric, subtract; otherwise, consider it 0 and do nothing. - if ( is_numeric( $this->cache[ $derived_key ] ) ) { - $this->cache[ $derived_key ] -= (int) $offset; - } else { - $this->cache[ $derived_key ] = 0; - } - - // Returned value cannot be less than 0. - if ( $this->cache[ $derived_key ] < 0 ) { - $this->cache[ $derived_key ] = 0; - } - - return $this->cache[ $derived_key ]; - } else { - return false; - } - } - - $result = $this->m->decrement( $derived_key, $offset ); - - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $result ); - } - - return $result; - } - - /** - * Decrements a numeric item's value. - * - * Alias for $this->decrement(). Other caching backends use this abbreviated form - * of the function. It *may* cause breakage somewhere, so it is nice to have. - * This function will also allow the core unit tests to pass. - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to decrement the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ - public function decr( $key, $offset = 1, $group = 'default' ) { - return $this->decrement( $key, $offset, $group ); - } - - /** - * Removes the item from the cache. - * - * Removes an item from memcached with identified by $key after $time seconds. - * The $time parameter allows an object to be queued for deletion without - * immediately deleting. Between the time that it is queued and the time it's deleted, - * add, replace, and get will fail, but set will succeed. - * - * @link https://www.php.net/manual/en/memcached.delete.php - * - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param int $time The amount of time the server will wait to delete the item in seconds. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function delete( $key, $group = 'default', $time = 0, $server_key = '', $by_key = false ) { - $derived_key = $this->buildKey( $key, $group ); - - // Remove from no_mc_groups array. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - if ( isset( $this->cache[ $derived_key ] ) ) { - unset( $this->cache[ $derived_key ] ); - } - - return true; - } - - if ( $by_key ) { - $result = $this->m->deleteByKey( $server_key, $derived_key, $time ); - } else { - $result = $this->m->delete( $derived_key, $time ); - } - - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - unset( $this->cache[ $derived_key ] ); - } - - return $result; - } - - /** - * Removes the item from the cache by server key. - * - * Removes an item from memcached with identified by $key after $time seconds. - * The $time parameter allows an object to be queued for deletion without - * immediately deleting. Between the time that it is queued and the time it's deleted, - * add, replace, and get will fail, but set will succeed. - * - * @link https://www.php.net/manual/en/memcached.deletebykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param int $time The amount of time the server will wait to delete the item in seconds. - * @return bool True on success, false on failure. - */ - public function deleteByKey( $server_key, $key, $group = 'default', $time = 0 ) { - return $this->delete( $key, $group, $time, $server_key, true ); - } - - /** - * Removes multiple items from the cache. - * - * @param array $keys Array of keys under which the cache to deleted. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false if the contents were not deleted. - */ - public function deleteMultiple( $keys, $group ) { - $values = array(); - - foreach ( $keys as $key ) { - $values[ $key ] = $this->delete( $key, $group ); - } - - return $values; - } - - /** - * Fetches the next result. - * - * @link https://www.php.net/manual/en/memcached.fetch.php - * - * @return array|false The next result on success, false on failure. - */ - public function fetch() { - return $this->m->fetch(); - } - - /** - * Fetches all remaining results from the last request. - * - * @link https://www.php.net/manual/en/memcached.fetchall.php - * - * @return array|false The results on success, false on failure. - */ - public function fetchAll() { - return $this->m->fetchAll(); - } - - /** - * Invalidates all items in the cache. - * - * @link https://www.php.net/manual/en/memcached.flush.php - * - * @param int $delay Number of seconds to wait before invalidating the items. - * @return bool True on success, false on failure. - */ - public function flush( $delay = 0 ) { - $result = $this->m->flush( $delay ); - - // Only reset the runtime cache if memcached was properly flushed. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->cache = array(); - } - - return $result; - } - - /** - * Retrieves object from cache. - * - * Gets an object from cache based on $key and $group. In order to fully support - * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function - * if either of those values are set. In that case, the request is made directly - * to the memcached server for proper handling of the callback and/or token. - * Note that the $cas_token variable cannot be directly passed to the function. - * The variable needs to be first defined with a non-null value. - * - * If using the $cache_cb argument, the new value will always have an expiration - * of time of 0 (forever). This is a limitation of the Memcached PECL extension. - * - * @link https://www.php.net/manual/en/memcached.get.php - * - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param bool $force Whether or not to force a cache invalidation. - * @param null|bool $found Variable passed by reference to determine if the value was found or not. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @param null|callable $cache_cb Read-through caching callback. - * @param null|float $cas_token The variable to store the CAS token in. - * @return bool|mixed Cached object value. - */ - public function get( $key, $group = 'default', $force = false, &$found = null, $server_key = '', $by_key = false, $cache_cb = null, &$cas_token = null ) { - $derived_key = $this->buildKey( $key, $group ); - - // Assume object is not found. - $found = false; - - // If either $cache_db, or $cas_token is set, must hit Memcached and bypass runtime cache. - if ( func_num_args() > 6 && ! in_array( $group, $this->no_mc_groups, true ) ) { - if ( $by_key ) { - $value = $this->m->getByKey( $server_key, $derived_key, $cache_cb, $cas_token ); - } else { - $value = $this->m->get( $derived_key, $cache_cb, $cas_token ); - } - } else { - if ( isset( $this->cache[ $derived_key ] ) ) { - $found = true; - return is_object( $this->cache[ $derived_key ] ) ? clone $this->cache[ $derived_key ] : $this->cache[ $derived_key ]; - } elseif ( in_array( $group, $this->no_mc_groups, true ) ) { - return false; - } else { - if ( $by_key ) { - $value = $this->m->getByKey( $server_key, $derived_key ); - } else { - $value = $this->m->get( $derived_key ); - } - } - } - - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $value ); - $found = true; - } - - return is_object( $value ) ? clone $value : $value; - } - - /** - * Retrieves object from cache from specified server. - * - * Gets an object from cache based on $key and $group, and $server_key. In order to fully support - * the $cache_cb and $cas_token parameters, the runtime cache is ignored by this function - * if either of those values are set. In that case, the request is made directly - * to the memcached server for proper handling of the callback and/or token. - * Note that the $cas_token variable cannot be directly passed to the function. - * The variable needs to be first defined with a non-null value. - * - * If using the $cache_cb argument, the new value will always have an expiration - * of time of 0 (forever). This is a limitation of the Memcached PECL extension. - * - * @link https://www.php.net/manual/en/memcached.getbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @param bool $force Whether or not to force a cache invalidation. - * @param null|bool $found Variable passed by reference to determine if the value was found or not. - * @param null|string $cache_cb Read-through caching callback. - * @param null|float $cas_token The variable to store the CAS token in. - * @return bool|mixed Cached object value. - */ - public function getByKey( $server_key, $key, $group = 'default', $force = false, &$found = null, $cache_cb = null, &$cas_token = null ) { - /** - * Need to be careful how "get" is called. If you send $cache_cb, and $cas_token, it will hit memcached. - * Only send those args if they were sent to this function. - */ - if ( func_num_args() > 5 ) { - return $this->get( $key, $group, $force, $found, $server_key, true, $cache_cb, $cas_token ); - } else { - return $this->get( $key, $group, $force, $found, $server_key, true ); - } - } - - /** - * Requests multiple keys without blocking. - * - * @link https://www.php.net/manual/en/memcached.getdelayed.php - * - * @param string|array $keys Array or string of key(s) to request. - * @param string|array $groups Array or string of group(s) for the key(s). - * See buildKeys for more on how these are handled. - * @param bool $with_cas Whether to request CAS token values also. - * @param null $value_cb The result callback or null. - * @return bool True on success, false on failure. - */ - public function getDelayed( $keys, $groups = 'default', $with_cas = false, $value_cb = null ) { - $derived_keys = $this->buildKeys( $keys, $groups ); - return $this->m->getDelayed( $derived_keys, $with_cas, $value_cb ); - } - - /** - * Requests multiple keys without blocking from a specified server. - * - * @link https://www.php.net/manual/en/memcached.getdelayed.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string|array $keys Array or string of key(s) to request. - * @param string|array $groups Array or string of group(s) for the key(s). - * See buildKeys for more on how these are handled. - * @param bool $with_cas Whether to request CAS token values also. - * @param null $value_cb The result callback or null. - * @return bool True on success, false on failure. - */ - public function getDelayedByKey( $server_key, $keys, $groups = 'default', $with_cas = false, $value_cb = null ) { - $derived_keys = $this->buildKeys( $keys, $groups ); - return $this->m->getDelayedByKey( $server_key, $derived_keys, $with_cas, $value_cb ); - } - - /** - * Gets multiple values from memcached in one request. - * - * See the buildKeys method definition to understand the $keys/$groups parameters. - * - * @link https://www.php.net/manual/en/memcached.getmulti.php - * - * @param array $keys Array of keys to retrieve. - * @param string|array $groups If string, used for all keys. - * If arrays, corresponds with the $keys array. - * @param string $server_key The key identifying the server to store the value on. - * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. - * @param int $flags The flags for the get operation. - * @return bool|array The array of found items on success, false on failure. - */ - public function getMulti( $keys, $groups = 'default', $server_key = '', &$cas_tokens = null, $flags = null ) { - $derived_keys = $this->buildKeys( $keys, $groups ); - - /** - * If either $cas_tokens, or $flags is set, must hit Memcached and bypass runtime cache. - * Note that this will purposely ignore no_mc_groups values as they cannot handle CAS tokens - * or the special flags; however, if the groups of groups contains a no_mc_group, this is bypassed. - */ - if ( func_num_args() > 3 && ! $this->contains_no_mc_group( $groups ) ) { - if ( ! empty( $server_key ) ) { - $values = $this->m->getMultiByKey( $server_key, $derived_keys, $cas_tokens, $flags ); - } else { - $values = $this->m->getMulti( $derived_keys, $cas_tokens, $flags ); - } - } else { - $values = array(); - $need_to_get = array(); - - // Pull out values from runtime cache, or mark for retrieval. - foreach ( $derived_keys as $key ) { - if ( isset( $this->cache[ $key ] ) ) { - $values[ $key ] = $this->cache[ $key ]; - } else { - $need_to_get[ $key ] = $key; - } - } - - // Get those keys not found in the runtime cache. - if ( ! empty( $need_to_get ) ) { - if ( ! empty( $server_key ) ) { - $result = $this->m->getMultiByKey( $server_key, array_keys( $need_to_get ) ); - } else { - $result = $this->m->getMulti( array_keys( $need_to_get ) ); - } - } - - // Merge with values found in runtime cache. - if ( isset( $result ) && Memcached::RES_SUCCESS === $this->getResultCode() ) { - $values = array_merge( $values, $result ); - } - - // If order should be preserved, reorder now. - if ( ! empty( $need_to_get ) && Memcached::GET_PRESERVE_ORDER === $flags ) { - $ordered_values = array(); - - foreach ( $derived_keys as $key ) { - if ( isset( $values[ $key ] ) ) { - $ordered_values[ $key ] = $values[ $key ]; - } - } - - $values = $ordered_values; - unset( $ordered_values ); - } - } - - // Add the values to the runtime cache. - $this->cache = array_merge( $this->cache, $values ); - - return $values; - } - - /** - * Gets multiple values from memcached in one request by specified server key. - * - * See the buildKeys method definition to understand the $keys/$groups parameters. - * - * @link https://www.php.net/manual/en/memcached.getmultibykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param array $keys Array of keys to retrieve. - * @param string|array $groups If string, used for all keys. - * If arrays, corresponds with the $keys array. - * @param null|array $cas_tokens The variable to store the CAS tokens for the found items. - * @param int $flags The flags for the get operation. - * @return bool|array The array of found items on success, false on failure. - */ - public function getMultiByKey( $server_key, $keys, $groups = 'default', &$cas_tokens = null, $flags = null ) { - /** - * Need to be careful how "getMulti" is called. If you send $cache_cb, and $cas_token, it will hit memcached. - * Only send those args if they were sent to this function. - */ - if ( func_num_args() > 3 ) { - return $this->getMulti( $keys, $groups, $server_key, $cas_tokens, $flags ); - } else { - return $this->getMulti( $keys, $groups, $server_key ); - } - } - - /** - * Get multiple items from the cache. - * - * @param array $keys Array of keys under which the cache contents are stored. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param bool $force Optional. Whether to force an update of the local cache - * from the persistent cache. Default false. - * @return array Array of return values, grouped by key. Each value is either - * the cache contents on success, or false on failure. - */ - public function getMultiple( $keys, $group = '', $force = false ) { - $values = array(); - - foreach ( $keys as $key ) { - $found = null; - $value = $this->get( $key, $group, $force, $found ); - $values[ $key ] = $found ? $value : false; - } - - return $values; - } - - /** - * Retrieves a Memcached option value. - * - * @link https://www.php.net/manual/en/memcached.getoption.php - * - * @param int $option One of the Memcached::OPT_* constants. - * @return mixed The value of the requested option on success, false on failure. - */ - public function getOption( $option ) { - return $this->m->getOption( $option ); - } - - /** - * Returns the result code of the last option. - * - * @link https://www.php.net/manual/en/memcached.getresultcode.php - * - * @return int Result code of the last Memcached operation. - */ - public function getResultCode() { - return $this->m->getResultCode(); - } - - /** - * Return the message describing the result of the last operation. - * - * @link https://www.php.net/manual/en/memcached.getresultmessage.php - * - * @return string Message describing the result of the last Memcached operation. - */ - public function getResultMessage() { - return $this->m->getResultMessage(); - } - - /** - * Gets server information by key. - * - * @link https://www.php.net/manual/en/memcached.getserverbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @return array Array with host, post, and weight on success, false on failure. - */ - public function getServerByKey( $server_key ) { - return $this->m->getServerByKey( $server_key ); - } - - /** - * Gets the list of servers in the pool. - * - * @link https://www.php.net/manual/en/memcached.getserverlist.php - * - * @return array The list of all servers in the server pool. - */ - public function getServerList() { - return $this->m->getServerList(); - } - - /** - * Gets server pool statistics. - * - * @link https://www.php.net/manual/en/memcached.getstats.php - * - * @return array Array of server statistics, one entry per server. - */ - public function getStats() { - return $this->m->getStats(); - } - - /** - * Gets server pool memcached version information. - * - * @link https://www.php.net/manual/en/memcached.getversion.php - * - * @return array Array of server versions, one entry per server. - */ - public function getVersion() { - return $this->m->getVersion(); - } - - /** - * Increments a numeric item's value. - * - * @link https://www.php.net/manual/en/memcached.increment.php - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to increment the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ - public function increment( $key, $offset = 1, $group = 'default' ) { - $derived_key = $this->buildKey( $key, $group ); - - // Increment values in no_mc_groups. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - - // Only increment if the key already exists and the number is currently 0 or greater (mimics memcached behavior). - if ( isset( $this->cache[ $derived_key ] ) && $this->cache[ $derived_key ] >= 0 ) { - - // If numeric, add; otherwise, consider it 0 and do nothing. - if ( is_numeric( $this->cache[ $derived_key ] ) ) { - $this->cache[ $derived_key ] += (int) $offset; - } else { - $this->cache[ $derived_key ] = 0; - } - - // Returned value cannot be less than 0. - if ( $this->cache[ $derived_key ] < 0 ) { - $this->cache[ $derived_key ] = 0; - } - - return $this->cache[ $derived_key ]; - } else { - return false; - } - } - - $result = $this->m->increment( $derived_key, $offset ); - - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $result ); - } - - return $result; - } - - /** - * Alias for $this->incr(). - * - * Certain plugins expect an "incr" method on the $wp_object_cache object (e.g., Batcache). - * Since the original version of this library matched names to the memcached methods, - * the "incr" method was missing. Adding this method restores compatibility with plugins - * expecting an "incr" method. - * - * @param string $key The key under which to store the value. - * @param int $offset The amount by which to increment the item's value. - * @param string $group The group value appended to the $key. - * @return int|bool Item's new value on success, false on failure. - */ - public function incr( $key, $offset = 1, $group = 'default' ) { - return $this->increment( $key, $offset, $group ); - } - - /** - * Prepends data to an existing item. - * - * This method should throw an error if it is used with compressed data. This is an expected behavior. - * Memcached casts the value to be prepended to the initial value to the type of the initial value. - * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 - * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" - * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been - * mimicked in the internal cache to produce similar results and improve consistency. It is recommended - * that prepends only occur with data of the same type. - * - * @link https://www.php.net/manual/en/memcached.prepend.php - * - * @param string $key The key under which to store the value. - * @param string $value Must be string as prepending mixed values is not well-defined. - * @param string $group The group value prepended to the $key. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function prepend( $key, $value, $group = 'default', $server_key = '', $by_key = false ) { - if ( ! is_string( $value ) && ! is_int( $value ) && ! is_float( $value ) ) { - return false; - } - - $derived_key = $this->buildKey( $key, $group ); - - // If group is a non-Memcached group, prepend to runtime cache value, not Memcached. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - if ( ! isset( $this->cache[ $derived_key ] ) ) { - return false; - } - - $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'pre' ); - $this->add_to_internal_cache( $derived_key, $combined ); - return true; - } - - // Append to Memcached value. - if ( $by_key ) { - $result = $this->m->prependByKey( $server_key, $derived_key, $value ); - } else { - $result = $this->m->prepend( $derived_key, $value ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $combined = $this->combine_values( $this->cache[ $derived_key ], $value, 'pre' ); - $this->add_to_internal_cache( $derived_key, $combined ); - } - - return $result; - } - - /** - * Appends data to an existing item by server key. - * - * This method should throw an error if it is used with compressed data. This is an expected behavior. - * Memcached casts the value to be prepended to the initial value to the type of the initial value. - * Be careful as this leads to unexpected behavior at times. For instance, prepending (float) 45.23 - * to (int) 23 will result in 45, because the value is first combined (45.2323) then cast to "integer" - * (the original value), which will be (int) 45. Due to how memcached treats types, the behavior has been - * mimicked in the internal cache to produce similar results and improve consistency. It is recommended - * that prepends only occur with data of the same type. - * - * @link https://www.php.net/manual/en/memcached.prependbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param string $value Must be string as prepending mixed values is not well-defined. - * @param string $group The group value prepended to the $key. - * @return bool True on success, false on failure. - */ - public function prependByKey( $server_key, $key, $value, $group = 'default' ) { - return $this->prepend( $key, $value, $group, $server_key, true ); - } - - /** - * Replaces a value in cache. - * - * This method is similar to "add"; however, is does not successfully set a value - * if the object's key is not already set in cache. - * - * @link https://www.php.net/manual/en/memcached.replace.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function replace( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { - $derived_key = $this->buildKey( $key, $group ); - $expiration = $this->sanitize_expiration( $expiration ); - - // If group is a non-Memcached group, save to runtime cache, not Memcached. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - - // Replace won't save unless the key already exists; mimic this behavior here. - if ( ! isset( $this->cache[ $derived_key ] ) ) { - return false; - } - - $this->cache[ $derived_key ] = $value; - return true; - } - - // Save to Memcached. - if ( $by_key ) { - $result = $this->m->replaceByKey( $server_key, $derived_key, $value, $expiration ); - } else { - $result = $this->m->replace( $derived_key, $value, $expiration ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $value ); - } - - return $result; - } - - /** - * Replaces a value in cache on a specific server. - * - * This method is similar to "addByKey"; however, is does not successfully set a value - * if the object's key is not already set in cache. - * - * @link https://www.php.net/manual/en/memcached.addbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function replaceByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { - return $this->replace( $key, $value, $group, $expiration, $server_key, true ); - } - - /** - * Sets a value in cache. - * - * The value is set whether or not this key already exists in memcached. - * - * @link https://www.php.net/manual/en/memcached.set.php - * - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function set( $key, $value, $group = 'default', $expiration = 0, $server_key = '', $by_key = false ) { - $derived_key = $this->buildKey( $key, $group ); - $expiration = $this->sanitize_expiration( $expiration ); - - // If group is a non-Memcached group, save to runtime cache, not Memcached. - if ( in_array( $group, $this->no_mc_groups, true ) ) { - $this->add_to_internal_cache( $derived_key, $value ); - return true; - } - - // Save to Memcached. - if ( $by_key ) { - $result = $this->m->setByKey( $server_key, $derived_key, $value, $expiration ); - } else { - $result = $this->m->set( $derived_key, $value, $expiration ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->add_to_internal_cache( $derived_key, $value ); - } - - return $result; - } - - /** - * Sets a value in cache on a specific server. - * - * The value is set whether or not this key already exists in memcached. - * - * @link https://www.php.net/manual/en/memcached.setbykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param string $key The key under which to store the value. - * @param mixed $value The value to store. - * @param string $group The group value appended to the $key. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function setByKey( $server_key, $key, $value, $group = 'default', $expiration = 0 ) { - return $this->set( $key, $value, $group, $expiration, $server_key, true ); - } - - /** - * Sets multiple values to cache at once. - * - * By sending an array of $items to this function, all values are saved at once to - * memcached, reducing the need for multiple requests to memcached. The $items array - * keys and values are what are stored to memcached. The keys in the $items array - * are merged with the $groups array/string value via buildKeys to determine the - * final key for the object. - * - * @link https://www.php.net/manual/en/memcached.setmulti.php - * - * @param array $items An array of key/value pairs to store on the server. - * @param string|array $groups Group(s) to merge with key(s) in $items. - * @param int $expiration The expiration time, defaults to 0. - * @param string $server_key The key identifying the server to store the value on. - * @param bool $by_key True to store in internal cache by key; false to not store by key. - * @return bool True on success, false on failure. - */ - public function setMulti( $items, $groups = 'default', $expiration = 0, $server_key = '', $by_key = false ) { - // Build final keys and replace $items keys with the new keys. - $derived_keys = $this->buildKeys( array_keys( $items ), $groups ); - $expiration = $this->sanitize_expiration( $expiration ); - $derived_items = array_combine( $derived_keys, $items ); - - // Do not add to memcached if in no_mc_groups. - foreach ( $derived_items as $derived_key => $value ) { - - // Get the individual item's group. - $key_pieces = explode( ':', $derived_key ); - - // If group is a non-Memcached group, save to runtime cache, not Memcached. - if ( in_array( $key_pieces[1], $this->no_mc_groups, true ) ) { - $this->add_to_internal_cache( $derived_key, $value ); - unset( $derived_items[ $derived_key ] ); - } - } - - // Save to memcached. - if ( $by_key ) { - $result = $this->m->setMultiByKey( $server_key, $derived_items, $expiration ); - } else { - $result = $this->m->setMulti( $derived_items, $expiration ); - } - - // Store in runtime cache if add was successful. - if ( Memcached::RES_SUCCESS === $this->getResultCode() ) { - $this->cache = array_merge( $this->cache, $derived_items ); - } - - return $result; - } - - /** - * Sets multiple values to cache at once on specified server. - * - * By sending an array of $items to this function, all values are saved at once to - * memcached, reducing the need for multiple requests to memcached. The $items array - * keys and values are what are stored to memcached. The keys in the $items array - * are merged with the $groups array/string value via buildKeys to determine the - * final key for the object. - * - * @link https://www.php.net/manual/en/memcached.setmultibykey.php - * - * @param string $server_key The key identifying the server to store the value on. - * @param array $items An array of key/value pairs to store on the server. - * @param string|array $groups Group(s) to merge with key(s) in $items. - * @param int $expiration The expiration time, defaults to 0. - * @return bool True on success, false on failure. - */ - public function setMultiByKey( $server_key, $items, $groups = 'default', $expiration = 0 ) { - return $this->setMulti( $items, $groups, $expiration, $server_key, true ); - } - - /** - * Sets multiple values in cache. - * - * @param array $items Array of keys and values to be set. - * @param string $group Optional. Where the cache contents are grouped. Default empty. - * @param int $expiration Optional. When to expire the cache contents, in seconds. - * Default 0 (no expiration). - * @return bool[] Array of return values, grouped by key. Each value is either - * true on success, or false on failure. - */ - public function setMultiple( array $items, $group = '', $expiration = 0 ) { - $values = array(); - - foreach ( $items as $key => $value ) { - $values[ $key ] = $this->set( $key, $value, $group, $expiration ); - } - - return $values; - } - - /** - * Sets a Memcached option. - * - * @link https://www.php.net/manual/en/memcached.setoption.php - * - * @param int $option Option name. - * @param mixed $value Option value. - * @return bool True on success, false on failure. - */ - public function setOption( $option, $value ) { - return $this->m->setOption( $option, $value ); - } - - /** - * Builds a key for the cached object using the blog_id, key, and group values. - * - * This function is inspired by the original WP Memcached Object cache. - * - * @author Ryan Boren - * @link http://wordpress.org/extend/plugins/memcached/ - * - * @param string $key The key under which to store the value. - * @param string $group The group value appended to the $key. - * @return string - */ - public function buildKey( $key, $group = 'default' ) { - if ( empty( $group ) ) { - $group = 'default'; - } - - if ( false !== array_search( $group, $this->global_groups, true ) ) { - $prefix = $this->global_prefix; - } else { - $prefix = $this->blog_prefix; - } - - return preg_replace( '/\s+/', '', WP_CACHE_KEY_SALT . "$prefix$group:$key" ); - } - - /** - * Creates an array of keys from passed key(s) and group(s). - * - * This function takes a string or array of key(s) and group(s) and combines them into a single dimensional - * array that merges the keys and groups. If the same number of keys and groups exist, the final keys will - * append $groups[n] to $keys[n]. If there are more keys than groups and the $groups parameter is an array, - * $keys[n] will be combined with $groups[n] until $groups runs out of values. 'default' will be used for remaining - * values. If $keys is an array and $groups is a string, all final values will append $groups to $keys[n]. - * If both values are strings, they will be combined into a single string. Note that if more $groups are received - * than $keys, the method will return an empty array. This method is primarily a helper method for methods - * that call memcached with an array of keys. - * - * @param string|array $keys Key(s) to merge with group(s). - * @param string|array $groups Group(s) to merge with key(s). - * @return array Array that combines keys and groups into a single set of memcached keys. - */ - public function buildKeys( $keys, $groups = 'default' ) { - $derived_keys = array(); - - // If strings sent, convert to arrays for proper handling. - if ( ! is_array( $groups ) ) { - $groups = (array) $groups; - } - - if ( ! is_array( $keys ) ) { - $keys = (array) $keys; - } - - // If we have equal numbers of keys and groups, merge $keys[n] and $group[n]. - if ( count( $keys ) === count( $groups ) ) { - for ( $i = 0; $i < count( $keys ); $i++ ) { - $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[ $i ] ); - } - - // If more keys are received than groups, merge $keys[n] and $group[n] - // until no more groups are left; remaining groups are 'default'. - } elseif ( count( $keys ) > count( $groups ) ) { - for ( $i = 0; $i < count( $keys ); $i++ ) { - if ( isset( $groups[ $i ] ) ) { - $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[ $i ] ); - } elseif ( count( $groups ) === 1 ) { - $derived_keys[] = $this->buildKey( $keys[ $i ], $groups[0] ); - } else { - $derived_keys[] = $this->buildKey( $keys[ $i ], 'default' ); - } - } - } - - return $derived_keys; - } - - /** - * Ensures that a proper expiration time is set. - * - * Memcached treats any value over 30 days as a timestamp. If a developer sets the expiration - * for greater than 30 days or less than the current timestamp, the timestamp is in the past - * and the value isn't cached. This function detects values in that range and corrects them. - * - * @param string|int $expiration The dirty expiration time. - * @return string|int The sanitized expiration time. - */ - public function sanitize_expiration( $expiration ) { - if ( $expiration > $this->thirty_days && $expiration <= $this->now ) { - $expiration = $expiration + $this->now; - } - - return $expiration; - } - - /** - * Concatenates two values and casts to type of the first value. - * - * This is used in append and prepend operations to match how these functions are handled - * by memcached. In both cases, whichever value is the original value in the combined value - * will dictate the type of the combined value. - * - * @param mixed $original Original value that dictates the combined type. - * @param mixed $pended Value to combine with original value. - * @param string $direction Either 'pre' or 'app'. - * @return mixed Combined value casted to the type of the first value. - */ - public function combine_values( $original, $pended, $direction ) { - $type = gettype( $original ); - - // Combine the values based on direction of the "pend". - if ( 'pre' === $direction ) { - $combined = $pended . $original; - } else { - $combined = $original . $pended; - } - - // Cast type of combined value. - settype( $combined, $type ); - - return $combined; - } - - /** - * Simple wrapper for saving object to the internal cache. - * - * @param string $derived_key Key to save value under. - * @param mixed $value Object value. - */ - public function add_to_internal_cache( $derived_key, $value ) { - if ( is_object( $value ) ) { - $value = clone $value; - } - - $this->cache[ $derived_key ] = $value; - } - - /** - * Determines if a no_mc_group exists in a group of groups. - * - * @param mixed $groups The groups to search. - * @return bool True if a no_mc_group is present; false if a no_mc_group is not present. - */ - public function contains_no_mc_group( $groups ) { - if ( is_scalar( $groups ) ) { - return in_array( $groups, $this->no_mc_groups, true ); - } - - if ( ! is_array( $groups ) ) { - return false; - } - - foreach ( $groups as $group ) { - if ( in_array( $group, $this->no_mc_groups, true ) ) { - return true; - } - } - - return false; - } - - /** - * Adds global groups. - * - * This function comes straight from the original WP Memcached Object cache. - * - * @author Ryan Boren - * @link http://wordpress.org/extend/plugins/memcached/ - * - * @param array $groups Array of groups. - * @return void - */ - public function add_global_groups( $groups ) { - if ( ! is_array( $groups ) ) { - $groups = (array) $groups; - } - - $this->global_groups = array_merge( $this->global_groups, $groups ); - $this->global_groups = array_unique( $this->global_groups ); - } - - /** - * Adds non-persistent groups. - * - * This function comes straight from the original WP Memcached Object cache. - * - * @author Ryan Boren - * @link http://wordpress.org/extend/plugins/memcached/ - * - * @param array $groups Array of groups. - * @return void - */ - public function add_non_persistent_groups( $groups ) { - if ( ! is_array( $groups ) ) { - $groups = (array) $groups; - } - - $this->no_mc_groups = array_merge( $this->no_mc_groups, $groups ); - $this->no_mc_groups = array_unique( $this->no_mc_groups ); - } - - /** - * Gets a value specifically from the internal, run-time cache, not memcached. - * - * @param int|string $key Key value. - * @param int|string $group Group that the value belongs to. - * @return bool|mixed Value on success, false on failure. - */ - public function get_from_runtime_cache( $key, $group ) { - $derived_key = $this->buildKey( $key, $group ); - - if ( isset( $this->cache[ $derived_key ] ) ) { - return $this->cache[ $derived_key ]; - } - - return false; - } - - /** - * Switches blog prefix, which changes the cache that is accessed. - * - * @param int $blog_id Blog to switch to. - * @return void - */ - public function switch_to_blog( $blog_id ) { - global $table_prefix; - $blog_id = (int) $blog_id; - $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':'; - } -} -// phpcs:enable From 596ea3e6de7fa22e7780a06ac17ab125f7d6d08f Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 12:38:45 +0000 Subject: [PATCH 5/6] Use global --- src/wp-includes/script-loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 68b96e7b4f8c5..24f67c79da1e3 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -3201,7 +3201,7 @@ function _wp_theme_json_webfonts_handler() { * @return array Array of defined webfonts. */ $fn_get_webfonts_from_theme_json = static function() { - $wp_theme_json_resolver = new WP_Theme_JSON_Resolver(); + global $wp_theme_json_resolver; // Get settings from theme.json. $settings = $wp_theme_json_resolver->get_merged_data()->get_settings(); From bcfd7d554b1694581d76dec6665122b572fd5551 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Mon, 31 Oct 2022 21:11:58 +0000 Subject: [PATCH 6/6] Check if. --- src/wp-includes/default-filters.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 3982583cc3eeb..47a39db93842c 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -349,8 +349,10 @@ global $wp_theme_json_resolver; -add_action( 'switch_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); -add_action( 'start_previewing_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); +if( $wp_theme_json_resolver ) { + add_action( 'switch_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); + add_action( 'start_previewing_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); +} add_action( 'after_switch_theme', '_wp_menus_changed' ); add_action( 'after_switch_theme', '_wp_sidebars_changed' ); add_action( 'wp_print_styles', 'print_emoji_styles' );