1<?php
2
3namespace Mpdf;
4
5use DirectoryIterator;
6
7class Cache
8{
9
10	private $basePath;
11
12	private $cleanupInterval;
13
14	public function __construct($basePath, $cleanupInterval = 3600)
15	{
16		if (!is_int($cleanupInterval) && false !== $cleanupInterval) {
17			throw new \Mpdf\MpdfException('Cache cleanup interval has to be an integer or false');
18		}
19
20		if (!$this->createBasePath($basePath)) {
21			throw new \Mpdf\MpdfException(sprintf('Temporary files directory "%s" is not writable', $basePath));
22		}
23
24		$this->basePath = $basePath;
25		$this->cleanupInterval = $cleanupInterval;
26	}
27
28	protected function createBasePath($basePath)
29	{
30		if (!file_exists($basePath)) {
31			if (!$this->createBasePath(dirname($basePath))) {
32				return false;
33			}
34
35			if (!$this->createDirectory($basePath)) {
36				return false;
37			}
38		}
39
40		if (!is_writable($basePath) || !is_dir($basePath)) {
41			return false;
42		}
43
44		return true;
45	}
46
47	protected function createDirectory($basePath)
48	{
49		if (!mkdir($basePath)) {
50			return false;
51		}
52
53		if (!chmod($basePath, 0777)) {
54			return false;
55		}
56
57		return true;
58	}
59
60	public function tempFilename($filename)
61	{
62		return $this->getFilePath($filename);
63	}
64
65	public function has($filename)
66	{
67		return file_exists($this->getFilePath($filename));
68	}
69
70	public function load($filename)
71	{
72		return file_get_contents($this->getFilePath($filename));
73	}
74
75	public function write($filename, $data)
76	{
77		$tempFile = tempnam($this->basePath, 'cache_tmp_');
78		file_put_contents($tempFile, $data);
79		chmod($tempFile, 0664);
80
81		$path = $this->getFilePath($filename);
82		rename($tempFile, $path);
83
84		return $path;
85	}
86
87	public function remove($filename)
88	{
89		return unlink($this->getFilePath($filename));
90	}
91
92	public function clearOld()
93	{
94		$iterator = new DirectoryIterator($this->basePath);
95
96		/** @var \DirectoryIterator $item */
97		foreach ($iterator as $item) {
98			if (!$item->isDot()
99					&& $item->isFile()
100					&& !$this->isDotFile($item)
101					&& $this->isOld($item)) {
102				unlink($item->getPathname());
103			}
104		}
105	}
106
107	private function getFilePath($filename)
108	{
109		return $this->basePath . '/' . $filename;
110	}
111
112	private function isOld(DirectoryIterator $item)
113	{
114		return $this->cleanupInterval
115			? $item->getMTime() + $this->cleanupInterval < time()
116			: false;
117	}
118
119	public function isDotFile(DirectoryIterator $item)
120	{
121		return substr($item->getFilename(), 0, 1) === '.';
122	}
123}
124