/src/Gaufrette/StreamWrapper.php

https://bitbucket.org/ajalovec/gaufrette · PHP · 272 lines · 160 code · 43 blank · 69 comment · 15 complexity · 3ba0a3170770d0e7aa719e656ce5eb9e MD5 · raw file

  1. <?php
  2. namespace Gaufrette;
  3. /**
  4. * Stream wrapper class for the Gaufrette filesystems
  5. *
  6. * @author Antoine Hérault <antoine.herault@gmail.com>
  7. * @author Leszek Prabucki <leszek.prabucki@gmail.com>
  8. */
  9. class StreamWrapper
  10. {
  11. private static $filesystemMap;
  12. private $stream;
  13. /**
  14. * Defines the filesystem map
  15. *
  16. * @param FilesystemMap $map
  17. */
  18. public static function setFilesystemMap(FilesystemMap $map)
  19. {
  20. static::$filesystemMap = $map;
  21. }
  22. /**
  23. * Returns the filesystem map
  24. *
  25. * @return FilesystemMap $map
  26. */
  27. public static function getFilesystemMap()
  28. {
  29. if (null === static::$filesystemMap) {
  30. static::$filesystemMap = static::createFilesystemMap();
  31. }
  32. return static::$filesystemMap;
  33. }
  34. /**
  35. * Registers the stream wrapper to handle the specified scheme
  36. *
  37. * @param string $scheme Default is gaufrette
  38. */
  39. public static function register($scheme = 'gaufrette')
  40. {
  41. static::streamWrapperUnregister($scheme);
  42. if (! static::streamWrapperRegister($scheme, __CLASS__)) {
  43. throw new \RuntimeException(sprintf(
  44. 'Could not register stream wrapper class %s for scheme %s.',
  45. __CLASS__,
  46. $scheme
  47. ));
  48. }
  49. }
  50. /**
  51. * @return FilesystemMap
  52. */
  53. protected static function createFilesystemMap()
  54. {
  55. return new FilesystemMap();
  56. }
  57. /**
  58. * @param string $scheme - protocol scheme
  59. */
  60. protected static function streamWrapperUnregister($scheme)
  61. {
  62. return @stream_wrapper_unregister($scheme);
  63. }
  64. /**
  65. * @param string $scheme - protocol scheme
  66. * @param string $className
  67. */
  68. protected static function streamWrapperRegister($scheme, $className)
  69. {
  70. return stream_wrapper_register($scheme, $className);
  71. }
  72. public function stream_open($path, $mode)
  73. {
  74. $this->stream = $this->createStream($path);
  75. return $this->stream->open($this->createStreamMode($mode));
  76. }
  77. /**
  78. * @param int $bytes
  79. * @return mixed
  80. */
  81. public function stream_read($bytes)
  82. {
  83. if ($this->stream) {
  84. return $this->stream->read($bytes);
  85. }
  86. return false;
  87. }
  88. /**
  89. * @param string $data
  90. * @return int
  91. */
  92. public function stream_write($data)
  93. {
  94. if ($this->stream) {
  95. return $this->stream->write($data);
  96. }
  97. return 0;
  98. }
  99. public function stream_close()
  100. {
  101. if ($this->stream) {
  102. $this->stream->close();
  103. }
  104. }
  105. /**
  106. * @return boolean
  107. */
  108. public function stream_flush()
  109. {
  110. if ($this->stream) {
  111. return $this->stream->flush();
  112. }
  113. return false;
  114. }
  115. /**
  116. * @param int $offset
  117. * @param int $whence - one of values [SEEK_SET, SEEK_CUR, SEEK_END]
  118. * @return boolean
  119. */
  120. public function stream_seek($offset, $whence = SEEK_SET)
  121. {
  122. if ($this->stream) {
  123. return $this->stream->seek($offset, $whence);
  124. }
  125. return false;
  126. }
  127. /**
  128. * @return mixed
  129. */
  130. public function stream_tell()
  131. {
  132. if ($this->stream) {
  133. return $this->stream->tell();
  134. }
  135. return false;
  136. }
  137. /**
  138. * @return boolean
  139. */
  140. public function stream_eof()
  141. {
  142. if ($this->stream) {
  143. return $this->stream->eof();
  144. }
  145. return true;
  146. }
  147. /**
  148. * @return mixed
  149. */
  150. public function stream_stat()
  151. {
  152. if ($this->stream) {
  153. return $this->stream->stat();
  154. }
  155. return false;
  156. }
  157. /**
  158. * @param string $path
  159. * @param int $flags
  160. * @return mixed
  161. * @todo handle $flags parameter
  162. */
  163. public function url_stat($path, $flags)
  164. {
  165. $stream = $this->createStream($path);
  166. try {
  167. $stream->open($this->createStreamMode('r+'));
  168. } catch (\RuntimeException $e) {
  169. return false;
  170. }
  171. return $stream->stat();
  172. }
  173. /**
  174. * @param string $path
  175. * @return mixed
  176. */
  177. public function unlink($path)
  178. {
  179. $stream = $this->createStream($path);
  180. try {
  181. $stream->open($this->createStreamMode('w+'));
  182. } catch (\RuntimeException $e) {
  183. return false;
  184. }
  185. return $stream->unlink();
  186. }
  187. /**
  188. * @return mixed
  189. */
  190. public function stream_cast($castAs)
  191. {
  192. if ($this->stream) {
  193. return $this->stream->cast($castAs);
  194. }
  195. return false;
  196. }
  197. protected function createStream($path)
  198. {
  199. $parts = array_merge(
  200. array(
  201. 'scheme' => null,
  202. 'host' => null,
  203. 'path' => null,
  204. 'query' => null,
  205. 'fragment' => null,
  206. ),
  207. parse_url($path) ?: array()
  208. );
  209. $domain = $parts['host'];
  210. $key = substr($parts['path'], 1);
  211. if (null !== $parts['query']) {
  212. $key.= '?' . $parts['query'];
  213. }
  214. if (null !== $parts['fragment']) {
  215. $key.= '#' . $parts['fragment'];
  216. }
  217. if (empty($domain) || empty($key)) {
  218. throw new \InvalidArgumentException(sprintf(
  219. 'The specified path (%s) is invalid.',
  220. $path
  221. ));
  222. }
  223. return static::getFilesystemMap()->get($domain)->createStream($key);
  224. }
  225. protected function createStreamMode($mode)
  226. {
  227. return new StreamMode($mode);
  228. }
  229. }