Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
80.00% covered (success)
80.00%
8 / 10
CRAP
94.92% covered (success)
94.92%
56 / 59
UploadedFile
0.00% covered (danger)
0.00%
0 / 1
80.00% covered (success)
80.00%
8 / 10
33.14
94.92% covered (success)
94.92%
56 / 59
 __construct
100.00% covered (success)
100.00%
1 / 1
13
100.00% covered (success)
100.00%
23 / 23
 createBy_FILE
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getStream
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
8 / 8
 moveTo
0.00% covered (danger)
0.00%
0 / 1
6.22
81.82% covered (success)
81.82%
9 / 11
 getSize
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getError
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getClientFilename
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getClientMediaType
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 writeFile
0.00% covered (danger)
0.00%
0 / 1
3.01
88.89% covered (success)
88.89%
8 / 9
 isUploadOk
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
<?php
namespace Puyo\Psr7;
/**
 * PSR-7 の UploadedFileInterface の実装
 *
 * アップロードされたファイル1件の抽象化。
 */
class UploadedFile implements \Psr\Http\Message\UploadedFileInterface
{
    /** @var string */
    private $clientFilename;
    /** @var string */
    private $clientMediaType;
    /** @var int */
    private $errorCode;
    /** @var string|null */
    private $file;
    /** @var bool */
    private $moved = false;
    /** @var int */
    private $size;
    /** @var \Psr\Http\Message\StreamInterface */
    private $stream;
    /**
     * @param string|resource|\Psr\Http\Message\StreamInterface $streamOrFile
     * @param int $size UPLOAD_ERR_* constant
     * @param int $errorCode
     * @param string $clientFilename
     * @param string $clientMediaType
     */
    public function __construct($streamOrFile, $size, $errorCode, $clientFilename=null, $clientMediaType=null) {
        if($errorCode === UPLOAD_ERR_OK) {
            if(is_string($streamOrFile)) {
                $this->file = $streamOrFile;
            } elseif(is_resource($streamOrFile)) {
                $this->stream = new Stream($streamOrFile);
            } elseif($streamOrFile instanceof \Psr\Http\Message\StreamInterface) {
                $this->stream = $streamOrFile;
            } else {
                throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile');
            }
        }
        if(!is_int($size)) {
            throw new \InvalidArgumentException('size must be an int');
        }
        $this->size = $size;
        if(!is_int($errorCode) || $errorCode < UPLOAD_ERR_OK || $errorCode > UPLOAD_ERR_EXTENSION) {
            throw new \InvalidArgumentException('error must be an UPLOAD_ERR_* constant');
        }
        $this->errorCode = $errorCode;
        if($clientFilename !== null && !is_string($clientFilename)) {
            throw new \InvalidArgumentException('name must be a string');
        }
        $this->clientFilename = $clientFilename;
        if($clientMediaType !== null && !is_string($clientMediaType)) {
            throw new \InvalidArgumentException('type must be a string');
        }
        $this->clientMediaType = $clientMediaType;
    }
    /**
     * $_FILES の1件分から作成する
     * @param array $file
     * @return \Puyo\Psr7\UploadedFile
     */
    public static function createBy_FILE(array $file) {
        return new UploadedFile($file['tmp_name'], $file['size'], $file['error'], $file['name'], $file['type']);
    }
    /**
     * {@inheritdoc}
     * @return \Psr\Http\Message\StreamInterface
     * @throws \RuntimeException if the upload was not successful.
     */
    public function getStream() {
        if(!$this->isUploadOk()) {
            throw new \RuntimeException('Cannot retrieve stream due to upload error');
        }
        if($this->moved) {
            throw new \RuntimeException('Cannot retrieve stream after it has already been moved');
        }
        if($this->stream instanceof \Psr\Http\Message\StreamInterface) {
            return $this->stream;
        }
        $this->stream = new Stream($this->file);
        return $this->stream;
    }
    /**
     * {@inheritdoc}
     * @param string $targetPath
     */
    public function moveTo($targetPath) {
        if(!$this->isUploadOk()) {
            throw new \RuntimeException('Cannot retrieve stream due to upload error');
        }
        if($this->moved) {
            throw new \RuntimeException('Cannot move file. already moved.');
        }
        if(PHP_SAPI === 'cli' || empty(PHP_SAPI)) {
            $this->writeFile($targetPath);
        } else {
            if(!move_uploaded_file($this->file, $targetPath)) {
                throw new \RuntimeException('Cannot moving uploaded file');
            }
        }
        $this->moved = true;
    }
    /**
     * {@inheritdoc}
     * @return int
     */
    public function getSize() {
        return $this->size;
    }
    /**
     * {@inheritdoc}
     * @return int
     */
    public function getError() {
        return $this->errorCode;
    }
    /**
     * {@inheritdoc}
     * @return string
     */
    public function getClientFilename() {
        return $this->clientFilename;
    }
    /**
     * {@inheritdoc}
     * @return string
     */
    public function getClientMediaType() {
        return $this->clientMediaType;
    }
    private function writeFile($path) {
        $fp = fopen($path, 'wb+');
        if(!is_resource($fp)) {
            throw new \RuntimeException('Unable to write to designated path');
        }
        $stream = $this->getStream();
        while(!$stream->eof()) {
            fwrite($fp, $stream->read(4096));
        }
        fclose($fp);
    }
    /**
     * アップロードが正常に完了したかどうかを返す
     * @return bool
     */
    public function isUploadOk() {
        if($this->errorCode === UPLOAD_ERR_OK) {
            return true;
        }
        return false;
    }
}