misuzu/src/Users/Assets/UserImageAsset.php
flashwave 383e2ed0e0 Rewrote the user information class.
This one took multiple days and it pretty invasive into the core of Misuzu so issue might (will) arise, there's also some features that have gone temporarily missing in the mean time and some inefficiencies introduced that will be fixed again at a later time.
The old class isn't gone entirely because I still have to figure out what I'm gonna do about validation, but for the most part this knocks out one of the "layers of backwards compatibility", as I've been referring to it, and is moving us closer to a future where Flashii actually gets real updates.
If you run into anything that's broken and you're inhibited from reporting it through the forum, do it through chat or mail me at flashii-issues@flash.moe.
2023-08-02 22:12:47 +00:00

122 lines
3.9 KiB
PHP

<?php
namespace Misuzu\Users\Assets;
use InvalidArgumentException;
use RuntimeException;
use Misuzu\Users\UserInfo;
abstract class UserImageAsset implements UserImageAssetInterface {
public const PUBLIC_STORAGE = '/msz-storage';
public const TYPE_PNG = IMAGETYPE_PNG;
public const TYPE_JPG = IMAGETYPE_JPEG;
public const TYPE_GIF = IMAGETYPE_GIF;
public const TYPES_EXT = [
self::TYPE_PNG => 'png',
self::TYPE_JPG => 'jpg',
self::TYPE_GIF => 'gif',
];
protected string $userId;
public function __construct(UserInfo $userInfo) {
$this->userId = (string)$userInfo->getId();
}
public function getUserId(): string {
return $this->userId;
}
public abstract function getMaxWidth(): int;
public abstract function getMaxHeight(): int;
public abstract function getMaxBytes(): int;
public function getAllowedTypes(): array {
return [self::TYPE_PNG, self::TYPE_JPG, self::TYPE_GIF];
}
public function isAllowedType(int $type): bool {
return in_array($type, $this->getAllowedTypes());
}
private function getImageSize(): array {
return $this->isPresent() && ($imageSize = getimagesize($this->getPath())) ? $imageSize : [];
}
public function getWidth(): int {
return $this->getImageSize()[0] ?? -1;
}
public function getHeight(): int {
return $this->getImageSize()[1] ?? -1;
}
public function getIntType(): int {
return $this->getImageSize()[2] ?? -1;
}
public function getMimeType(): string {
return mime_content_type($this->getPath());
}
public function getFileExtension(): string {
return self::TYPES_EXT[$this->getIntType()] ?? 'img';
}
public abstract function getFileName(): string;
public abstract function getRelativePath(): string;
public function isPresent(): bool {
return is_file($this->getPath());
}
public function getPublicPath(): string {
return self::PUBLIC_STORAGE . '/' . $this->getRelativePath();
}
public function delete(): void {
if($this->isPresent())
unlink($this->getPath());
}
public function getStoragePath(): string {
return MSZ_ROOT . DIRECTORY_SEPARATOR . 'store';
}
public function getPath(): string {
return $this->getStoragePath() . DIRECTORY_SEPARATOR . $this->getRelativePath();
}
public function setFromPath(string $path): void {
if(!is_file($path))
throw new InvalidArgumentException('$path not found.');
$imageInfo = getimagesize($path);
if($imageInfo === false || $imageInfo[0] < 1 || $imageInfo[1] < 1)
throw new InvalidArgumentException('$path is not a valid image.');
if(!self::isAllowedType($imageInfo[2]))
throw new InvalidArgumentException('$path is not an allowed image file.');
if($imageInfo[0] > $this->getMaxWidth() || $imageInfo[1] > $this->getMaxHeight())
throw new InvalidArgumentException('Dimensions of $path are too large.');
if(filesize($path) > $this->getMaxBytes())
throw new InvalidArgumentException('File size of $path is too large.');
$this->delete();
$targetPath = $this->getPath();
$targetDir = dirname($targetPath);
if(!is_dir($targetDir))
mkdir($targetDir, 0775, true);
if(is_uploaded_file($path) ? !move_uploaded_file($path, $targetPath) : !copy($path, $targetPath))
throw new RuntimeException('Was unable to move $path to the storage destination.');
}
public function setFromData(string $data): void {
$file = tempnam(sys_get_temp_dir(), 'msz');
if($file === false || !is_file($file))
throw new RuntimeException('Failed to apply user asset data.');
chmod($file, 0664);
file_put_contents($file, $data);
self::setFromPath($file);
unlink($file);
}
}