PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/zendframework/zend-cache/src/Pattern/CaptureCache.php

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