/vendor/guzzle/common/Guzzle/Common/Stream.php

https://bitbucket.org/dgavey/rps-hack · PHP · 272 lines · 149 code · 37 blank · 86 comment · 15 complexity · 95250f579b70a989d909eb89475b6510 MD5 · raw file

  1. <?php
  2. namespace Guzzle\Common;
  3. use Guzzle\Common\Exception\InvalidArgumentException;
  4. /**
  5. * PHP stream implementation
  6. */
  7. class Stream implements StreamInterface
  8. {
  9. const STREAM_TYPE = 'stream_type';
  10. const WRAPPER_TYPE = 'wrapper_type';
  11. const IS_LOCAL = 'is_local';
  12. const IS_READABLE = 'is_readable';
  13. const IS_WRITABLE = 'is_writable';
  14. const SEEKABLE = 'seekable';
  15. /**
  16. * @var resource Stream resource
  17. */
  18. protected $stream;
  19. /**
  20. * @var int Size of the stream contents in bytes
  21. */
  22. protected $size;
  23. /**
  24. * @var array Stream cached data
  25. */
  26. protected $cache = array();
  27. /**
  28. * @var array Hash table of readable and writeable stream types for fast lookups
  29. */
  30. protected static $readWriteHash = array(
  31. 'read' => array(
  32. 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
  33. 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true,
  34. 'rt' => true, 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true
  35. ),
  36. 'write' => array(
  37. 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, 'c+' => true,
  38. 'w+b' => true, 'r+b' => true, 'x+b' => true, 'c+b' => true,
  39. 'w+t' => true, 'r+t' => true, 'x+t' => true, 'c+t' => true
  40. )
  41. );
  42. /**
  43. * Construct a new Stream
  44. *
  45. * @param resource $stream Stream resource to wrap
  46. * @param int $size Size of the stream in bytes. Only pass if the size cannot be obtained from the stream.
  47. *
  48. * @throws InvalidArgumentException if the stream is not a stream resource
  49. */
  50. public function __construct($stream, $size = null)
  51. {
  52. if (!is_resource($stream)) {
  53. throw new InvalidArgumentException('Stream must be a resource');
  54. }
  55. $this->size = $size;
  56. $this->stream = $stream;
  57. $this->rebuildCache();
  58. }
  59. /**
  60. * Closes the stream when the helper is destructed
  61. */
  62. public function __destruct()
  63. {
  64. if (is_resource($this->stream)) {
  65. fclose($this->stream);
  66. }
  67. }
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public function __toString()
  72. {
  73. if (!$this->isReadable() || (!$this->isSeekable() && $this->isConsumed())) {
  74. return '';
  75. }
  76. $originalPos = $this->ftell();
  77. $body = stream_get_contents($this->stream, -1, 0);
  78. $this->seek($originalPos);
  79. return $body;
  80. }
  81. /**
  82. * {@inheritdoc}
  83. */
  84. public function getMetaData($key = null)
  85. {
  86. $meta = stream_get_meta_data($this->stream);
  87. return !$key ? $meta : (array_key_exists($key, $meta) ? $meta[$key] : null);
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function getStream()
  93. {
  94. return $this->stream;
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function getWrapper()
  100. {
  101. return $this->cache[self::WRAPPER_TYPE];
  102. }
  103. /**
  104. * {@inheritdoc}
  105. */
  106. public function getWrapperData()
  107. {
  108. return $this->getMetaData('wrapper_data') ?: array();
  109. }
  110. /**
  111. * {@inheritdoc}
  112. */
  113. public function getStreamType()
  114. {
  115. return $this->cache[self::STREAM_TYPE];
  116. }
  117. /**
  118. * {@inheritdoc}
  119. */
  120. public function getUri()
  121. {
  122. return $this->cache['uri'];
  123. }
  124. /**
  125. * {@inheritdoc}
  126. */
  127. public function getSize()
  128. {
  129. if ($this->size !== null) {
  130. return $this->size;
  131. }
  132. // If the stream is a file based stream and local, then check the filesize
  133. if ($this->isLocal() && $this->getWrapper() == 'plainfile' && $this->getUri() && file_exists($this->getUri())) {
  134. return filesize($this->getUri());
  135. }
  136. // Only get the size based on the content if the the stream is readable
  137. // and seekable so as to not interfere with actually reading the data
  138. if (!$this->cache[self::IS_READABLE] || !$this->cache[self::SEEKABLE]) {
  139. return false;
  140. } else {
  141. $pos = $this->ftell();
  142. $this->size = strlen((string) $this);
  143. $this->seek($pos);
  144. return $this->size;
  145. }
  146. }
  147. /**
  148. * {@inheritdoc}
  149. */
  150. public function isReadable()
  151. {
  152. return $this->cache[self::IS_READABLE];
  153. }
  154. /**
  155. * {@inheritdoc}
  156. */
  157. public function isWritable()
  158. {
  159. return $this->cache[self::IS_WRITABLE];
  160. }
  161. /**
  162. * {@inheritdoc}
  163. */
  164. public function isConsumed()
  165. {
  166. return feof($this->stream);
  167. }
  168. /**
  169. * {@inheritdoc}
  170. */
  171. public function isLocal()
  172. {
  173. return $this->cache[self::IS_LOCAL];
  174. }
  175. /**
  176. * {@inheritdoc}
  177. */
  178. public function isSeekable()
  179. {
  180. return $this->cache[self::SEEKABLE];
  181. }
  182. /**
  183. * {@inheritdoc}
  184. */
  185. public function setSize($size)
  186. {
  187. $this->size = $size;
  188. return $this;
  189. }
  190. /**
  191. * {@inheritdoc}
  192. */
  193. public function seek($offset, $whence = SEEK_SET)
  194. {
  195. return $this->cache[self::SEEKABLE] ? fseek($this->stream, $offset, $whence) === 0 : false;
  196. }
  197. /**
  198. * {@inheritdoc}
  199. */
  200. public function read($length)
  201. {
  202. return $this->cache[self::IS_READABLE] ? fread($this->stream, $length) : false;
  203. }
  204. /**
  205. * {@inheritdoc}
  206. */
  207. public function write($string)
  208. {
  209. if (!$this->cache[self::IS_WRITABLE]) {
  210. return 0;
  211. }
  212. $bytes = fwrite($this->stream, $string);
  213. $this->size += $bytes;
  214. return $bytes;
  215. }
  216. /**
  217. * {@inheritdoc}
  218. */
  219. public function ftell()
  220. {
  221. return ftell($this->stream);
  222. }
  223. /**
  224. * Reprocess stream metadata
  225. */
  226. protected function rebuildCache()
  227. {
  228. $this->cache = stream_get_meta_data($this->stream);
  229. $this->cache[self::STREAM_TYPE] = strtolower($this->cache[self::STREAM_TYPE]);
  230. $this->cache[self::WRAPPER_TYPE] = strtolower($this->cache[self::WRAPPER_TYPE]);
  231. $this->cache[self::IS_LOCAL] = stream_is_local($this->stream);
  232. $this->cache[self::IS_READABLE] = isset(self::$readWriteHash['read'][$this->cache['mode']]);
  233. $this->cache[self::IS_WRITABLE] = isset(self::$readWriteHash['write'][$this->cache['mode']]);
  234. }
  235. }