"Fossies" - the Fresh Open Source Software Archive

Member "serendipity/bundled-libs/voku/simple-cache/src/voku/cache/AdapterFileAbstract.php" (20 Nov 2022, 6555 Bytes) of package /linux/www/serendipity-2.4.0.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AdapterFileAbstract.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.5_vs_2.4.0.

    1 <?php
    2 
    3 declare(strict_types=1);
    4 
    5 namespace voku\cache;
    6 
    7 /**
    8  * AdapterFileSimple: File-adapter (simple)
    9  */
   10 abstract class AdapterFileAbstract implements iAdapter
   11 {
   12     const CACHE_FILE_PREFIX = '__';
   13 
   14     const CACHE_FILE_SUBFIX = '.php.cache';
   15 
   16     /**
   17      * @var bool
   18      */
   19     public $installed = false;
   20 
   21     /**
   22      * @var string
   23      */
   24     protected $cacheDir;
   25 
   26     /**
   27      * @var iSerializer
   28      */
   29     protected $serializer;
   30 
   31     /**
   32      * @var string
   33      */
   34     protected $fileMode = '0755';
   35 
   36     /**
   37      * @param callable|string|null $cacheDir
   38      */
   39     public function __construct($cacheDir = null)
   40     {
   41         $this->serializer = new SerializerIgbinary();
   42 
   43         if (!$cacheDir) {
   44             $cacheDir = \realpath(\sys_get_temp_dir()) . '/simple_php_cache';
   45         }
   46 
   47         if (\is_callable($cacheDir)) {
   48             $this->cacheDir = (string) \call_user_func($cacheDir);
   49         } else {
   50             $this->cacheDir = (string) $cacheDir;
   51         }
   52 
   53         if ($this->createCacheDirectory($this->cacheDir) === true) {
   54             $this->installed = true;
   55         }
   56     }
   57 
   58     /**
   59      * Recursively creates & chmod directories.
   60      *
   61      * @param string $path
   62      *
   63      * @return bool
   64      */
   65     protected function createCacheDirectory($path): bool
   66     {
   67         if (
   68             !$path
   69             ||
   70             $path === '/'
   71             ||
   72             $path === '.'
   73             ||
   74             $path === '\\'
   75         ) {
   76             return false;
   77         }
   78 
   79         // if the directory already exists, just return true
   80         if (\is_dir($path) && \is_writable($path)) {
   81             return true;
   82         }
   83 
   84         // if more than one level, try parent first
   85         if (\dirname($path) !== '.') {
   86             $return = $this->createCacheDirectory(\dirname($path));
   87             // if creating parent fails, we can abort immediately
   88             if (!$return) {
   89                 return false;
   90             }
   91         }
   92 
   93         $mode_dec = \intval($this->fileMode, 8);
   94         $old_umask = \umask(0);
   95 
   96         /** @noinspection PhpUsageOfSilenceOperatorInspection */
   97         if (!@\mkdir($path, $mode_dec) && !\is_dir($path)) {
   98             $return = false;
   99         } else {
  100             $return = true;
  101         }
  102 
  103         if (\is_dir($path) && !\is_writable($path)) {
  104             $return = \chmod($path, $mode_dec);
  105         }
  106 
  107         \umask($old_umask);
  108 
  109         return $return;
  110     }
  111 
  112     /**
  113      * @param string $cacheFileWithPath
  114      *
  115      * @return bool
  116      */
  117     protected function deleteFile($cacheFileWithPath): bool
  118     {
  119         if (\is_file($cacheFileWithPath)) {
  120             return \unlink($cacheFileWithPath);
  121         }
  122 
  123         return false;
  124     }
  125 
  126     /**
  127      * {@inheritdoc}
  128      */
  129     public function exists(string $key): bool
  130     {
  131         $value = $this->get($key);
  132 
  133         return $value !== null;
  134     }
  135 
  136     /**
  137      * {@inheritdoc}
  138      */
  139     abstract public function get(string $key);
  140 
  141     /**
  142      * {@inheritdoc}
  143      */
  144     public function installed(): bool
  145     {
  146         return $this->installed;
  147     }
  148 
  149     /**
  150      * {@inheritdoc}
  151      */
  152     public function remove(string $key): bool
  153     {
  154         $cacheFile = $this->getFileName($key);
  155 
  156         return $this->deleteFile($cacheFile);
  157     }
  158 
  159     /**
  160      * {@inheritdoc}
  161      */
  162     public function removeAll(): bool
  163     {
  164         if (!$this->cacheDir) {
  165             return false;
  166         }
  167 
  168         $return = [];
  169         foreach (new \DirectoryIterator($this->cacheDir) as $fileInfo) {
  170             if (!$fileInfo->isDot()) {
  171                 $return[] = \unlink($fileInfo->getPathname());
  172             }
  173         }
  174 
  175         return \in_array(false, $return, true) === false;
  176     }
  177 
  178     /**
  179      * {@inheritdoc}
  180      */
  181     public function set(string $key, $value): bool
  182     {
  183         return $this->setExpired($key, $value);
  184     }
  185 
  186     /**
  187      * {@inheritdoc}
  188      */
  189     abstract public function setExpired(string $key, $value, int $ttl = 0): bool;
  190 
  191     /**
  192      * @param string $key
  193      *
  194      * @return string
  195      */
  196     protected function getFileName(string $key): string
  197     {
  198         return $this->cacheDir . \DIRECTORY_SEPARATOR . self::CACHE_FILE_PREFIX . $key . self::CACHE_FILE_SUBFIX;
  199     }
  200 
  201     /**
  202      * Set the file-mode for new cache-files.
  203      *
  204      * e.g. '0777', or '0755' ...
  205      *
  206      * @param string $fileMode
  207      *
  208      * @return void
  209      */
  210     public function setFileMode($fileMode)
  211     {
  212         $this->fileMode = $fileMode;
  213     }
  214 
  215     /**
  216      * @param int $ttl
  217      *
  218      * @return bool
  219      */
  220     protected function ttlHasExpired(int $ttl): bool
  221     {
  222         if ($ttl === 0) {
  223             return false;
  224         }
  225 
  226         return \time() > $ttl;
  227     }
  228 
  229     /**
  230      * @param mixed $data
  231      *
  232      * @return bool
  233      */
  234     protected function validateDataFromCache($data): bool
  235     {
  236         if (!\is_array($data)) {
  237             return false;
  238         }
  239 
  240         foreach (['value', 'ttl'] as $missing) {
  241             if (!\array_key_exists($missing, $data)) {
  242                 return false;
  243             }
  244         }
  245 
  246         return true;
  247     }
  248 
  249     /**
  250      * copy&past from https://github.com/webimpress/safe-writer (thx @michalbundyra)
  251      *
  252      * @param string   $file
  253      * @param string   $content
  254      * @param int|null $chmod
  255      *
  256      * @return bool
  257      */
  258     protected function writeFile($file, $content, $chmod = null): bool
  259     {
  260         if (!$file) {
  261             return false;
  262         }
  263 
  264         if ($chmod === null) {
  265             $chmod = \intval($this->fileMode, 8);
  266         }
  267 
  268         $dir = \dirname($file);
  269 
  270         $tmp = \tempnam($dir, 'wsw');
  271         if ($tmp === false) {
  272             throw Exception\RuntimeException::unableToCreateTemporaryFile($dir);
  273         }
  274 
  275         if (\file_put_contents($tmp, $content) === false) {
  276             \unlink($tmp);
  277 
  278             throw Exception\WriteContentException::unableToWriteContent($tmp);
  279         }
  280 
  281         if (\chmod($tmp, $chmod & ~\umask()) === false) {
  282             \unlink($tmp);
  283 
  284             throw Exception\ChmodException::unableToChangeChmod($tmp);
  285         }
  286 
  287         // On windows try again if rename was not successful but target file is writable.
  288         /** @noinspection PhpUsageOfSilenceOperatorInspection */
  289         while (@\rename($tmp, $file) === false) {
  290             if (\is_writable($file) && \stripos(\PHP_OS, 'WIN') === 0) {
  291                 continue;
  292             }
  293             \unlink($tmp);
  294 
  295             throw Exception\RenameException::unableToMoveFile($tmp, $file);
  296         }
  297 
  298         return true;
  299     }
  300 }