1<?php
2
3/**
4 * Swift Mailer disk runtime cache
5 * Please read the LICENSE file
6 * @author Chris Corbyn <chris@w3style.co.uk>
7 * @package Swift_Cache
8 * @license GNU Lesser General Public License
9 */
10
11require_once dirname(__FILE__) . "/../ClassLoader.php";
12Swift_ClassLoader::load("Swift_Cache");
13
14/**
15 * Caches data in files on disk - this is the best approach if possible
16 * @package Swift_Cache
17 * @author Chris Corbyn <chris@w3style.co.uk>
18 */
19class Swift_Cache_Disk extends Swift_Cache
20{
21  /**
22   * Open file handles
23   * @var array
24   */
25  protected $open = array();
26  /**
27   * The prefix to prepend to files
28   * @var string
29   */
30  protected $prefix;
31  /**
32   * The save path on disk
33   * @var string
34   */
35  protected static $save_path = "/tmp";
36
37  /**
38   * Ctor
39   */
40  public function __construct()
41  {
42    $this->prefix = md5(uniqid(microtime(), true));
43  }
44  /**
45   * Set the save path of the disk - this is a global setting and called statically!
46   * @param string The path to a writable directory
47   */
48  public static function setSavePath($path="/tmp")
49  {
50    self::$save_path = realpath($path);
51  }
52  /**
53   * Write data to the cache
54   * @param string The cache key
55   * @param string The data to write
56   */
57  public function write($key, $data)
58  {
59    $handle = fopen(self::$save_path . "/" . $this->prefix . $key, "ab");
60    if (false === fwrite($handle, $data))
61    {
62      Swift_ClassLoader::load("Swift_FileException");
63      throw new Swift_FileException("Disk Caching failed.  Tried to write to file at [" .
64        self::$save_path . "/" . $this->prefix . $key . "] but failed.  Check the permissions, or don't use disk caching.");
65    }
66    fclose($handle);
67  }
68  /**
69   * Clear the cached data (unlink)
70   * @param string The cache key
71   */
72  public function clear($key)
73  {
74    @unlink(self::$save_path . "/" . $this->prefix . $key);
75  }
76  /**
77   * Check if data is cached for $key
78   * @param string The cache key
79   * @return boolean
80   */
81  public function has($key)
82  {
83    return file_exists(self::$save_path . "/" . $this->prefix . $key);
84  }
85  /**
86   * Read data from the cache for $key
87   * @param string The cache key
88   * @param int The number of bytes to read
89   * @return string
90   */
91  public function read($key, $size=null)
92  {
93    if ($size === null) $size = 8190;
94    if (!$this->has($key)) return false;
95
96    if (!isset($this->open[$key]))
97    {
98      $this->open[$key] = fopen(self::$save_path . "/" . $this->prefix . $key, "rb");
99    }
100    if (feof($this->open[$key]))
101    {
102      fclose($this->open[$key]);
103      unset($this->open[$key]);
104      return false;
105    }
106    $ret = fread($this->open[$key], $size);
107    if ($ret !== false)
108    {
109      return $ret;
110    }
111    else
112    {
113      fclose($this->open[$key]);
114      unset($this->open[$key]);
115      return false;
116    }
117  }
118  /**
119   * Dtor.
120   * Clear out cached data at end of script execution or cache destruction
121   */
122  public function __destruct()
123  {
124    $list = glob(self::$save_path . "/" . $this->prefix . "*");
125    foreach ((array)$list as $f)
126    {
127      @unlink($f);
128    }
129  }
130}
131