/lib/Horde/Kolab/FreeBusy/Cache/File.php

https://github.com/Excito/horde3 · PHP · 317 lines · 169 code · 18 blank · 130 comment · 19 complexity · 96be9d72c8005467ac336650ff150fe9 MD5 · raw file

  1. <?php
  2. /**
  3. * A representation of a cache file.
  4. *
  5. * PHP version 5
  6. *
  7. * @category Kolab
  8. * @package Kolab_FreeBusy
  9. * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
  10. * @author Gunnar Wrobel <wrobel@pardus.de>
  11. * @license http://www.fsf.org/copyleft/lgpl.html LGPL
  12. * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
  13. */
  14. /**
  15. * A representation of a cache file.
  16. *
  17. * $Horde: framework/Kolab_FreeBusy/lib/Horde/Kolab/FreeBusy/Cache/File.php,v 1.1.2.3 2010/10/10 16:26:42 wrobel Exp $
  18. *
  19. * Copyright 2004-2008 Klarälvdalens Datakonsult AB
  20. *
  21. * See the enclosed file COPYING for license information (LGPL). If you
  22. * did not receive this file, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  23. *
  24. * @category Kolab
  25. * @package Kolab_FreeBusy
  26. * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
  27. * @author Gunnar Wrobel <wrobel@pardus.de>
  28. * @license http://www.fsf.org/copyleft/lgpl.html LGPL
  29. * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
  30. */
  31. class Horde_Kolab_FreeBusy_Cache_File {
  32. /**
  33. * The suffix of this cache file.
  34. *
  35. * @var string
  36. */
  37. private $_suffix = '';
  38. /**
  39. * Full path to the cache file.
  40. *
  41. * @var string
  42. */
  43. private $_file;
  44. /**
  45. * Cache file version.
  46. *
  47. * @var int
  48. */
  49. private $_version = 1;
  50. /**
  51. * Construct the Horde_Kolab_FreeBusy_Cache_File instance.
  52. *
  53. * @param string $cache_dir The path to the cache direcory.
  54. * @param string $suffix The suffix of the cache file name.
  55. */
  56. public function __construct(
  57. $cache_dir
  58. ) {
  59. $this->_cache_dir = $cache_dir;
  60. }
  61. /**
  62. * Set the cache file suffix.
  63. *
  64. * @param string $suffix The suffix.
  65. *
  66. * @return NULL
  67. */
  68. protected function setSuffix($suffix)
  69. {
  70. $this->_suffix = $suffix;
  71. }
  72. /**
  73. * Set the version expected for the cached data.
  74. *
  75. * @param int $version The version number.
  76. *
  77. * @return NULL
  78. */
  79. protected function setVersion($version)
  80. {
  81. $this->_version = $version;
  82. }
  83. /**
  84. * Set the partial represented by this cache file.
  85. *
  86. * @param Horde_Kolab_FreeBusy_Cache_Partial $partial The partial.
  87. *
  88. * @return NULL
  89. */
  90. public function setPartial(
  91. Horde_Kolab_FreeBusy_Cache_Partial $partial
  92. ) {
  93. $this->setFilename($partial->getId());
  94. }
  95. /**
  96. * Set the full path to the cache file.
  97. *
  98. * @param string $filename The file name of the cache file.
  99. *
  100. * @return NULL
  101. */
  102. public function setFilename($filename)
  103. {
  104. if ($this->_suffix === null) {
  105. throw new Horde_Kolab_FreeBusy_Exception(
  106. 'You need to set the cache file suffix first!'
  107. );
  108. }
  109. $this->_file = $this->_cache_dir . '/' . $filename . '.' . $this->_suffix;
  110. }
  111. /**
  112. * Get the full path to the cache file.
  113. *
  114. * @return string The full path to the file.
  115. */
  116. public function getFile()
  117. {
  118. if ($this->_file === null) {
  119. throw new Horde_Kolab_FreeBusy_Exception(
  120. 'No partial has been associated with this file cache yet!'
  121. );
  122. }
  123. return $this->_file;
  124. }
  125. /**
  126. * Clean the cache file contents.
  127. *
  128. * @return NULL
  129. *
  130. * @throws Horde_Kolab_FreeBusy_Exception In case cleaning the cache file
  131. * failed.
  132. */
  133. public function delete()
  134. {
  135. if (file_exists($this->getFile())) {
  136. if (!@unlink($this->getFile())) {
  137. throw new Horde_Kolab_FreeBusy_Exception(
  138. sprintf(
  139. "Failed removing file %s: %s",
  140. $this->getFile(),
  141. $this->_describeLastError()
  142. )
  143. );
  144. }
  145. }
  146. }
  147. /**
  148. * Store data in the cache file.
  149. *
  150. * @param mixed $data A reference to the data object.
  151. *
  152. * @return NULL
  153. *
  154. * @throws Horde_Kolab_FreeBusy_Exception In case storing the data failed.
  155. */
  156. public function store(&$data)
  157. {
  158. /* Create directories if missing */
  159. $fbdirname = dirname($this->getFile());
  160. if (!is_dir($fbdirname)) {
  161. $this->_makeTree($fbdirname);
  162. }
  163. /* Store the cache data */
  164. if (!$fh = fopen($this->getFile(), 'w')) {
  165. throw new Horde_Kolab_FreeBusy_Exception(
  166. sprintf(
  167. "Failed creating cache file %s: %s",
  168. $this->getFile(),
  169. $this->_describeLastError()
  170. )
  171. );
  172. }
  173. fwrite(
  174. $fh,
  175. serialize(
  176. array(
  177. 'version' => $this->_version,
  178. 'data' => $data)
  179. )
  180. );
  181. fclose($fh);
  182. }
  183. /**
  184. * Load data from the cache file.
  185. *
  186. * @return mixed The data retrieved from the cache file.
  187. *
  188. * @throws Horde_Kolab_FreeBusy_Exception In case reading the cached data failed.
  189. */
  190. public function load()
  191. {
  192. if (($file = @file_get_contents($this->getFile())) === false) {
  193. throw new Horde_Kolab_FreeBusy_Exception(
  194. sprintf(
  195. "%s failed reading cache file %s: %s",
  196. get_class($this),
  197. $this->getFile(),
  198. $this->_describeLastError()
  199. )
  200. );
  201. }
  202. if (!$cache = @unserialize($file)) {
  203. throw new Horde_Kolab_FreeBusy_Exception(
  204. sprintf(
  205. "%s failed to unserialize cache data from file %s!",
  206. get_class($this),
  207. $this->getFile(),
  208. $this->_describeLastError()
  209. )
  210. );
  211. }
  212. if (!isset($cache['version'])) {
  213. throw new Horde_Kolab_FreeBusy_Exception(
  214. sprintf(
  215. "Cache file %s lacks version data!",
  216. $this->getFile()
  217. )
  218. );
  219. }
  220. $this->_version = $cache['version'];
  221. if (!isset($cache['data'])) {
  222. throw new Horde_Kolab_FreeBusy_Exception(
  223. sprintf(
  224. "Cache file %s lacks data!",
  225. $this->getFile()
  226. )
  227. );
  228. }
  229. if ($cache['version'] != $this->_version) {
  230. throw new Horde_Kolab_FreeBusy_Exception(
  231. sprintf(
  232. "Cache file %s has version %s while %s is required!",
  233. $this->getFile(),
  234. $cache['version'],
  235. $this->_version
  236. )
  237. );
  238. }
  239. return $cache['data'];
  240. }
  241. /**
  242. * Return the last modification date of the cache file.
  243. *
  244. * @return int The last modification date.
  245. */
  246. public function getMtime()
  247. {
  248. if (file_exists($this->getFile())) {
  249. return filemtime($this->getFile());
  250. } else {
  251. return -1;
  252. }
  253. }
  254. /**
  255. * Generate a tree of directories.
  256. *
  257. * @param string $dirname The path to a directory that should exist.
  258. *
  259. * @return NULL
  260. *
  261. * @throws Horde_Kolab_FreeBusy_Exception In case creating the tree failed.
  262. */
  263. private function _maketree($dirname)
  264. {
  265. $base = substr($dirname, 0, strrpos($dirname, '/'));
  266. $base = str_replace(".", "^", $base);
  267. if (!empty($base) && !is_dir($base)) {
  268. $this->_maketree($base);
  269. }
  270. if (!file_exists($dirname)) {
  271. if (!@mkdir($dirname, 0755)) {
  272. throw new Horde_Kolab_FreeBusy_Exception(
  273. sprintf(
  274. "Error creating directory %s: %s",
  275. $dirname,
  276. $this->_describeLastError()
  277. )
  278. );
  279. }
  280. }
  281. }
  282. /**
  283. * Return a descriptive string for the last error.
  284. *
  285. * @return string An error string.
  286. *
  287. * @todo Check how to do this with H4 (exceptions).
  288. */
  289. private function _describeLastError()
  290. {
  291. $error = error_get_last();
  292. return sprintf(
  293. '%s [line %s in %s]',
  294. $error['message'],
  295. $error['line'],
  296. $error['file']
  297. );
  298. }
  299. }