annotate vendor/zendframework/zend-diactoros/src/UploadedFile.php @ 12:7a779792577d

Update Drupal core to v8.4.5 (via Composer)
author Chris Cannam
date Fri, 23 Feb 2018 15:52:07 +0000
parents 4c8ae668cc8c
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@12 3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
Chris@12 4 * @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
Chris@0 5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
Chris@0 6 */
Chris@0 7
Chris@0 8 namespace Zend\Diactoros;
Chris@0 9
Chris@0 10 use InvalidArgumentException;
Chris@0 11 use Psr\Http\Message\StreamInterface;
Chris@0 12 use Psr\Http\Message\UploadedFileInterface;
Chris@0 13 use RuntimeException;
Chris@0 14
Chris@0 15 class UploadedFile implements UploadedFileInterface
Chris@0 16 {
Chris@12 17 const ERROR_MESSAGES = [
Chris@12 18 UPLOAD_ERR_OK => 'There is no error, the file uploaded with success',
Chris@12 19 UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
Chris@12 20 UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was '
Chris@12 21 . 'specified in the HTML form',
Chris@12 22 UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded',
Chris@12 23 UPLOAD_ERR_NO_FILE => 'No file was uploaded',
Chris@12 24 UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder',
Chris@12 25 UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
Chris@12 26 UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the file upload.',
Chris@12 27 ];
Chris@12 28
Chris@0 29 /**
Chris@12 30 * @var string|null
Chris@0 31 */
Chris@0 32 private $clientFilename;
Chris@0 33
Chris@0 34 /**
Chris@12 35 * @var string|null
Chris@0 36 */
Chris@0 37 private $clientMediaType;
Chris@0 38
Chris@0 39 /**
Chris@0 40 * @var int
Chris@0 41 */
Chris@0 42 private $error;
Chris@0 43
Chris@0 44 /**
Chris@0 45 * @var null|string
Chris@0 46 */
Chris@0 47 private $file;
Chris@0 48
Chris@0 49 /**
Chris@0 50 * @var bool
Chris@0 51 */
Chris@0 52 private $moved = false;
Chris@0 53
Chris@0 54 /**
Chris@0 55 * @var int
Chris@0 56 */
Chris@0 57 private $size;
Chris@0 58
Chris@0 59 /**
Chris@0 60 * @var null|StreamInterface
Chris@0 61 */
Chris@0 62 private $stream;
Chris@0 63
Chris@0 64 /**
Chris@0 65 * @param string|resource $streamOrFile
Chris@0 66 * @param int $size
Chris@0 67 * @param int $errorStatus
Chris@0 68 * @param string|null $clientFilename
Chris@0 69 * @param string|null $clientMediaType
Chris@0 70 * @throws InvalidArgumentException
Chris@0 71 */
Chris@0 72 public function __construct($streamOrFile, $size, $errorStatus, $clientFilename = null, $clientMediaType = null)
Chris@0 73 {
Chris@0 74 if ($errorStatus === UPLOAD_ERR_OK) {
Chris@0 75 if (is_string($streamOrFile)) {
Chris@0 76 $this->file = $streamOrFile;
Chris@0 77 }
Chris@0 78 if (is_resource($streamOrFile)) {
Chris@0 79 $this->stream = new Stream($streamOrFile);
Chris@0 80 }
Chris@0 81
Chris@0 82 if (! $this->file && ! $this->stream) {
Chris@0 83 if (! $streamOrFile instanceof StreamInterface) {
Chris@0 84 throw new InvalidArgumentException('Invalid stream or file provided for UploadedFile');
Chris@0 85 }
Chris@0 86 $this->stream = $streamOrFile;
Chris@0 87 }
Chris@0 88 }
Chris@0 89
Chris@0 90 if (! is_int($size)) {
Chris@0 91 throw new InvalidArgumentException('Invalid size provided for UploadedFile; must be an int');
Chris@0 92 }
Chris@0 93 $this->size = $size;
Chris@0 94
Chris@0 95 if (! is_int($errorStatus)
Chris@0 96 || 0 > $errorStatus
Chris@0 97 || 8 < $errorStatus
Chris@0 98 ) {
Chris@0 99 throw new InvalidArgumentException(
Chris@0 100 'Invalid error status for UploadedFile; must be an UPLOAD_ERR_* constant'
Chris@0 101 );
Chris@0 102 }
Chris@0 103 $this->error = $errorStatus;
Chris@0 104
Chris@0 105 if (null !== $clientFilename && ! is_string($clientFilename)) {
Chris@0 106 throw new InvalidArgumentException(
Chris@0 107 'Invalid client filename provided for UploadedFile; must be null or a string'
Chris@0 108 );
Chris@0 109 }
Chris@0 110 $this->clientFilename = $clientFilename;
Chris@0 111
Chris@0 112 if (null !== $clientMediaType && ! is_string($clientMediaType)) {
Chris@0 113 throw new InvalidArgumentException(
Chris@0 114 'Invalid client media type provided for UploadedFile; must be null or a string'
Chris@0 115 );
Chris@0 116 }
Chris@0 117 $this->clientMediaType = $clientMediaType;
Chris@0 118 }
Chris@0 119
Chris@0 120 /**
Chris@0 121 * {@inheritdoc}
Chris@0 122 * @throws \RuntimeException if the upload was not successful.
Chris@0 123 */
Chris@0 124 public function getStream()
Chris@0 125 {
Chris@0 126 if ($this->error !== UPLOAD_ERR_OK) {
Chris@12 127 throw new RuntimeException(sprintf(
Chris@12 128 'Cannot retrieve stream due to upload error: %s',
Chris@12 129 self::ERROR_MESSAGES[$this->error]
Chris@12 130 ));
Chris@0 131 }
Chris@0 132
Chris@0 133 if ($this->moved) {
Chris@0 134 throw new RuntimeException('Cannot retrieve stream after it has already been moved');
Chris@0 135 }
Chris@0 136
Chris@0 137 if ($this->stream instanceof StreamInterface) {
Chris@0 138 return $this->stream;
Chris@0 139 }
Chris@0 140
Chris@0 141 $this->stream = new Stream($this->file);
Chris@0 142 return $this->stream;
Chris@0 143 }
Chris@0 144
Chris@0 145 /**
Chris@0 146 * {@inheritdoc}
Chris@0 147 *
Chris@0 148 * @see http://php.net/is_uploaded_file
Chris@0 149 * @see http://php.net/move_uploaded_file
Chris@0 150 * @param string $targetPath Path to which to move the uploaded file.
Chris@0 151 * @throws \RuntimeException if the upload was not successful.
Chris@0 152 * @throws \InvalidArgumentException if the $path specified is invalid.
Chris@0 153 * @throws \RuntimeException on any error during the move operation, or on
Chris@0 154 * the second or subsequent call to the method.
Chris@0 155 */
Chris@0 156 public function moveTo($targetPath)
Chris@0 157 {
Chris@0 158 if ($this->moved) {
Chris@0 159 throw new RuntimeException('Cannot move file; already moved!');
Chris@0 160 }
Chris@0 161
Chris@0 162 if ($this->error !== UPLOAD_ERR_OK) {
Chris@12 163 throw new RuntimeException(sprintf(
Chris@12 164 'Cannot retrieve stream due to upload error: %s',
Chris@12 165 self::ERROR_MESSAGES[$this->error]
Chris@12 166 ));
Chris@0 167 }
Chris@0 168
Chris@0 169 if (! is_string($targetPath) || empty($targetPath)) {
Chris@0 170 throw new InvalidArgumentException(
Chris@0 171 'Invalid path provided for move operation; must be a non-empty string'
Chris@0 172 );
Chris@0 173 }
Chris@0 174
Chris@0 175 $targetDirectory = dirname($targetPath);
Chris@0 176 if (! is_dir($targetDirectory) || ! is_writable($targetDirectory)) {
Chris@0 177 throw new RuntimeException(sprintf(
Chris@0 178 'The target directory `%s` does not exists or is not writable',
Chris@0 179 $targetDirectory
Chris@0 180 ));
Chris@0 181 }
Chris@0 182
Chris@0 183 $sapi = PHP_SAPI;
Chris@0 184 switch (true) {
Chris@0 185 case (empty($sapi) || 0 === strpos($sapi, 'cli') || ! $this->file):
Chris@0 186 // Non-SAPI environment, or no filename present
Chris@0 187 $this->writeFile($targetPath);
Chris@0 188 break;
Chris@0 189 default:
Chris@0 190 // SAPI environment, with file present
Chris@0 191 if (false === move_uploaded_file($this->file, $targetPath)) {
Chris@0 192 throw new RuntimeException('Error occurred while moving uploaded file');
Chris@0 193 }
Chris@0 194 break;
Chris@0 195 }
Chris@0 196
Chris@0 197 $this->moved = true;
Chris@0 198 }
Chris@0 199
Chris@0 200 /**
Chris@0 201 * {@inheritdoc}
Chris@0 202 *
Chris@0 203 * @return int|null The file size in bytes or null if unknown.
Chris@0 204 */
Chris@0 205 public function getSize()
Chris@0 206 {
Chris@0 207 return $this->size;
Chris@0 208 }
Chris@0 209
Chris@0 210 /**
Chris@0 211 * {@inheritdoc}
Chris@0 212 *
Chris@0 213 * @see http://php.net/manual/en/features.file-upload.errors.php
Chris@0 214 * @return int One of PHP's UPLOAD_ERR_XXX constants.
Chris@0 215 */
Chris@0 216 public function getError()
Chris@0 217 {
Chris@0 218 return $this->error;
Chris@0 219 }
Chris@0 220
Chris@0 221 /**
Chris@0 222 * {@inheritdoc}
Chris@0 223 *
Chris@0 224 * @return string|null The filename sent by the client or null if none
Chris@0 225 * was provided.
Chris@0 226 */
Chris@0 227 public function getClientFilename()
Chris@0 228 {
Chris@0 229 return $this->clientFilename;
Chris@0 230 }
Chris@0 231
Chris@0 232 /**
Chris@0 233 * {@inheritdoc}
Chris@0 234 */
Chris@0 235 public function getClientMediaType()
Chris@0 236 {
Chris@0 237 return $this->clientMediaType;
Chris@0 238 }
Chris@0 239
Chris@0 240 /**
Chris@0 241 * Write internal stream to given path
Chris@0 242 *
Chris@0 243 * @param string $path
Chris@0 244 */
Chris@0 245 private function writeFile($path)
Chris@0 246 {
Chris@0 247 $handle = fopen($path, 'wb+');
Chris@0 248 if (false === $handle) {
Chris@0 249 throw new RuntimeException('Unable to write to designated path');
Chris@0 250 }
Chris@0 251
Chris@0 252 $stream = $this->getStream();
Chris@0 253 $stream->rewind();
Chris@0 254 while (! $stream->eof()) {
Chris@0 255 fwrite($handle, $stream->read(4096));
Chris@0 256 }
Chris@0 257
Chris@0 258 fclose($handle);
Chris@0 259 }
Chris@0 260 }