floor12 /
yii2-module-files
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace floor12\files\actions; |
||||
| 4 | |||||
| 5 | use floor12\files\logic\ImagePreviewer; |
||||
| 6 | use floor12\files\models\File; |
||||
| 7 | use Yii; |
||||
| 8 | use yii\base\Action; |
||||
| 9 | use yii\base\InvalidConfigException; |
||||
| 10 | use yii\web\NotFoundHttpException; |
||||
| 11 | use yii\web\RangeNotSatisfiableHttpException; |
||||
| 12 | use yii\web\Response; |
||||
| 13 | |||||
| 14 | |||||
| 15 | class GetPreviewAction extends Action |
||||
| 16 | { |
||||
| 17 | const HEADER_CACHE_TIME = 60 * 60 * 24 * 15; |
||||
| 18 | |||||
| 19 | /** @var int */ |
||||
| 20 | protected $width; |
||||
| 21 | /** @var File */ |
||||
| 22 | protected $model; |
||||
| 23 | |||||
| 24 | /** |
||||
| 25 | * @param $hash |
||||
| 26 | * @param null $width |
||||
|
0 ignored issues
–
show
Documentation
Bug
introduced
by
Loading history...
|
|||||
| 27 | * @param null $webp |
||||
|
0 ignored issues
–
show
|
|||||
| 28 | * @throws NotFoundHttpException |
||||
| 29 | * @throws InvalidConfigException |
||||
| 30 | * @throws RangeNotSatisfiableHttpException |
||||
| 31 | */ |
||||
| 32 | public function run($hash, $width = null, $webp = null) |
||||
| 33 | { |
||||
| 34 | $this->loadAndCheckModel($hash); |
||||
| 35 | $this->width = $width; |
||||
| 36 | |||||
| 37 | if ($width && |
||||
|
0 ignored issues
–
show
|
|||||
| 38 | $this->model->content_type !== 'image/svg+xml' && |
||||
| 39 | $this->model->content_type !== 'image/svg') { |
||||
| 40 | $this->sendPreview($width, $webp); |
||||
| 41 | } else { |
||||
| 42 | $this->sendAsIs(); |
||||
| 43 | } |
||||
| 44 | } |
||||
| 45 | |||||
| 46 | /** |
||||
| 47 | * @param string $hash |
||||
| 48 | * @throws NotFoundHttpException |
||||
| 49 | */ |
||||
| 50 | private function loadAndCheckModel(string $hash): void |
||||
| 51 | { |
||||
| 52 | $this->model = File::findOne(['hash' => $hash]); |
||||
| 53 | if (!$this->model) |
||||
| 54 | throw new NotFoundHttpException("Запрашиваемый файл не найден"); |
||||
| 55 | |||||
| 56 | if (!$this->model->isImage() && !$this->model->isVideo()) |
||||
| 57 | throw new NotFoundHttpException("Запрашиваемый файл не является изображением"); |
||||
| 58 | |||||
| 59 | if (!file_exists($this->model->rootPath)) |
||||
|
0 ignored issues
–
show
It seems like
$this->model->rootPath can also be of type null; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 60 | throw new NotFoundHttpException('Запрашиваемый файл не найден на диске.'); |
||||
| 61 | } |
||||
| 62 | |||||
| 63 | /** |
||||
| 64 | * @param $width |
||||
| 65 | * @throws InvalidConfigException |
||||
| 66 | * @throws NotFoundHttpException |
||||
| 67 | * @throws RangeNotSatisfiableHttpException |
||||
| 68 | */ |
||||
| 69 | protected function sendPreview($width, $webp) |
||||
| 70 | { |
||||
| 71 | $filename = Yii::createObject(ImagePreviewer::class, [$this->model, $width, $webp])->getUrl(); |
||||
| 72 | |||||
| 73 | if (!file_exists($filename)) |
||||
| 74 | throw new NotFoundHttpException('Запрашиваемый файл не найден на диске.'); |
||||
| 75 | |||||
| 76 | $response = Yii::$app->response; |
||||
|
0 ignored issues
–
show
It seems like
Yii::app->response can also be of type yii\web\Response. However, the property $response is declared as type yii\console\Response. Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
Loading history...
|
|||||
| 77 | $response->format = Response::FORMAT_RAW; |
||||
| 78 | $coontentType = mime_content_type($filename); |
||||
| 79 | $this->setHeaders($response, $coontentType, md5($this->model->created)); |
||||
| 80 | $stream = fopen($filename, 'rb'); |
||||
| 81 | Yii::$app->response->sendStreamAsFile($stream, $this->model->title, [ |
||||
| 82 | 'inline' => true, |
||||
| 83 | 'mimeType' => $this->model->content_type, |
||||
| 84 | 'filesize' => $this->model->size |
||||
| 85 | ]); |
||||
| 86 | } |
||||
| 87 | |||||
| 88 | /** |
||||
| 89 | * @param $response |
||||
| 90 | * @param string $contentType |
||||
| 91 | * @param string $etag |
||||
| 92 | */ |
||||
| 93 | private function setHeaders($response, string $contentType, string $etag): void |
||||
| 94 | { |
||||
| 95 | $response->headers->set('Last-Modified', date("c", $this->model->created)); |
||||
| 96 | $response->headers->set('Cache-Control', 'public, max-age=' . self::HEADER_CACHE_TIME); |
||||
| 97 | $response->headers->set('Content-Type', $contentType . '; charset=utf-8'); |
||||
| 98 | $response->headers->set('ETag', $etag); |
||||
| 99 | } |
||||
| 100 | |||||
| 101 | /** |
||||
| 102 | * @throws RangeNotSatisfiableHttpException |
||||
| 103 | */ |
||||
| 104 | protected function sendAsIs() |
||||
| 105 | { |
||||
| 106 | $stream = fopen($this->model->rootPath, 'rb'); |
||||
| 107 | Yii::$app->response->sendStreamAsFile($stream, $this->model->title, [ |
||||
| 108 | 'inline' => true, |
||||
| 109 | 'mimeType' => $this->model->content_type, |
||||
| 110 | 'filesize' => $this->model->size |
||||
| 111 | ]); |
||||
| 112 | } |
||||
| 113 | } |
||||
| 114 |