2018-10-08 14:29:18 +02:00
|
|
|
<?php
|
|
|
|
define('MSZ_USER_AVATAR_FORMAT', '%d.msz');
|
2019-03-25 21:11:31 +01:00
|
|
|
define('MSZ_USER_AVATAR_RESOLUTION_DEFAULT', 200);
|
|
|
|
define('MSZ_USER_AVATAR_RESOLUTION_ORIGINAL', 0);
|
|
|
|
define('MSZ_USER_AVATAR_RESOLUTIONS', [
|
|
|
|
MSZ_USER_AVATAR_RESOLUTION_ORIGINAL,
|
|
|
|
40, 60, 80, 100, 120, 200, 240,
|
|
|
|
]);
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_valid_resolution(int $resolution): bool {
|
2019-03-25 21:11:31 +01:00
|
|
|
return in_array($resolution, MSZ_USER_AVATAR_RESOLUTIONS, true);
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_resolution_closest(int $resolution): int {
|
|
|
|
if($resolution === 0) {
|
2019-03-25 21:11:31 +01:00
|
|
|
return MSZ_USER_AVATAR_RESOLUTION_ORIGINAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
$closest = null;
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
foreach(MSZ_USER_AVATAR_RESOLUTIONS as $res) {
|
|
|
|
if($res === MSZ_USER_AVATAR_RESOLUTION_ORIGINAL) {
|
2019-03-25 21:11:31 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if($closest === null || abs($resolution - $closest) >= abs($res - $resolution)) {
|
2019-03-25 21:11:31 +01:00
|
|
|
$closest = $res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $closest;
|
|
|
|
}
|
2018-10-08 14:29:18 +02:00
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_delete(int $userId): void {
|
2018-10-08 14:29:18 +02:00
|
|
|
$avatarFileName = sprintf(MSZ_USER_AVATAR_FORMAT, $userId);
|
2019-03-25 21:11:31 +01:00
|
|
|
$avatarPathFormat = MSZ_STORAGE . '/avatars/%s/%s';
|
2018-10-08 14:29:18 +02:00
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
foreach(MSZ_USER_AVATAR_RESOLUTIONS as $res) {
|
2019-03-25 21:11:31 +01:00
|
|
|
safe_delete(sprintf(
|
|
|
|
$avatarPathFormat,
|
|
|
|
$res === MSZ_USER_AVATAR_RESOLUTION_ORIGINAL
|
|
|
|
? 'original'
|
|
|
|
: sprintf('%1$dx%1$d', $res),
|
|
|
|
$avatarFileName
|
|
|
|
));
|
2018-10-08 14:29:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
define('MSZ_USER_AVATAR_TYPE_PNG', IMAGETYPE_PNG);
|
|
|
|
define('MSZ_USER_AVATAR_TYPE_JPG', IMAGETYPE_JPEG);
|
|
|
|
define('MSZ_USER_AVATAR_TYPE_GIF', IMAGETYPE_GIF);
|
|
|
|
define('MSZ_USER_AVATAR_TYPES', [
|
|
|
|
MSZ_USER_AVATAR_TYPE_PNG,
|
|
|
|
MSZ_USER_AVATAR_TYPE_JPG,
|
|
|
|
MSZ_USER_AVATAR_TYPE_GIF,
|
|
|
|
]);
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_is_allowed_type(int $type): bool {
|
2018-10-08 14:29:18 +02:00
|
|
|
return in_array($type, MSZ_USER_AVATAR_TYPES, true);
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_default_options(): array {
|
2019-08-14 21:40:36 +02:00
|
|
|
return [
|
2019-12-04 00:49:46 +01:00
|
|
|
'max_width' => \Misuzu\Config::get('avatar.max_width', \Misuzu\Config::TYPE_INT, 2000),
|
|
|
|
'max_height' => \Misuzu\Config::get('avatar.max_height', \Misuzu\Config::TYPE_INT, 2000),
|
2019-12-03 19:52:20 +01:00
|
|
|
'max_size' => \Misuzu\Config::get('avatar.max_height', \Misuzu\Config::TYPE_INT, 500000),
|
2019-08-14 21:40:36 +02:00
|
|
|
];
|
2018-10-08 14:29:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
define('MSZ_USER_AVATAR_NO_ERRORS', 0);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_INVALID_IMAGE', 1);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_PROHIBITED_TYPE', 2);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_DIMENSIONS_TOO_LARGE', 3);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_DATA_TOO_LARGE', 4);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_TMP_FAILED', 5);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_STORE_FAILED', 6);
|
|
|
|
define('MSZ_USER_AVATAR_ERROR_FILE_NOT_FOUND', 7);
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_set_from_path(int $userId, string $path, array $options = []): int {
|
|
|
|
if(!file_exists($path)) {
|
2018-10-08 14:29:18 +02:00
|
|
|
return MSZ_USER_AVATAR_ERROR_FILE_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2019-08-14 21:40:36 +02:00
|
|
|
$options = array_merge(user_avatar_default_options(), $options);
|
2018-10-08 14:29:18 +02:00
|
|
|
|
|
|
|
// 0 => width, 1 => height, 2 => type
|
|
|
|
$imageInfo = getimagesize($path);
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if($imageInfo === false
|
2018-10-08 14:29:18 +02:00
|
|
|
|| count($imageInfo) < 3
|
|
|
|
|| $imageInfo[0] < 1
|
|
|
|
|| $imageInfo[1] < 1) {
|
|
|
|
return MSZ_USER_AVATAR_ERROR_INVALID_IMAGE;
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if(!user_avatar_is_allowed_type($imageInfo[2])) {
|
2018-10-08 14:29:18 +02:00
|
|
|
return MSZ_USER_AVATAR_ERROR_PROHIBITED_TYPE;
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if($imageInfo[0] > $options['max_width']
|
2018-10-08 14:29:18 +02:00
|
|
|
|| $imageInfo[1] > $options['max_height']) {
|
|
|
|
return MSZ_USER_AVATAR_ERROR_DIMENSIONS_TOO_LARGE;
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if(filesize($path) > $options['max_size']) {
|
2018-10-08 14:29:18 +02:00
|
|
|
return MSZ_USER_AVATAR_ERROR_DATA_TOO_LARGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
user_avatar_delete($userId);
|
|
|
|
|
|
|
|
$fileName = sprintf(MSZ_USER_AVATAR_FORMAT, $userId);
|
2019-02-05 21:29:37 +01:00
|
|
|
$storageDir = MSZ_STORAGE . '/avatars/original';
|
|
|
|
mkdirs($storageDir, true);
|
|
|
|
$avatarPath = "{$storageDir}/{$fileName}";
|
2018-10-08 14:29:18 +02:00
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if(!copy($path, $avatarPath)) {
|
2018-10-08 14:29:18 +02:00
|
|
|
return MSZ_USER_AVATAR_ERROR_STORE_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MSZ_USER_AVATAR_NO_ERRORS;
|
|
|
|
}
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
function user_avatar_set_from_data(int $userId, string $data, array $options = []): int {
|
2018-10-08 14:29:18 +02:00
|
|
|
$tmp = tempnam(sys_get_temp_dir(), 'msz');
|
|
|
|
|
2019-06-10 19:04:53 +02:00
|
|
|
if($tmp === false || !file_exists($tmp)) {
|
2018-10-08 14:29:18 +02:00
|
|
|
return MSZ_USER_AVATAR_ERROR_TMP_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
chmod($tmp, 644);
|
|
|
|
file_put_contents($tmp, $data);
|
|
|
|
$result = user_avatar_set_from_path($userId, $tmp, $options);
|
|
|
|
safe_delete($tmp);
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|