PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/monica/monica/vendor/zendframework/zendframework/library/Zend/Cache/Pattern/CaptureCache.php

https://bitbucket.org/alexandretaz/maniac_divers
PHP | 380 lines | 287 code | 32 blank | 61 comment | 22 complexity | 930925772ae4a836710de8f0989c4e88 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Cache\Pattern;
  10. use Zend\Cache\Exception;
  11. use Zend\Stdlib\ErrorHandler;
  12. class CaptureCache extends AbstractPattern
  13. {
  14. /**
  15. * Start the cache
  16. *
  17. * @param string $pageId Page identifier
  18. * @return void
  19. */
  20. public function start($pageId = null)
  21. {
  22. if ($pageId === null) {
  23. $pageId = $this->detectPageId();
  24. }
  25. $that = $this;
  26. ob_start(function ($content) use ($that, $pageId) {
  27. $that->set($content, $pageId);
  28. // http://php.net/manual/function.ob-start.php
  29. // -> If output_callback returns FALSE original input is sent to the browser.
  30. return false;
  31. });
  32. ob_implicit_flush(false);
  33. }
  34. /**
  35. * Write content to page identity
  36. *
  37. * @param string $content
  38. * @param null|string $pageId
  39. * @throws Exception\LogicException
  40. */
  41. public function set($content, $pageId = null)
  42. {
  43. $publicDir = $this->getOptions()->getPublicDir();
  44. if ($publicDir === null) {
  45. throw new Exception\LogicException("Option 'public_dir' no set");
  46. }
  47. if ($pageId === null) {
  48. $pageId = $this->detectPageId();
  49. }
  50. $path = $this->pageId2Path($pageId);
  51. $file = $path . \DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
  52. $this->createDirectoryStructure($publicDir . \DIRECTORY_SEPARATOR . $path);
  53. $this->putFileContent($publicDir . \DIRECTORY_SEPARATOR . $file, $content);
  54. }
  55. /**
  56. * Get from cache
  57. *
  58. * @param null|string $pageId
  59. * @return bool|string
  60. * @throws Exception\LogicException
  61. * @throws Exception\RuntimeException
  62. */
  63. public function get($pageId = null)
  64. {
  65. $publicDir = $this->getOptions()->getPublicDir();
  66. if ($publicDir === null) {
  67. throw new Exception\LogicException("Option 'public_dir' no set");
  68. }
  69. if ($pageId === null) {
  70. $pageId = $this->detectPageId();
  71. }
  72. $file = $publicDir
  73. . \DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
  74. . \DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
  75. if (file_exists($file)) {
  76. ErrorHandler::start();
  77. $content = file_get_contents($file);
  78. $error = ErrorHandler::stop();
  79. if ($content === false) {
  80. throw new Exception\RuntimeException(
  81. "Failed to read cached pageId '{$pageId}'", 0, $error
  82. );
  83. }
  84. return $content;
  85. }
  86. }
  87. /**
  88. * Checks if a cache with given id exists
  89. *
  90. * @param null|string $pageId
  91. * @throws Exception\LogicException
  92. * @return bool
  93. */
  94. public function has($pageId = null)
  95. {
  96. $publicDir = $this->getOptions()->getPublicDir();
  97. if ($publicDir === null) {
  98. throw new Exception\LogicException("Option 'public_dir' no set");
  99. }
  100. if ($pageId === null) {
  101. $pageId = $this->detectPageId();
  102. }
  103. $file = $publicDir
  104. . \DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
  105. . \DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
  106. return file_exists($file);
  107. }
  108. /**
  109. * Remove from cache
  110. *
  111. * @param null|string $pageId
  112. * @throws Exception\LogicException
  113. * @throws Exception\RuntimeException
  114. * @return bool
  115. */
  116. public function remove($pageId = null)
  117. {
  118. $publicDir = $this->getOptions()->getPublicDir();
  119. if ($publicDir === null) {
  120. throw new Exception\LogicException("Option 'public_dir' no set");
  121. }
  122. if ($pageId === null) {
  123. $pageId = $this->detectPageId();
  124. }
  125. $file = $publicDir
  126. . \DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
  127. . \DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);
  128. if (file_exists($file)) {
  129. ErrorHandler::start();
  130. $res = unlink($file);
  131. $err = ErrorHandler::stop();
  132. if (!$res) {
  133. throw new Exception\RuntimeException(
  134. "Failed to remove cached pageId '{$pageId}'", 0, $err
  135. );
  136. }
  137. return true;
  138. }
  139. return false;
  140. }
  141. /**
  142. * Clear cached pages matching glob pattern
  143. *
  144. * @param string $pattern
  145. * @throws Exception\LogicException
  146. */
  147. public function clearByGlob($pattern = '**')
  148. {
  149. $publicDir = $this->getOptions()->getPublicDir();
  150. if ($publicDir === null) {
  151. throw new Exception\LogicException("Option 'public_dir' no set");
  152. }
  153. $it = new \GlobIterator(
  154. $publicDir . '/' . $pattern,
  155. \GlobIterator::CURRENT_AS_SELF | \GlobIterator::SKIP_DOTS | \GlobIterator::UNIX_PATHS
  156. );
  157. foreach ($it as $pathname => $entry) {
  158. if ($entry->isFile()) {
  159. unlink($pathname);
  160. }
  161. }
  162. }
  163. /**
  164. * Determine the page to save from the request
  165. *
  166. * @throws Exception\RuntimeException
  167. * @return string
  168. */
  169. protected function detectPageId()
  170. {
  171. if (!isset($_SERVER['REQUEST_URI'])) {
  172. throw new Exception\RuntimeException("Can't auto-detect current page identity");
  173. }
  174. return $_SERVER['REQUEST_URI'];
  175. }
  176. /**
  177. * Get filename for page id
  178. *
  179. * @param string $pageId
  180. * @return string
  181. */
  182. protected function pageId2Filename($pageId)
  183. {
  184. if (substr($pageId, -1) === '/') {
  185. return $this->getOptions()->getIndexFilename();
  186. }
  187. return basename($pageId);
  188. }
  189. /**
  190. * Get path for page id
  191. *
  192. * @param string $pageId
  193. * @return string
  194. */
  195. protected function pageId2Path($pageId)
  196. {
  197. if (substr($pageId, -1) == '/') {
  198. $path = rtrim($pageId, '/');
  199. } else {
  200. $path = dirname($pageId);
  201. }
  202. // convert requested "/" to the valid local directory separator
  203. if ('/' != \DIRECTORY_SEPARATOR) {
  204. $path = str_replace('/', \DIRECTORY_SEPARATOR, $path);
  205. }
  206. return $path;
  207. }
  208. /**
  209. * Write content to a file
  210. *
  211. * @param string $file File complete path
  212. * @param string $data Data to write
  213. * @return void
  214. * @throws Exception\RuntimeException
  215. */
  216. protected function putFileContent($file, $data)
  217. {
  218. $options = $this->getOptions();
  219. $locking = $options->getFileLocking();
  220. $perm = $options->getFilePermission();
  221. $umask = $options->getUmask();
  222. if ($umask !== false && $perm !== false) {
  223. $perm = $perm & ~$umask;
  224. }
  225. ErrorHandler::start();
  226. $umask = ($umask !== false) ? umask($umask) : false;
  227. $rs = file_put_contents($file, $data, $locking ? \LOCK_EX : 0);
  228. if ($umask) {
  229. umask($umask);
  230. }
  231. if ($rs === false) {
  232. $err = ErrorHandler::stop();
  233. throw new Exception\RuntimeException(
  234. "Error writing file '{$file}'", 0, $err
  235. );
  236. }
  237. if ($perm !== false && !chmod($file, $perm)) {
  238. $oct = decoct($perm);
  239. $err = ErrorHandler::stop();
  240. throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
  241. }
  242. ErrorHandler::stop();
  243. }
  244. /**
  245. * Creates directory if not already done.
  246. *
  247. * @param string $pathname
  248. * @return void
  249. * @throws Exception\RuntimeException
  250. */
  251. protected function createDirectoryStructure($pathname)
  252. {
  253. // Directory structure already exists
  254. if (file_exists($pathname)) {
  255. return;
  256. }
  257. $options = $this->getOptions();
  258. $perm = $options->getDirPermission();
  259. $umask = $options->getUmask();
  260. if ($umask !== false && $perm !== false) {
  261. $perm = $perm & ~$umask;
  262. }
  263. ErrorHandler::start();
  264. if ($perm === false) {
  265. // build-in mkdir function is enough
  266. $umask = ($umask !== false) ? umask($umask) : false;
  267. $res = mkdir($pathname, ($perm !== false) ? $perm : 0777, true);
  268. if ($umask !== false) {
  269. umask($umask);
  270. }
  271. if (!$res) {
  272. $oct = ($perm === false) ? '777' : decoct($perm);
  273. $err = ErrorHandler::stop();
  274. throw new Exception\RuntimeException(
  275. "mkdir('{$pathname}', 0{$oct}, true) failed", 0, $err
  276. );
  277. }
  278. if ($perm !== false && !chmod($pathname, $perm)) {
  279. $oct = decoct($perm);
  280. $err = ErrorHandler::stop();
  281. throw new Exception\RuntimeException(
  282. "chmod('{$pathname}', 0{$oct}) failed", 0, $err
  283. );
  284. }
  285. } else {
  286. // build-in mkdir function sets permission together with current umask
  287. // which doesn't work well on multo threaded webservers
  288. // -> create directories one by one and set permissions
  289. // find existing path and missing path parts
  290. $parts = array();
  291. $path = $pathname;
  292. while (!file_exists($path)) {
  293. array_unshift($parts, basename($path));
  294. $nextPath = dirname($path);
  295. if ($nextPath === $path) {
  296. break;
  297. }
  298. $path = $nextPath;
  299. }
  300. // make all missing path parts
  301. foreach ($parts as $part) {
  302. $path.= \DIRECTORY_SEPARATOR . $part;
  303. // create a single directory, set and reset umask immediately
  304. $umask = ($umask !== false) ? umask($umask) : false;
  305. $res = mkdir($path, ($perm === false) ? 0777 : $perm, false);
  306. if ($umask !== false) {
  307. umask($umask);
  308. }
  309. if (!$res) {
  310. $oct = ($perm === false) ? '777' : decoct($perm);
  311. $err = ErrorHandler::stop();
  312. throw new Exception\RuntimeException(
  313. "mkdir('{$path}', 0{$oct}, false) failed"
  314. );
  315. }
  316. if ($perm !== false && !chmod($path, $perm)) {
  317. $oct = decoct($perm);
  318. $err = ErrorHandler::stop();
  319. throw new Exception\RuntimeException(
  320. "chmod('{$path}', 0{$oct}) failed"
  321. );
  322. }
  323. }
  324. }
  325. ErrorHandler::stop();
  326. }
  327. }