* @copyright 2008-2017 Alexander Schneider * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 * @version SVN: $id$ * @link http://wordpress.org/extend/plugins/user-access-manager/ */ declare(strict_types=1); namespace UserAccessManager\Cache; use Exception; use UserAccessManager\Config\Config; use UserAccessManager\Config\ConfigFactory; use UserAccessManager\Config\ConfigParameterFactory; use UserAccessManager\Util\Util; use UserAccessManager\Wrapper\Php; use UserAccessManager\Wrapper\Wordpress; /** * Class FileSystemCacheProvider * * @package UserAccessManager\Cache */ class FileSystemCacheProvider implements CacheProviderInterface { const ID = 'FileSystemCacheProvider'; const CONFIG_KEY = 'uam_file_system_cache_provider'; const CONFIG_PATH = 'fs_cache_path'; const CONFIG_METHOD = 'fs_cache_method'; const METHOD_SERIALIZE = 'serialize'; const METHOD_IGBINARY = 'igbinary'; const METHOD_JSON = 'json'; const METHOD_VAR_EXPORT = 'var_export'; /** * @var Php */ private $php; /** * @var Wordpress */ private $wordpress; /** * @var Util */ private $util; /** * @var ConfigFactory */ private $configFactory; /** * @var ConfigParameterFactory */ private $configParameterFactory; /** * @var null|Config */ private $config = null; /** * @var string */ private $path = null; /** * FileSystemCacheProvider constructor. * @param Php $php * @param Wordpress $wordpress * @param Util $util * @param ConfigFactory $configFactory * @param ConfigParameterFactory $configParameterFactory */ public function __construct( Php $php, Wordpress $wordpress, Util $util, ConfigFactory $configFactory, ConfigParameterFactory $configParameterFactory ) { $this->php = $php; $this->wordpress = $wordpress; $this->util = $util; $this->configFactory = $configFactory; $this->configParameterFactory = $configParameterFactory; } /** * Returns the id. * @return string */ public function getId(): string { return self::ID; } /** * Returns the cache path. * @return string * @throws Exception */ private function getPath(): string { if ($this->path === null) { $this->path = $this->getConfig()->getParameterValue(self::CONFIG_PATH); if ($this->util->endsWith($this->path, DIRECTORY_SEPARATOR) === false) { $this->path .= DIRECTORY_SEPARATOR; } } return $this->path; } /** * Initialise the caching path. * @throws Exception */ public function init() { $path = $this->getPath(); if (is_dir($path) === false) { $this->php->mkdir($path, 0775, true); } $htaccessFile = $path . '.htaccess'; if (file_exists($htaccessFile) === false) { file_put_contents($htaccessFile, 'Deny from all'); } } /** * Returns the cache config. * @return Config * @throws Exception */ public function getConfig(): Config { if ($this->config === null) { $this->config = $this->configFactory->createConfig(self::CONFIG_KEY); $selections = [ self::METHOD_SERIALIZE, self::METHOD_JSON, self::METHOD_VAR_EXPORT ]; if ($this->php->functionExists('igbinary_serialize') === true) { $selections[] = self::METHOD_IGBINARY; } $configParameters = [ self::CONFIG_PATH => $this->configParameterFactory->createStringConfigParameter( self::CONFIG_PATH, $this->wordpress->getHomePath() . 'cache/uam' ), self::CONFIG_METHOD => $this->configParameterFactory->createSelectionConfigParameter( self::CONFIG_METHOD, self::METHOD_VAR_EXPORT, $selections ) ]; $this->config->setDefaultConfigParameters($configParameters); } return $this->config; } /** * Returns the caching method. * @return string|null * @throws Exception */ private function getCacheMethod(): ?string { $method = (string) $this->getConfig()->getParameterValue(self::CONFIG_METHOD); if ($method === self::METHOD_IGBINARY && ($this->php->functionExists('igbinary_serialize') === false || $this->php->functionExists('igbinary_unserialize') === false) ) { $method = null; } return $method; } /** * Returns the cache file name with path. * @param string|null $method * @param string $key * @return string * @throws Exception */ private function getCacheFile(?string $method, string $key): string { $cacheFile = $this->getPath() . $key; $cacheFile .= ($method === self::METHOD_VAR_EXPORT) ? '.php' : '.cache'; return $cacheFile; } /** * Adds a value to the cache. * @param string $key * @param mixed $value * @throws Exception */ public function add(string $key, $value) { $method = $this->getCacheMethod(); $cacheFile = $this->getCacheFile($method, $key); if ($method === self::METHOD_SERIALIZE) { $this->php->filePutContents($cacheFile, base64_encode(serialize($value)), LOCK_EX); } elseif ($method === self::METHOD_IGBINARY) { $this->php->filePutContents($cacheFile, $this->php->igbinarySerialize($value), LOCK_EX); } elseif ($method === self::METHOD_JSON) { $this->php->filePutContents($cacheFile, json_encode($value), LOCK_EX); } elseif ($method === self::METHOD_VAR_EXPORT) { $this->php->filePutContents( $cacheFile, "getCacheMethod(); $cacheFile = $this->getCacheFile($method, $key); if ((file_exists($cacheFile) === true)) { if ($method === self::METHOD_SERIALIZE) { return unserialize(base64_decode(file_get_contents($cacheFile))); } elseif ($method === self::METHOD_IGBINARY) { return $this->php->igbinaryUnserialize(file_get_contents($cacheFile)); } elseif ($method === self::METHOD_JSON) { return json_decode(file_get_contents($cacheFile), true); } elseif ($method === self::METHOD_VAR_EXPORT) { $cachedValue = null; /** @noinspection PhpIncludeInspection */ include($cacheFile); return $cachedValue; } } return null; } /** * Invalidates the cache. * @param string $key * @throws Exception */ public function invalidate(string $key) { $method = $this->getCacheMethod(); $cacheFile = $this->getCacheFile($method, $key); if ((file_exists($cacheFile) === true)) { unlink($cacheFile); } } }