misuzu/src/Users/Assets/UserAvatarAsset.php
2023-09-08 20:40:48 +00:00

105 lines
3.4 KiB
PHP

<?php
namespace Misuzu\Users\Assets;
use Misuzu\Imaging\Image;
class UserAvatarAsset extends UserImageAsset implements UserAssetScalableInterface {
private const FORMAT = 'avatars/%s/%d.msz';
private const DIR_ORIG = 'original';
private const DIR_SIZE = '%1$dx%1$d';
public const DEFAULT_DIMENSION = 200;
public const DIMENSIONS = [
40, 60, 80, 100, 120, 200, 240,
];
private const MAX_RES = 2000;
private const MAX_BYTES = 1000000;
public function getMaxWidth(): int {
global $cfg;
return $cfg->getInteger('avatar.max_res', self::MAX_RES);
}
public function getMaxHeight(): int {
return $this->getMaxWidth();
}
public function getMaxBytes(): int {
global $cfg;
return $cfg->getInteger('avatar.max_size', self::MAX_BYTES);
}
public static function clampDimensions(int $dimensions): int {
$closest = null;
foreach(self::DIMENSIONS as $dims)
if($closest === null || abs($dimensions - $closest) >= abs($dims - $dimensions))
$closest = $dims;
return $closest;
}
public function getFileName(): string {
return sprintf('avatar-%1$d.%2$s', $this->getUserId(), $this->getFileExtension());
}
public function getScaledFileName(int $dims): string {
return sprintf('avatar-%1$d-%3$dx%3$d.%2$s', $this->getUserId(), $this->getScaledFileExtension($dims), self::clampDimensions($dims));
}
public function getScaledMimeType(int $dims): string {
if(!$this->isScaledPresent($dims))
return '';
return mime_content_type($this->getScaledPath($dims));
}
public function getScaledFileExtension(int $dims): string {
$imageSize = getimagesize($this->getScaledPath($dims));
if($imageSize === false)
return 'img';
return self::TYPES_EXT[$imageSize[2]] ?? 'img';
}
public function getRelativePath(): string {
return sprintf(self::FORMAT, self::DIR_ORIG, $this->getUserId());
}
public function getScaledRelativePath(int $dims): string {
$dims = self::clampDimensions($dims);
return sprintf(self::FORMAT, sprintf(self::DIR_SIZE, $dims), $this->getUserId());
}
public function getScaledPath(int $dims): string {
return $this->getStoragePath() . DIRECTORY_SEPARATOR . $this->getScaledRelativePath($dims);
}
public function isScaledPresent(int $dims): bool {
return is_file($this->getScaledPath($dims));
}
public function deleteScaled(int $dims): void {
if($this->isScaledPresent($dims))
unlink($this->getScaledPath($dims));
}
public function ensureScaledExists(int $dims): void {
if(!$this->isPresent())
return;
$dims = self::clampDimensions($dims);
if($this->isScaledPresent($dims))
return;
$scaledPath = $this->getScaledPath($dims);
$scaledDir = dirname($scaledPath);
if(!is_dir($scaledDir))
mkdir($scaledDir, 0775, true);
$scale = Image::create($this->getPath());
$scale->squareCrop($dims);
$scale->save($scaledPath);
$scale->destroy();
}
public function getPublicScaledPath(int $dims): string {
return self::PUBLIC_STORAGE . '/' . $this->getScaledRelativePath($dims);
}
public function delete(): void {
parent::delete();
foreach(self::DIMENSIONS as $dims)
$this->deleteScaled($dims);
}
}