From 2b83a4b627d6aa065c4d08290559735b2435d54c Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sun, 2 May 2021 15:02:26 +0000 Subject: [PATCH] [UTILS][TemporaryFile] Change way TemporaryFile takes arguments and it's internal implementation --- components/Avatar/Controller/Avatar.php | 2 +- plugins/ImageEncoder/ImageEncoder.php | 2 +- plugins/VideoEncoder/VideoEncoder.php | 2 +- src/Entity/AttachmentThumbnail.php | 36 ++++++++++++------------- src/Util/TemporaryFile.php | 30 ++++++++++----------- 5 files changed, 34 insertions(+), 38 deletions(-) diff --git a/components/Avatar/Controller/Avatar.php b/components/Avatar/Controller/Avatar.php index 87d7350eb4..e7e5559407 100644 --- a/components/Avatar/Controller/Avatar.php +++ b/components/Avatar/Controller/Avatar.php @@ -92,7 +92,7 @@ class Avatar extends Controller list(, $mimetype_user, , $encoding_user, $data_user) = $matches; if ($encoding_user == 'base64') { $data_user = base64_decode($data_user); - $tempfile = new TemporaryFile('avatar'); + $tempfile = new TemporaryFile(['prefix' => 'avatar']); $path = $tempfile->getRealPath(); file_put_contents($path, $data_user); $sfile = new SymfonyFile($path); diff --git a/plugins/ImageEncoder/ImageEncoder.php b/plugins/ImageEncoder/ImageEncoder.php index 6452e2347f..8eb6b17fee 100644 --- a/plugins/ImageEncoder/ImageEncoder.php +++ b/plugins/ImageEncoder/ImageEncoder.php @@ -77,7 +77,7 @@ class ImageEncoder extends Plugin $type = self::preferredType(); $extension = image_type_to_extension($type, include_dot: true); - $temp = new TemporaryFile(prefix: null, suffix: $extension); // This handles deleting the file if some error occurs + $temp = new TemporaryFile(['prefix' => 'image', 'suffix' => $extension]); // This handles deleting the file if some error occurs $mimetype = image_type_to_mime_type($type); if ($mimetype != $original_mimetype) { // If title seems to be a filename with an extension diff --git a/plugins/VideoEncoder/VideoEncoder.php b/plugins/VideoEncoder/VideoEncoder.php index 9a593db681..6faff5fc0a 100644 --- a/plugins/VideoEncoder/VideoEncoder.php +++ b/plugins/VideoEncoder/VideoEncoder.php @@ -72,7 +72,7 @@ class VideoEncoder extends Plugin // FFmpeg can't edit existing files in place, // generate temporary output file to avoid that - $tempfile = new TemporaryFile('gs-outpath'); + $tempfile = new TemporaryFile(['prefix' => 'video']); // Generate palette file. FFmpeg explictly needs to be told the // extension for PNG files outputs diff --git a/src/Entity/AttachmentThumbnail.php b/src/Entity/AttachmentThumbnail.php index e604ae0eb1..accd362d7c 100644 --- a/src/Entity/AttachmentThumbnail.php +++ b/src/Entity/AttachmentThumbnail.php @@ -100,18 +100,17 @@ class AttachmentThumbnail extends Entity return $this->filename; } - public function setModified(\DateTimeInterface $modified): self + public function setModified(DateTimeInterface $modified): self { $this->modified = $modified; return $this; } - public function getModified(): \DateTimeInterface + public function getModified(): DateTimeInterface { return $this->modified; } - // }}} Autocode private Attachment $attachment; @@ -139,10 +138,10 @@ class AttachmentThumbnail extends Entity return DB::findOneBy('attachment_thumbnail', ['attachment_id' => $attachment->getId(), 'width' => $predicted_width, 'height' => $predicted_height]); }); } catch (NotFoundException $e) { - $ext = image_type_to_extension(IMAGETYPE_WEBP, include_dot: true); - $temp = new TemporaryFile(prefix: null, suffix: $ext); - $thumbnail = self::create(['attachment_id' => $attachment->getId()]); - $event_map = ['image' => 'ResizeImagePath', 'video' => 'ResizeVideoPath']; + $ext = image_type_to_extension(IMAGETYPE_WEBP, include_dot: true); + $temp = new TemporaryFile(['prefix' => 'thumbnail', 'suffix' => $ext]); + $thumbnail = self::create(['attachment_id' => $attachment->getId()]); + $event_map = ['image' => 'ResizeImagePath', 'video' => 'ResizeVideoPath']; $major_mime = GSFile::mimetypeMajor($attachment->getMimetype()); if (in_array($major_mime, array_keys($event_map))) { Event::handle($event_map[$major_mime], [$attachment->getPath(), $temp->getRealPath(), &$width, &$height, $crop, &$mimetype]); @@ -178,8 +177,8 @@ class AttachmentThumbnail extends Entity { $attrs = [ 'height' => $this->getHeight(), - 'width' => $this->getWidth(), - 'src' => $this->getUrl(), + 'width' => $this->getWidth(), + 'src' => $this->getUrl(), ]; return $overwrite ? array_merge($orig, $attrs) : array_merge($attrs, $orig); } @@ -221,8 +220,7 @@ class AttachmentThumbnail extends Entity int $maxW, int $maxH, bool $crop - ): array - { + ): array { // Cropping data (for original image size). Default values, 0 and null, // imply no cropping and with preserved aspect ratio (per axis). $cx = 0; // crop x @@ -232,7 +230,7 @@ class AttachmentThumbnail extends Entity if ($crop) { $s_ar = $width / $height; - $t_ar = $maxW / $maxH; + $t_ar = $maxW / $maxH; $rw = $maxW; $rh = $maxH; @@ -255,22 +253,22 @@ class AttachmentThumbnail extends Entity $rw = ceil($width * $rh / $height); } } - return [(int)$rw, (int)$rh]; + return [(int) $rw, (int) $rh]; } public static function schemaDef(): array { return [ - 'name' => 'attachment_thumbnail', + 'name' => 'attachment_thumbnail', 'fields' => [ 'attachment_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Attachment.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'thumbnail for what attachment'], - 'width' => ['type' => 'int', 'not null' => true, 'description' => 'width of thumbnail'], - 'height' => ['type' => 'int', 'not null' => true, 'description' => 'height of thumbnail'], - 'filename' => ['type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'thubmnail filename'], - 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], + 'width' => ['type' => 'int', 'not null' => true, 'description' => 'width of thumbnail'], + 'height' => ['type' => 'int', 'not null' => true, 'description' => 'height of thumbnail'], + 'filename' => ['type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'thubmnail filename'], + 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], ], 'primary key' => ['attachment_id', 'width', 'height'], - 'indexes' => [ + 'indexes' => [ 'attachment_thumbnail_attachment_id_idx' => ['attachment_id'], ], ]; diff --git a/src/Util/TemporaryFile.php b/src/Util/TemporaryFile.php index 7740105eef..7404ef1191 100644 --- a/src/Util/TemporaryFile.php +++ b/src/Util/TemporaryFile.php @@ -35,27 +35,25 @@ class TemporaryFile extends \SplFileInfo protected $resource; /** - * @param null|string $prefix The file name will begin with that prefix - * ("php" by default) - * @param null|string $mode File open mode ("w+b" by default) + * @param array $options - ['prefix' => ?string, 'suffix' => ?string, 'mode' => ?string, 'directory' => ?string] */ - public function __construct( - ?string $prefix = null, - ?string $suffix = null, - ?string $mode = null - ) { - $filename = tempnam(sys_get_temp_dir(), $prefix ?? 'gs-php') . ($suffix ?? ''); + public function __construct(array $options) + { + $attempts = 16; + for ($count = 0; $count < $attempts; ++$count) { + $filename = uniqid(($options['directory'] ?? (sys_get_temp_dir() . '/')) . ($options['prefix'] ?? 'gs-php')) . ($options['suffix'] ?? ''); - if ($filename === false) { - throw new TemporaryFileException('Could not create file: ' . $filename); + $this->resource = @fopen($filename, $options['mode'] ?? 'w+b'); + if ($this->resource !== false) { + break; + } } - - parent::__construct($filename); - - if (($this->resource = fopen($filename, $mode ?? 'w+b')) === false) { + if ($count == $attempts) { $this->cleanup(); throw new TemporaryFileException('Could not open file: ' . $filename); } + + parent::__construct($filename); } public function __destruct() @@ -100,7 +98,7 @@ class TemporaryFile extends \SplFileInfo $path = $this->getRealPath(); $this->close(); if (file_exists($path)) { - unlink($path); + @unlink($path); } }