File.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <?php
  2. /**
  3. * Hoa
  4. *
  5. *
  6. * @license
  7. *
  8. * New BSD License
  9. *
  10. * Copyright © 2007-2017, Hoa community. All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * * Neither the name of the Hoa nor the names of its contributors may be
  20. * used to endorse or promote products derived from this software without
  21. * specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  24. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  27. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  30. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  31. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  32. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. namespace Hoa\File;
  36. use Hoa\Consistency;
  37. use Hoa\Stream;
  38. /**
  39. * Class \Hoa\File.
  40. *
  41. * File handler.
  42. *
  43. * @copyright Copyright © 2007-2017 Hoa community
  44. * @license New BSD License
  45. */
  46. abstract class File
  47. extends Generic
  48. implements Stream\IStream\Bufferable,
  49. Stream\IStream\Lockable,
  50. Stream\IStream\Pointable
  51. {
  52. /**
  53. * Open for reading only; place the file pointer at the beginning of the
  54. * file.
  55. *
  56. * @const string
  57. */
  58. const MODE_READ = 'rb';
  59. /**
  60. * Open for reading and writing; place the file pointer at the beginning of
  61. * the file.
  62. *
  63. * @const string
  64. */
  65. const MODE_READ_WRITE = 'r+b';
  66. /**
  67. * Open for writing only; place the file pointer at the beginning of the
  68. * file and truncate the file to zero length. If the file does not exist,
  69. * attempt to create it.
  70. *
  71. * @const string
  72. */
  73. const MODE_TRUNCATE_WRITE = 'wb';
  74. /**
  75. * Open for reading and writing; place the file pointer at the beginning of
  76. * the file and truncate the file to zero length. If the file does not
  77. * exist, attempt to create it.
  78. *
  79. * @const string
  80. */
  81. const MODE_TRUNCATE_READ_WRITE = 'w+b';
  82. /**
  83. * Open for writing only; place the file pointer at the end of the file. If
  84. * the file does not exist, attempt to create it.
  85. *
  86. * @const string
  87. */
  88. const MODE_APPEND_WRITE = 'ab';
  89. /**
  90. * Open for reading and writing; place the file pointer at the end of the
  91. * file. If the file does not exist, attempt to create it.
  92. *
  93. * @const string
  94. */
  95. const MODE_APPEND_READ_WRITE = 'a+b';
  96. /**
  97. * Create and open for writing only; place the file pointer at the beginning
  98. * of the file. If the file already exits, the fopen() call with fail by
  99. * returning false and generating an error of level E_WARNING. If the file
  100. * does not exist, attempt to create it. This is equivalent to specifying
  101. * O_EXCL | O_CREAT flags for the underlying open(2) system call.
  102. *
  103. * @const string
  104. */
  105. const MODE_CREATE_WRITE = 'xb';
  106. /**
  107. * Create and open for reading and writing; place the file pointer at the
  108. * beginning of the file. If the file already exists, the fopen() call with
  109. * fail by returning false and generating an error of level E_WARNING. If
  110. * the file does not exist, attempt to create it. This is equivalent to
  111. * specifying O_EXCL | O_CREAT flags for the underlying open(2) system call.
  112. *
  113. * @const string
  114. */
  115. const MODE_CREATE_READ_WRITE = 'x+b';
  116. /**
  117. * Open a file.
  118. *
  119. * @param string $streamName Stream name (or file descriptor).
  120. * @param string $mode Open mode, see the self::MODE_*
  121. * constants.
  122. * @param string $context Context ID (please, see the
  123. * \Hoa\Stream\Context class).
  124. * @param bool $wait Differ opening or not.
  125. * @throws \Hoa\File\Exception
  126. */
  127. public function __construct(
  128. $streamName,
  129. $mode,
  130. $context = null,
  131. $wait = false
  132. ) {
  133. $this->setMode($mode);
  134. switch ($streamName) {
  135. case '0':
  136. $streamName = 'php://stdin';
  137. break;
  138. case '1':
  139. $streamName = 'php://stdout';
  140. break;
  141. case '2':
  142. $streamName = 'php://stderr';
  143. break;
  144. default:
  145. if (true === ctype_digit($streamName)) {
  146. if (PHP_VERSION_ID >= 50306) {
  147. $streamName = 'php://fd/' . $streamName;
  148. } else {
  149. throw new Exception(
  150. 'You need PHP5.3.6 to use a file descriptor ' .
  151. 'other than 0, 1 or 2 (tried %d with PHP%s).',
  152. 0,
  153. [$streamName, PHP_VERSION]
  154. );
  155. }
  156. }
  157. }
  158. parent::__construct($streamName, $context, $wait);
  159. return;
  160. }
  161. /**
  162. * Open the stream and return the associated resource.
  163. *
  164. * @param string $streamName Stream name (e.g. path or URL).
  165. * @param \Hoa\Stream\Context $context Context.
  166. * @return resource
  167. * @throws \Hoa\File\Exception\FileDoesNotExist
  168. * @throws \Hoa\File\Exception
  169. */
  170. protected function &_open($streamName, Stream\Context $context = null)
  171. {
  172. if (substr($streamName, 0, 4) == 'file' &&
  173. false === is_dir(dirname($streamName))) {
  174. throw new Exception(
  175. 'Directory %s does not exist. Could not open file %s.',
  176. 1,
  177. [dirname($streamName), basename($streamName)]
  178. );
  179. }
  180. if (null === $context) {
  181. if (false === $out = @fopen($streamName, $this->getMode(), true)) {
  182. throw new Exception(
  183. 'Failed to open stream %s.',
  184. 2,
  185. $streamName
  186. );
  187. }
  188. return $out;
  189. }
  190. $out = @fopen(
  191. $streamName,
  192. $this->getMode(),
  193. true,
  194. $context->getContext()
  195. );
  196. if (false === $out) {
  197. throw new Exception(
  198. 'Failed to open stream %s.',
  199. 3,
  200. $streamName
  201. );
  202. }
  203. return $out;
  204. }
  205. /**
  206. * Close the current stream.
  207. *
  208. * @return bool
  209. */
  210. protected function _close()
  211. {
  212. return @fclose($this->getStream());
  213. }
  214. /**
  215. * Start a new buffer.
  216. * The callable acts like a light filter.
  217. *
  218. * @param mixed $callable Callable.
  219. * @param int $size Size.
  220. * @return int
  221. */
  222. public function newBuffer($callable = null, $size = null)
  223. {
  224. $this->setStreamBuffer($size);
  225. //@TODO manage $callable as a filter?
  226. return 1;
  227. }
  228. /**
  229. * Flush the output to a stream.
  230. *
  231. * @return bool
  232. */
  233. public function flush()
  234. {
  235. return fflush($this->getStream());
  236. }
  237. /**
  238. * Delete buffer.
  239. *
  240. * @return bool
  241. */
  242. public function deleteBuffer()
  243. {
  244. return $this->disableStreamBuffer();
  245. }
  246. /**
  247. * Get bufffer level.
  248. *
  249. * @return int
  250. */
  251. public function getBufferLevel()
  252. {
  253. return 1;
  254. }
  255. /**
  256. * Get buffer size.
  257. *
  258. * @return int
  259. */
  260. public function getBufferSize()
  261. {
  262. return $this->getStreamBufferSize();
  263. }
  264. /**
  265. * Portable advisory locking.
  266. *
  267. * @param int $operation Operation, use the
  268. * \Hoa\Stream\IStream\Lockable::LOCK_* constants.
  269. * @return bool
  270. */
  271. public function lock($operation)
  272. {
  273. return flock($this->getStream(), $operation);
  274. }
  275. /**
  276. * Rewind the position of a stream pointer.
  277. *
  278. * @return bool
  279. */
  280. public function rewind()
  281. {
  282. return rewind($this->getStream());
  283. }
  284. /**
  285. * Seek on a stream pointer.
  286. *
  287. * @param int $offset Offset (negative value should be supported).
  288. * @param int $whence Whence, use the
  289. * \Hoa\Stream\IStream\Pointable::SEEK_* constants.
  290. * @return int
  291. */
  292. public function seek($offset, $whence = Stream\IStream\Pointable::SEEK_SET)
  293. {
  294. return fseek($this->getStream(), $offset, $whence);
  295. }
  296. /**
  297. * Get the current position of the stream pointer.
  298. *
  299. * @return int
  300. */
  301. public function tell()
  302. {
  303. $stream = $this->getStream();
  304. if (null === $stream) {
  305. return 0;
  306. }
  307. return ftell($stream);
  308. }
  309. /**
  310. * Create a file.
  311. *
  312. * @param string $name File name.
  313. * @param mixed $dummy To be compatible with childs.
  314. * @return bool
  315. */
  316. public static function create($name, $dummy)
  317. {
  318. if (file_exists($name)) {
  319. return true;
  320. }
  321. return touch($name);
  322. }
  323. }
  324. /**
  325. * Flex entity.
  326. */
  327. Consistency::flexEntity('Hoa\File\File');