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
![]() |
|||||
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
![]() |
|||||
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;
}
![]() |
|||||
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 |