File.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. /**
  7. * Helper class that simplifies files stream reading and writing
  8. */
  9. namespace Magento\Framework\Archive\Helper;
  10. use Magento\Framework\Exception\LocalizedException;
  11. class File
  12. {
  13. /**
  14. * Full path to directory where file located
  15. *
  16. * @var string
  17. */
  18. protected $_fileLocation;
  19. /**
  20. * File name
  21. *
  22. * @var string
  23. */
  24. protected $_fileName;
  25. /**
  26. * Full path (directory + filename) to file
  27. *
  28. * @var string
  29. */
  30. protected $_filePath;
  31. /**
  32. * File permissions that will be set if file opened in write mode
  33. *
  34. * @var int
  35. */
  36. protected $_chmod;
  37. /**
  38. * File handler
  39. *
  40. * @var resource
  41. */
  42. protected $_fileHandler;
  43. /**
  44. * Whether file has been opened in write mode
  45. *
  46. * @var bool
  47. */
  48. protected $_isInWriteMode;
  49. /**
  50. * Set file path via constructor
  51. *
  52. * @param string $filePath
  53. */
  54. public function __construct($filePath)
  55. {
  56. $pathInfo = pathinfo($filePath);
  57. $this->_filePath = $filePath;
  58. $this->_fileLocation = isset($pathInfo['dirname']) ? $pathInfo['dirname'] : '';
  59. $this->_fileName = isset($pathInfo['basename']) ? $pathInfo['basename'] : '';
  60. }
  61. /**
  62. * Close file if it's not closed before object destruction
  63. */
  64. public function __destruct()
  65. {
  66. if ($this->_fileHandler) {
  67. $this->_close();
  68. }
  69. }
  70. /**
  71. * Open file
  72. *
  73. * @param string $mode
  74. * @param int $chmod
  75. * @return void
  76. * @throws LocalizedException
  77. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  78. */
  79. public function open($mode = 'w+', $chmod = null)
  80. {
  81. $this->_isInWriteMode = $this->_isWritableMode($mode);
  82. if ($this->_isInWriteMode) {
  83. if (!is_writable($this->_fileLocation)) {
  84. throw new LocalizedException(
  85. new \Magento\Framework\Phrase(
  86. 'You don\'t have permissions to write to the "%1" file.',
  87. [$this->_fileLocation]
  88. )
  89. );
  90. }
  91. if (is_file($this->_filePath) && !is_writable($this->_filePath)) {
  92. throw new LocalizedException(
  93. new \Magento\Framework\Phrase(
  94. 'You don\'t have the permissions to open the "%1" file for writing access.',
  95. [$this->_fileName]
  96. )
  97. );
  98. }
  99. }
  100. if ($this->_isReadableMode($mode) && (!is_file($this->_filePath) || !is_readable($this->_filePath))) {
  101. if (!is_file($this->_filePath)) {
  102. throw new LocalizedException(
  103. new \Magento\Framework\Phrase(
  104. 'The "%1" file doesn\'t exist. Verify the file and try again.',
  105. [$this->_filePath]
  106. )
  107. );
  108. }
  109. if (!is_readable($this->_filePath)) {
  110. throw new LocalizedException(
  111. new \Magento\Framework\Phrase(
  112. 'You don\'t have permissions to read the "%1" file.',
  113. [$this->_filePath]
  114. )
  115. );
  116. }
  117. }
  118. $this->_open($mode);
  119. $this->_chmod = $chmod;
  120. }
  121. /**
  122. * Write data to file
  123. *
  124. * @param string $data
  125. * @return void
  126. */
  127. public function write($data)
  128. {
  129. $this->_checkFileOpened();
  130. $this->_write($data);
  131. }
  132. /**
  133. * Read data from file
  134. *
  135. * @param int $length
  136. * @return string|boolean
  137. */
  138. public function read($length = 4096)
  139. {
  140. $data = false;
  141. $this->_checkFileOpened();
  142. if ($length > 0) {
  143. $data = $this->_read($length);
  144. }
  145. return $data;
  146. }
  147. /**
  148. * Check whether end of file reached
  149. *
  150. * @return boolean
  151. */
  152. public function eof()
  153. {
  154. $this->_checkFileOpened();
  155. return $this->_eof();
  156. }
  157. /**
  158. * Close file
  159. *
  160. * @return void
  161. */
  162. public function close()
  163. {
  164. $this->_checkFileOpened();
  165. $this->_close();
  166. $this->_fileHandler = false;
  167. if ($this->_isInWriteMode && isset($this->_chmod)) {
  168. @chmod($this->_filePath, $this->_chmod);
  169. }
  170. }
  171. /**
  172. * Implementation of file opening
  173. *
  174. * @param string $mode
  175. * @return void
  176. * @throws LocalizedException
  177. */
  178. protected function _open($mode)
  179. {
  180. $this->_fileHandler = @fopen($this->_filePath, $mode);
  181. if (false === $this->_fileHandler) {
  182. throw new LocalizedException(
  183. new \Magento\Framework\Phrase('The "%1" file failed to open.', [$this->_filePath])
  184. );
  185. }
  186. }
  187. /**
  188. * Implementation of writing data to file
  189. *
  190. * @param string $data
  191. * @return void
  192. * @throws LocalizedException
  193. */
  194. protected function _write($data)
  195. {
  196. $result = @fwrite($this->_fileHandler, $data);
  197. if (false === $result) {
  198. throw new LocalizedException(
  199. new \Magento\Framework\Phrase('The data failed to write to "%1".', [$this->_filePath])
  200. );
  201. }
  202. }
  203. /**
  204. * Implementation of file reading
  205. *
  206. * @param int $length
  207. * @return string
  208. * @throws LocalizedException
  209. */
  210. protected function _read($length)
  211. {
  212. $result = fread($this->_fileHandler, $length);
  213. if (false === $result) {
  214. throw new LocalizedException(
  215. new \Magento\Framework\Phrase('Failed to read data from %1', [$this->_filePath])
  216. );
  217. }
  218. return $result;
  219. }
  220. /**
  221. * Implementation of EOF indicator
  222. *
  223. * @return boolean
  224. */
  225. protected function _eof()
  226. {
  227. return feof($this->_fileHandler);
  228. }
  229. /**
  230. * Implementation of file closing
  231. *
  232. * @return void
  233. */
  234. protected function _close()
  235. {
  236. fclose($this->_fileHandler);
  237. }
  238. /**
  239. * Check whether requested mode is writable mode
  240. *
  241. * @param string $mode
  242. * @return int
  243. */
  244. protected function _isWritableMode($mode)
  245. {
  246. return preg_match('/(^[waxc])|(\+$)/', $mode);
  247. }
  248. /**
  249. * Check whether requested mode is readable mode
  250. *
  251. * @param string $mode
  252. * @return bool
  253. */
  254. protected function _isReadableMode($mode)
  255. {
  256. return !$this->_isWritableMode($mode);
  257. }
  258. /**
  259. * Check whether file is opened
  260. *
  261. * @return void
  262. * @throws LocalizedException
  263. */
  264. protected function _checkFileOpened()
  265. {
  266. if (!$this->_fileHandler) {
  267. throw new LocalizedException(new \Magento\Framework\Phrase('File not opened'));
  268. }
  269. }
  270. }