酒店预订平台
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

329 строки
7.6 KiB

  1. <?php
  2. namespace GuzzleHttp\Psr7;
  3. use InvalidArgumentException;
  4. use Psr\Http\Message\StreamInterface;
  5. use Psr\Http\Message\UploadedFileInterface;
  6. use RuntimeException;
  7. class UploadedFile implements UploadedFileInterface
  8. {
  9. /**
  10. * @var int[]
  11. */
  12. private static $errors = [
  13. UPLOAD_ERR_OK,
  14. UPLOAD_ERR_INI_SIZE,
  15. UPLOAD_ERR_FORM_SIZE,
  16. UPLOAD_ERR_PARTIAL,
  17. UPLOAD_ERR_NO_FILE,
  18. UPLOAD_ERR_NO_TMP_DIR,
  19. UPLOAD_ERR_CANT_WRITE,
  20. UPLOAD_ERR_EXTENSION,
  21. ];
  22. /**
  23. * @var string
  24. */
  25. private $clientFilename;
  26. /**
  27. * @var string
  28. */
  29. private $clientMediaType;
  30. /**
  31. * @var int
  32. */
  33. private $error;
  34. /**
  35. * @var string|null
  36. */
  37. private $file;
  38. /**
  39. * @var bool
  40. */
  41. private $moved = false;
  42. /**
  43. * @var int
  44. */
  45. private $size;
  46. /**
  47. * @var StreamInterface|null
  48. */
  49. private $stream;
  50. /**
  51. * @param StreamInterface|string|resource $streamOrFile
  52. * @param int $size
  53. * @param int $errorStatus
  54. * @param string|null $clientFilename
  55. * @param string|null $clientMediaType
  56. */
  57. public function __construct(
  58. $streamOrFile,
  59. $size,
  60. $errorStatus,
  61. $clientFilename = null,
  62. $clientMediaType = null
  63. ) {
  64. $this->setError($errorStatus);
  65. $this->setSize($size);
  66. $this->setClientFilename($clientFilename);
  67. $this->setClientMediaType($clientMediaType);
  68. if ($this->isOk()) {
  69. $this->setStreamOrFile($streamOrFile);
  70. }
  71. }
  72. /**
  73. * Depending on the value set file or stream variable
  74. *
  75. * @param mixed $streamOrFile
  76. *
  77. * @throws InvalidArgumentException
  78. */
  79. private function setStreamOrFile($streamOrFile)
  80. {
  81. if (is_string($streamOrFile)) {
  82. $this->file = $streamOrFile;
  83. } elseif (is_resource($streamOrFile)) {
  84. $this->stream = new Stream($streamOrFile);
  85. } elseif ($streamOrFile instanceof StreamInterface) {
  86. $this->stream = $streamOrFile;
  87. } else {
  88. throw new InvalidArgumentException(
  89. 'Invalid stream or file provided for UploadedFile'
  90. );
  91. }
  92. }
  93. /**
  94. * @param int $error
  95. *
  96. * @throws InvalidArgumentException
  97. */
  98. private function setError($error)
  99. {
  100. if (false === is_int($error)) {
  101. throw new InvalidArgumentException(
  102. 'Upload file error status must be an integer'
  103. );
  104. }
  105. if (false === in_array($error, UploadedFile::$errors)) {
  106. throw new InvalidArgumentException(
  107. 'Invalid error status for UploadedFile'
  108. );
  109. }
  110. $this->error = $error;
  111. }
  112. /**
  113. * @param int $size
  114. *
  115. * @throws InvalidArgumentException
  116. */
  117. private function setSize($size)
  118. {
  119. if (false === is_int($size)) {
  120. throw new InvalidArgumentException(
  121. 'Upload file size must be an integer'
  122. );
  123. }
  124. $this->size = $size;
  125. }
  126. /**
  127. * @param mixed $param
  128. *
  129. * @return bool
  130. */
  131. private function isStringOrNull($param)
  132. {
  133. return in_array(gettype($param), ['string', 'NULL']);
  134. }
  135. /**
  136. * @param mixed $param
  137. *
  138. * @return bool
  139. */
  140. private function isStringNotEmpty($param)
  141. {
  142. return is_string($param) && false === empty($param);
  143. }
  144. /**
  145. * @param string|null $clientFilename
  146. *
  147. * @throws InvalidArgumentException
  148. */
  149. private function setClientFilename($clientFilename)
  150. {
  151. if (false === $this->isStringOrNull($clientFilename)) {
  152. throw new InvalidArgumentException(
  153. 'Upload file client filename must be a string or null'
  154. );
  155. }
  156. $this->clientFilename = $clientFilename;
  157. }
  158. /**
  159. * @param string|null $clientMediaType
  160. *
  161. * @throws InvalidArgumentException
  162. */
  163. private function setClientMediaType($clientMediaType)
  164. {
  165. if (false === $this->isStringOrNull($clientMediaType)) {
  166. throw new InvalidArgumentException(
  167. 'Upload file client media type must be a string or null'
  168. );
  169. }
  170. $this->clientMediaType = $clientMediaType;
  171. }
  172. /**
  173. * Return true if there is no upload error
  174. *
  175. * @return bool
  176. */
  177. private function isOk()
  178. {
  179. return $this->error === UPLOAD_ERR_OK;
  180. }
  181. /**
  182. * @return bool
  183. */
  184. public function isMoved()
  185. {
  186. return $this->moved;
  187. }
  188. /**
  189. * @throws RuntimeException if is moved or not ok
  190. */
  191. private function validateActive()
  192. {
  193. if (false === $this->isOk()) {
  194. throw new RuntimeException('Cannot retrieve stream due to upload error');
  195. }
  196. if ($this->isMoved()) {
  197. throw new RuntimeException('Cannot retrieve stream after it has already been moved');
  198. }
  199. }
  200. /**
  201. * {@inheritdoc}
  202. *
  203. * @throws RuntimeException if the upload was not successful.
  204. */
  205. public function getStream()
  206. {
  207. $this->validateActive();
  208. if ($this->stream instanceof StreamInterface) {
  209. return $this->stream;
  210. }
  211. return new LazyOpenStream($this->file, 'r+');
  212. }
  213. /**
  214. * {@inheritdoc}
  215. *
  216. * @see http://php.net/is_uploaded_file
  217. * @see http://php.net/move_uploaded_file
  218. *
  219. * @param string $targetPath Path to which to move the uploaded file.
  220. *
  221. * @throws RuntimeException if the upload was not successful.
  222. * @throws InvalidArgumentException if the $path specified is invalid.
  223. * @throws RuntimeException on any error during the move operation, or on
  224. * the second or subsequent call to the method.
  225. */
  226. public function moveTo($targetPath)
  227. {
  228. $this->validateActive();
  229. if (false === $this->isStringNotEmpty($targetPath)) {
  230. throw new InvalidArgumentException(
  231. 'Invalid path provided for move operation; must be a non-empty string'
  232. );
  233. }
  234. if ($this->file) {
  235. $this->moved = php_sapi_name() == 'cli'
  236. ? rename($this->file, $targetPath)
  237. : move_uploaded_file($this->file, $targetPath);
  238. } else {
  239. Utils::copyToStream(
  240. $this->getStream(),
  241. new LazyOpenStream($targetPath, 'w')
  242. );
  243. $this->moved = true;
  244. }
  245. if (false === $this->moved) {
  246. throw new RuntimeException(
  247. sprintf('Uploaded file could not be moved to %s', $targetPath)
  248. );
  249. }
  250. }
  251. /**
  252. * {@inheritdoc}
  253. *
  254. * @return int|null The file size in bytes or null if unknown.
  255. */
  256. public function getSize()
  257. {
  258. return $this->size;
  259. }
  260. /**
  261. * {@inheritdoc}
  262. *
  263. * @see http://php.net/manual/en/features.file-upload.errors.php
  264. *
  265. * @return int One of PHP's UPLOAD_ERR_XXX constants.
  266. */
  267. public function getError()
  268. {
  269. return $this->error;
  270. }
  271. /**
  272. * {@inheritdoc}
  273. *
  274. * @return string|null The filename sent by the client or null if none
  275. * was provided.
  276. */
  277. public function getClientFilename()
  278. {
  279. return $this->clientFilename;
  280. }
  281. /**
  282. * {@inheritdoc}
  283. */
  284. public function getClientMediaType()
  285. {
  286. return $this->clientMediaType;
  287. }
  288. }