src/CacheKeyGen/WpPsrCacheKeyGen.php
<?php
/**
* Class WpPsrCacheKeyGen
*
* @package LeavesAndLove\WpPsrCache
* @license GNU General Public License, version 2
* @link https://github.com/felixarntz/wp-psr-cache
*/
namespace LeavesAndLove\WpPsrCache\CacheKeyGen;
/**
* WordPress PSR cache key generator class.
*
* @since 1.0.0
*/
class WpPsrCacheKeyGen implements WpCacheKeyGen
{
/** @var array List of global cache groups. */
protected $globalGroups = array();
/** @var array List of network cache groups. */
protected $networkGroups = array();
/** @var int Current site ID. */
protected $siteId;
/** @var int Current network ID. */
protected $networkId;
/**
* Constructor.
*
* @since 1.0.0
*
* @param int $siteId Initial site ID.
* @param int $networkId Initial network ID.
*/
public function __construct(int $siteId, int $networkId)
{
$this->switchSiteContext($siteId);
$this->switchNetworkContext($networkId);
}
/**
* Generate the full cache key for a given key and group.
*
* @since 1.0.0
*
* @param string $key A cache key.
* @param string $group A cache group.
* @return string The full cache key to use with cache implementations.
*/
public function generate(string $key, string $group): string
{
switch (true) {
case isset($this->globalGroups[$group]):
$key = 'global.' . $group . '.' . $key;
break;
case isset($this->networkGroups[$group]):
$key = 'network.' . $this->networkId . '.' . $group . '.' . $key;
break;
default:
$key = 'site.' . $this->siteId . '.' . $group . '.' . $key;
}
if (defined('WP_CACHE_KEY_PREFIX') && !empty(WP_CACHE_KEY_PREFIX)) {
$key = WP_CACHE_KEY_PREFIX . '.' . $key;
}
return $this->sanitize($key);
}
/**
* Add cache groups to consider global groups.
*
* @since 1.0.0
*
* @param array $groups The list of groups that are global.
*/
public function addGlobalGroups(array $groups)
{
$groups = array_fill_keys($groups, true);
$this->globalGroups = array_merge($this->globalGroups, $groups);
}
/**
* Gets the list of global groups.
*
* @since 1.0.0
*
* @return array List of global groups.
*/
public function getGlobalGroups(): array
{
return array_keys($this->globalGroups);
}
/**
* Add cache groups to consider network groups.
*
* @since 1.0.0
*
* @param array $groups The list of groups that are network-specific.
*/
public function addNetworkGroups(array $groups)
{
$groups = array_fill_keys($groups, true);
$this->networkGroups = array_merge($this->networkGroups, $groups);
}
/**
* Gets the list of network groups.
*
* @since 1.0.0
*
* @return array List of network groups.
*/
public function getNetworkGroups(): array
{
return array_keys($this->networkGroups);
}
/**
* Switch the site context.
*
* @since 1.0.0
*
* @param int $siteId Site ID to switch the context to.
*/
public function switchSiteContext(int $siteId)
{
$this->siteId = $siteId;
}
/**
* Get the site context.
*
* @since 1.0.0
*
* @return int Site ID of the current context.
*/
public function getSiteContext(): int
{
return $this->siteId;
}
/**
* Switch the network context.
*
* @since 1.0.0
*
* @param int $networkId Network ID to switch the context to.
*/
public function switchNetworkContext(int $networkId)
{
$this->networkId = $networkId;
}
/**
* Get the network context.
*
* @since 1.0.0
*
* @return int Network ID of the current context.
*/
public function getNetworkContext(): int
{
return $this->networkId;
}
/**
* Sanitize a cache key by replacing unsupported characters.
*
* @since 1.0.0
*
* @param string $key A cache key.
* @return string The sanitized cache key.
*/
protected function sanitize(string $key): string
{
// The following characters are not supported in PSR-6/PSR-16.
$replacements = array(
'{' => '',
'}' => '',
'(' => '',
')' => '',
'/' => '',
'\\' => '',
'@' => '',
':' => '.',
' ' => '', // This is not explicitly forbidden, but causes issues easily.
);
return str_replace(array_keys($replacements), array_values($replacements), $key);
}
}