mirror of
https://github.com/chevereto/chevereto.git
synced 2026-05-07 08:47:01 +02:00
Automatic push 4.1.0
This commit is contained in:
@@ -88,7 +88,11 @@ class Album
|
||||
}
|
||||
$return = $album_db;
|
||||
if (isset($return['album_password']) && hasEncryption()) {
|
||||
$return['album_password'] = decrypt($return['album_password']);
|
||||
try {
|
||||
$return['album_password'] = decrypt($return['album_password']);
|
||||
} catch (Throwable) {
|
||||
$return['album_password'] = $return['album_password'];
|
||||
}
|
||||
}
|
||||
|
||||
return $pretty
|
||||
@@ -114,7 +118,11 @@ class Album
|
||||
if (hasEncryption()) {
|
||||
foreach ($db_rows as &$row) {
|
||||
if (isset($row['album_password'])) {
|
||||
$row['album_password'] = decrypt($row['album_password']);
|
||||
try {
|
||||
$row['album_password'] = decrypt($row['album_password']);
|
||||
} catch (Throwable) {
|
||||
$row['album_password'] = $row['album_password'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +81,15 @@ class DB extends GDB
|
||||
string $clause = 'AND',
|
||||
array $sort = [],
|
||||
int $limit = null,
|
||||
int $fetch_style = PDO::FETCH_ASSOC
|
||||
int $fetch_style = PDO::FETCH_ASSOC,
|
||||
array $valuesOperators = []
|
||||
): mixed {
|
||||
$prefix = self::getFieldPrefix($table);
|
||||
$values = self::getPrefixedValues($prefix, $values);
|
||||
$valuesOperators = self::getPrefixedValues($prefix, $valuesOperators);
|
||||
$sort = self::getPrefixedSort($prefix, $sort);
|
||||
|
||||
return GDB::get($table, $values, $clause, $sort, $limit, $fetch_style);
|
||||
return GDB::get($table, $values, $clause, $sort, $limit, $fetch_style, $valuesOperators);
|
||||
}
|
||||
|
||||
public static function update(
|
||||
|
||||
76
app/src/Legacy/Classes/Fonts.php
Normal file
76
app/src/Legacy/Classes/Fonts.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chevereto\Legacy\Classes;
|
||||
|
||||
class Fonts
|
||||
{
|
||||
private array $handles = [
|
||||
0 => 'Helvetica, Arial, sans-serif',
|
||||
1 => '"Times New Roman", Times, serif',
|
||||
2 => 'Georgia, serif',
|
||||
3 => 'Tahoma, Verdana, sans-serif',
|
||||
4 => '"Trebuchet MS", Helvetica, sans-serif',
|
||||
5 => 'Geneva, Verdana, sans-serif',
|
||||
6 => '"Courier New", Courier, monospace',
|
||||
7 => '"Brush Script MT", cursive',
|
||||
8 => 'Copperplate, Papyrus, fantasy',
|
||||
];
|
||||
|
||||
private array $names = [
|
||||
0 => 'Helvetica, Arial, sans-serif',
|
||||
1 => 'Times New Roman, Times, serif',
|
||||
2 => 'Georgia, serif',
|
||||
3 => 'Tahoma, Verdana, sans-serif',
|
||||
4 => 'Trebuchet MS, Helvetica, sans-serif',
|
||||
5 => 'Geneva, Verdana, sans-serif',
|
||||
6 => 'Courier New, Courier, monospace',
|
||||
7 => 'Brush Script MT, cursive',
|
||||
8 => 'Copperplate, Papyrus, fantasy',
|
||||
];
|
||||
|
||||
private array $get = [];
|
||||
|
||||
private array $handlesToId = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->handlesToId = array_flip($this->handles);
|
||||
foreach ($this->handles as $id => $handle) {
|
||||
$this->get[$id] = [$handle, $this->names[$id]];
|
||||
}
|
||||
}
|
||||
|
||||
public function handlesToId(): array
|
||||
{
|
||||
return $this->handlesToId;
|
||||
}
|
||||
|
||||
public function get(): array
|
||||
{
|
||||
return $this->get;
|
||||
}
|
||||
|
||||
public function getHandle(int $id): string
|
||||
{
|
||||
return $this->get()[$id][0] ?? '';
|
||||
}
|
||||
|
||||
public function getName(int $id): string
|
||||
{
|
||||
return $this->get()[$id][1] ?? '';
|
||||
}
|
||||
|
||||
public function getIdForHandle(string $handle): int
|
||||
{
|
||||
return $this->handlesToId[$handle] ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ use function Chevereto\Legacy\G\starts_with;
|
||||
use function Chevereto\Legacy\G\truncate;
|
||||
use function Chevereto\Legacy\G\unlinkIfExists;
|
||||
use function Chevereto\Legacy\G\url_to_relative;
|
||||
use function Chevereto\Legacy\get_image_fileinfo;
|
||||
use function Chevereto\Legacy\get_fileinfo;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\system_notification_email;
|
||||
use function Chevereto\Legacy\time_elapsed_string;
|
||||
@@ -52,6 +52,8 @@ use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use FFMpeg\Coordinate\TimeCode;
|
||||
use FFMpeg\FFMpeg;
|
||||
use Intervention\Image\ImageManagerStatic;
|
||||
use PHPExif\Exif;
|
||||
use function Safe\password_hash;
|
||||
@@ -82,12 +84,15 @@ class Image
|
||||
'chain',
|
||||
'thumb_size',
|
||||
'medium_size',
|
||||
'frame_size',
|
||||
'title',
|
||||
'expiration_date_gmt',
|
||||
'likes',
|
||||
'is_animated',
|
||||
'is_approved',
|
||||
'is_360',
|
||||
'duration',
|
||||
'type'
|
||||
];
|
||||
|
||||
protected static array $expirations = [
|
||||
@@ -116,7 +121,19 @@ class Image
|
||||
['year', 1, 31536000],
|
||||
];
|
||||
|
||||
public static array $chain_sizes = ['original', 'image', 'medium', 'thumb'];
|
||||
public static array $types = [
|
||||
1 => 'image',
|
||||
2 => 'video',
|
||||
3 => 'audio',
|
||||
];
|
||||
|
||||
public static array $chain_sizes = [
|
||||
'frame', // 2^4
|
||||
'original', // 2^3
|
||||
'image', // 2^2
|
||||
'medium', // 2^1
|
||||
'thumb', // 2^0
|
||||
];
|
||||
|
||||
public static function getSingle(
|
||||
int $id,
|
||||
@@ -285,36 +302,37 @@ class Image
|
||||
return $slice;
|
||||
}
|
||||
|
||||
public static function getSrcTargetSingle(array $filearray, bool $prefix = true): array
|
||||
public static function getSrcTargetSingle(array $fileArray, bool $prefix = true): array
|
||||
{
|
||||
$prefix = $prefix ? 'image_' : null;
|
||||
$folder = CHV_PATH_IMAGES;
|
||||
$pretty = !isset($filearray['image_id']);
|
||||
$mode = $filearray[$prefix . 'storage_mode'];
|
||||
$pretty = !isset($fileArray['image_id']);
|
||||
$mode = $fileArray[$prefix . 'storage_mode'];
|
||||
$chain_mask = str_split(
|
||||
(string) str_pad(
|
||||
decbin((int) ($filearray[$pretty ? 'chain' : 'image_chain'])),
|
||||
4,
|
||||
decbin((int) ($fileArray[$pretty ? 'chain' : 'image_chain'])),
|
||||
5,
|
||||
'0',
|
||||
STR_PAD_LEFT
|
||||
)
|
||||
);
|
||||
$chain_to_sufix = [
|
||||
$chain_to_suffix = [
|
||||
'image' => '.',
|
||||
'frame' => '.fr.',
|
||||
'medium' => '.md.',
|
||||
'thumb' => '.th.',
|
||||
'medium' => '.md.'
|
||||
];
|
||||
if ($pretty) {
|
||||
$type = isset($filearray['storage']['id']) ? 'url' : 'path';
|
||||
$type = isset($fileArray['storage']['id']) ? 'url' : 'path';
|
||||
} else {
|
||||
$type = isset($filearray['storage_id']) ? 'url' : 'path';
|
||||
$type = isset($fileArray['storage_id']) ? 'url' : 'path';
|
||||
}
|
||||
if ($type == 'url') { // URL resource folder
|
||||
$folder = add_ending_slash($pretty ? $filearray['storage']['url'] : $filearray['storage_url']);
|
||||
if ($type == 'url') {
|
||||
$folder = add_ending_slash($pretty ? $fileArray['storage']['url'] : $fileArray['storage_url']);
|
||||
}
|
||||
switch ($mode) {
|
||||
case 'datefolder':
|
||||
$datetime = $filearray[$prefix . 'date'];
|
||||
$datetime = $fileArray[$prefix . 'date'];
|
||||
$datefolder = preg_replace('/(.*)(\s.*)/', '$1', str_replace('-', '/', $datetime));
|
||||
$folder .= add_ending_slash($datefolder); // Y/m/d/
|
||||
|
||||
@@ -327,20 +345,25 @@ class Image
|
||||
// use direct $folder
|
||||
break;
|
||||
case 'path':
|
||||
$folder = add_ending_slash($filearray['path']);
|
||||
$folder = add_ending_slash($fileArray['path']);
|
||||
|
||||
break;
|
||||
}
|
||||
$targets = [
|
||||
'type' => $type,
|
||||
'chain' => [
|
||||
'frame' => null,
|
||||
'image' => null,
|
||||
'thumb' => null,
|
||||
'medium' => null
|
||||
]
|
||||
];
|
||||
foreach (array_keys($targets['chain']) as $k) {
|
||||
$targets['chain'][$k] = $folder . $filearray[$prefix . 'name'] . $chain_to_sufix[$k] . $filearray[$prefix . 'extension'];
|
||||
$extension = $fileArray[$prefix . 'extension'];
|
||||
if ($k !== 'image' && in_array($extension, ['mp4', 'webm'])) {
|
||||
$extension = 'jpeg';
|
||||
}
|
||||
$targets['chain'][$k] = $folder . $fileArray[$prefix . 'name'] . $chain_to_suffix[$k] . $extension;
|
||||
}
|
||||
if ($type == 'path') {
|
||||
foreach ($targets['chain'] as $k => $v) {
|
||||
@@ -557,7 +580,7 @@ class Image
|
||||
|
||||
// Mostly for people uploading two times the same image to test or just bug you
|
||||
// $mixed => $_FILES or md5 string
|
||||
public static function isDuplicatedUpload(array|string $source, string $time_frame = 'P1D'): bool
|
||||
public static function isDuplicatedUpload(array|string $source, string $timePeriod = 'P1D'): bool
|
||||
{
|
||||
if (is_array($source) && isset($source['tmp_name'])) {
|
||||
$filename = $source['tmp_name'];
|
||||
@@ -576,7 +599,7 @@ class Image
|
||||
$db->query('SELECT * FROM ' . DB::getTable('images') . ' WHERE (image_md5=:md5 OR image_source_md5=:md5) AND image_uploader_ip=:ip AND image_date_gmt > :date_gmt');
|
||||
$db->bind(':md5', $md5_file);
|
||||
$db->bind(':ip', get_client_ip());
|
||||
$db->bind(':date_gmt', datetime_sub(datetimegmt(), $time_frame));
|
||||
$db->bind(':date_gmt', datetime_sub(datetimegmt(), $timePeriod));
|
||||
$db->exec();
|
||||
|
||||
return (bool) $db->fetchColumn();
|
||||
@@ -591,7 +614,7 @@ class Image
|
||||
): array {
|
||||
$params['use_file_date'] = $params['use_file_date'] ?? false;
|
||||
nullify_string($params['album_id']);
|
||||
$datefolder = '';
|
||||
$dateFolder = '';
|
||||
|
||||
try {
|
||||
if ($user !== []
|
||||
@@ -605,8 +628,20 @@ class Image
|
||||
throw new Exception(_s('Duplicated upload'), 101);
|
||||
}
|
||||
$storage_id = null;
|
||||
$upload_types = [
|
||||
'image' => 1,
|
||||
'video' => 2,
|
||||
// 'audio' => 4,
|
||||
// 'document' => 8,
|
||||
// 'other' => 16,
|
||||
];
|
||||
$mimetype = strtok($params['mimetype'], '/');
|
||||
$type_chain = $upload_types[$mimetype] ?? 1;
|
||||
$get_active_storages = env()['CHEVERETO_ENABLE_EXTERNAL_STORAGE']
|
||||
? Storage::get(['is_active' => 1])
|
||||
? Storage::get([
|
||||
'is_active' => 1,
|
||||
'type_chain' => $type_chain
|
||||
])
|
||||
: [];
|
||||
if ($get_active_storages !== []) {
|
||||
if (count($get_active_storages) > 1) {
|
||||
@@ -659,14 +694,14 @@ class Image
|
||||
'date' => $stockDate,
|
||||
'date_gmt' => $stockDateGmt,
|
||||
];
|
||||
$datefolder = date('Y/m/d/', strtotime($datefolder_stock['date']));
|
||||
$upload_path = CHV_PATH_IMAGES . $datefolder;
|
||||
$dateFolder = date('Y/m/d/', strtotime($datefolder_stock['date']));
|
||||
$upload_path = CHV_PATH_IMAGES . $dateFolder;
|
||||
|
||||
break;
|
||||
}
|
||||
$filenaming = getSetting('upload_filenaming');
|
||||
if ($filenaming !== 'id' && in_array($params['privacy'] ?? '', ['password', 'private', 'private_but_link'])) {
|
||||
$filenaming = 'random';
|
||||
$fileNaming = getSetting('upload_filenaming');
|
||||
if ($fileNaming !== 'id' && in_array($params['privacy'] ?? '', ['password', 'private', 'private_but_link'])) {
|
||||
$fileNaming = 'random';
|
||||
}
|
||||
$upload_options = [
|
||||
'max_size' => get_bytes(getSetting('upload_max_filesize_mb') . ' MB'),
|
||||
@@ -674,7 +709,7 @@ class Image
|
||||
? $user['image_keep_exif']
|
||||
: getSetting('upload_image_exif'),
|
||||
];
|
||||
if ($filenaming == 'id') {
|
||||
if ($fileNaming == 'id') {
|
||||
try {
|
||||
$dummy = [
|
||||
'name' => '',
|
||||
@@ -691,27 +726,29 @@ class Image
|
||||
'chain' => 0,
|
||||
'thumb_size' => 0,
|
||||
'medium_size' => 0,
|
||||
'frame_size' => 0,
|
||||
'duration' => 0,
|
||||
];
|
||||
$dummy_insert = DB::insert('images', $dummy);
|
||||
DB::delete('images', ['id' => $dummy_insert]);
|
||||
$target_id = $dummy_insert;
|
||||
} catch (Throwable $e) {
|
||||
$filenaming = 'original';
|
||||
$fileNaming = 'original';
|
||||
}
|
||||
}
|
||||
$upload_options['filenaming'] = $filenaming;
|
||||
$upload_options['allowed_formats'] = self::getEnabledImageFormats();
|
||||
$upload_options['filenaming'] = $fileNaming;
|
||||
$upload_options['allowed_formats'] = self::getEnabledImageExtensions();
|
||||
$image_upload = self::upload(
|
||||
$source,
|
||||
$upload_path,
|
||||
($filenaming == 'id' && isset($target_id))
|
||||
($fileNaming == 'id' && isset($target_id))
|
||||
? encodeID((int) $target_id)
|
||||
: null,
|
||||
$upload_options,
|
||||
$storage_id,
|
||||
$guestSessionHandle
|
||||
);
|
||||
$chain_mask = [0, 1, 0, 1]; // original image medium thumb
|
||||
$chain_mask = [0, 0, 1, 0, 1]; // frame, original, image, medium, thumb
|
||||
if ($do_dupe_check && self::isDuplicatedUpload($image_upload['uploaded']['fileinfo']['md5'])) {
|
||||
throw new Exception(_s('Duplicated upload'), 102);
|
||||
}
|
||||
@@ -751,6 +788,14 @@ class Image
|
||||
if (is_animated_image($image_upload['uploaded']['file'])) {
|
||||
$must_resize = false;
|
||||
}
|
||||
$resizeSourceImage = $image_upload['uploaded']['file'];
|
||||
$uploadDir = dirname($resizeSourceImage);
|
||||
if ($image_upload['source']['type'] === 'video') {
|
||||
$frameImage = $uploadDir . '/' . $image_upload['uploaded']['name'] . '.fr.jpeg';
|
||||
rename($image_upload['uploaded']['frame'], $frameImage);
|
||||
$resizeSourceImage = $frameImage;
|
||||
$chain_mask[0] = 1;
|
||||
}
|
||||
if ($must_resize) {
|
||||
$source_md5 = $image_upload['uploaded']['fileinfo']['md5'];
|
||||
if ($do_dupe_check && self::isDuplicatedUpload($source_md5)) {
|
||||
@@ -766,8 +811,8 @@ class Image
|
||||
$image_resize_options = ['width' => $params['width']];
|
||||
}
|
||||
$image_upload['uploaded'] = self::resize(
|
||||
$image_upload['uploaded']['file'],
|
||||
dirname($image_upload['uploaded']['file']),
|
||||
$resizeSourceImage,
|
||||
dirname($resizeSourceImage),
|
||||
null,
|
||||
$image_resize_options
|
||||
);
|
||||
@@ -784,8 +829,8 @@ class Image
|
||||
$medium_fixed_dimension = getSetting('upload_medium_fixed_dimension');
|
||||
$is_animated_image = is_animated_image($image_upload['uploaded']['file']);
|
||||
$image_thumb = self::resize(
|
||||
source: $image_upload['uploaded']['file'],
|
||||
destination: dirname($image_upload['uploaded']['file']),
|
||||
source: $resizeSourceImage,
|
||||
destination: $uploadDir,
|
||||
filename: $image_upload['uploaded']['name'] . '.th',
|
||||
options: $image_thumb_options
|
||||
);
|
||||
@@ -814,8 +859,8 @@ class Image
|
||||
$apply_watermark = false;
|
||||
}
|
||||
}
|
||||
if ($apply_watermark && self::watermark($image_upload['uploaded']['file'])) {
|
||||
$image_upload['uploaded']['fileinfo'] = GGet_image_fileinfo($image_upload['uploaded']['file']); // Remake the fileinfo array, new full array file info (todo: faster!)
|
||||
if ($apply_watermark && self::watermark($resizeSourceImage)) {
|
||||
$image_upload['uploaded']['fileinfo'] = GGet_image_fileinfo($resizeSourceImage); // Remake the fileinfo array, new full array file info (todo: faster!)
|
||||
$image_upload['uploaded']['fileinfo']['md5'] = $original_md5; // Preserve original MD5 for watermarked images
|
||||
}
|
||||
if ($image_upload['uploaded']['fileinfo'][$medium_fixed_dimension] > $medium_size || $is_animated_image) {
|
||||
@@ -826,12 +871,12 @@ class Image
|
||||
$image_medium_options[$medium_fixed_dimension] = min($image_medium_options[$medium_fixed_dimension], $image_upload['uploaded']['fileinfo'][$medium_fixed_dimension]);
|
||||
}
|
||||
$image_medium = self::resize(
|
||||
$image_upload['uploaded']['file'],
|
||||
dirname($image_upload['uploaded']['file']),
|
||||
$resizeSourceImage,
|
||||
$uploadDir,
|
||||
$image_upload['uploaded']['name'] . '.md',
|
||||
$image_medium_options
|
||||
);
|
||||
$chain_mask[2] = 1;
|
||||
$chain_mask[3] = 1;
|
||||
}
|
||||
$chain_value = bindec((string) implode('', $chain_mask));
|
||||
$disk_space_needed = $image_upload['uploaded']['fileinfo']['size'];
|
||||
@@ -894,8 +939,9 @@ class Image
|
||||
if (!($image_medium ?? false)) {
|
||||
unset($chain_props['medium']);
|
||||
}
|
||||
$dirChain = dirname($image_upload['uploaded']['file']);
|
||||
foreach ($chain_props as $k => $v) {
|
||||
$chain_file = add_ending_slash(dirname($image_upload['uploaded']['file'])) . $image_upload['uploaded']['name'] . '.' . $v['suffix'] . '.' . ${"image_$k"}['fileinfo']['extension'];
|
||||
$chain_file = add_ending_slash($dirChain) . $image_upload['uploaded']['name'] . '.' . $v['suffix'] . '.' . ${"image_$k"}['fileinfo']['extension'];
|
||||
|
||||
try {
|
||||
$renamed_chain = rename(${"image_$k"}['file'], $chain_file);
|
||||
@@ -926,9 +972,11 @@ class Image
|
||||
'chain' => $chain_value,
|
||||
'thumb_size' => $image_thumb['fileinfo']['size'] ?? 0,
|
||||
'medium_size' => $image_medium['fileinfo']['size'] ?? 0,
|
||||
'frame_size' => $image_upload['uploaded']['frameinfo']['size'] ?? 0,
|
||||
'is_animated' => $is_animated_image,
|
||||
'source_md5' => $source_md5 ?? null,
|
||||
'is_360' => $is_360
|
||||
'is_360' => $is_360,
|
||||
'duration' => $image_upload['uploaded']['fileinfo']['duration'] ?? 0,
|
||||
];
|
||||
if (isset($datefolder_stock)) {
|
||||
foreach ($datefolder_stock as $k => $v) {
|
||||
@@ -964,6 +1012,14 @@ class Image
|
||||
case 'image':
|
||||
$prop = $image_upload['uploaded'];
|
||||
|
||||
break;
|
||||
case 'frame':
|
||||
$prop = [
|
||||
'file' => $frameImage,
|
||||
'filename' => basename($frameImage),
|
||||
'fileinfo' => $image_upload['uploaded']['frameinfo']
|
||||
];
|
||||
|
||||
break;
|
||||
default:
|
||||
$prop = ${"image_$v"};
|
||||
@@ -978,7 +1034,7 @@ class Image
|
||||
}
|
||||
Storage::uploadFiles($toStorage, $storage, [
|
||||
'keyprefix' => $storage_mode == 'datefolder'
|
||||
? $datefolder
|
||||
? $dateFolder
|
||||
: null
|
||||
]);
|
||||
}
|
||||
@@ -1009,7 +1065,7 @@ class Image
|
||||
}
|
||||
}
|
||||
$image_insert_values['title'] = $image_title;
|
||||
if ($filenaming == 'id' && isset($target_id)) { // Insert as a reserved ID
|
||||
if ($fileNaming == 'id' && isset($target_id)) { // Insert as a reserved ID
|
||||
$image_insert_values['id'] = $target_id;
|
||||
}
|
||||
$image_insert_values['title'] = mb_substr($image_insert_values['title'] ?? '', 0, 100, 'UTF-8');
|
||||
@@ -1028,7 +1084,7 @@ class Image
|
||||
DB::insert('images_hash', ['image_id' => $uploaded_id, 'hash' => $deleteHash]);
|
||||
if (isset($toStorage)) {
|
||||
foreach ($toStorage as $k => $v) {
|
||||
unlinkIfExists($v['file']); // Remove the source image
|
||||
unlinkIfExists($v['file']); // Remove files from local when doing external storage
|
||||
}
|
||||
}
|
||||
$privacyTargets = ['private', 'private_but_link'];
|
||||
@@ -1085,16 +1141,29 @@ class Image
|
||||
}
|
||||
}
|
||||
|
||||
public static function getEnabledImageFormats(): array
|
||||
public static function getEnabledImageExtensions(): array
|
||||
{
|
||||
$formats = explode(',', Settings::get('upload_enabled_image_formats'));
|
||||
if (in_array('jpg', $formats)) {
|
||||
if (in_array('jpg', $formats) && !in_array('jpeg', $formats)) {
|
||||
$formats[] = 'jpeg';
|
||||
}
|
||||
|
||||
return $formats;
|
||||
}
|
||||
|
||||
public static function getEnabledImageAcceptAttribute(): string
|
||||
{
|
||||
$extensions = self::getEnabledImageExtensions();
|
||||
$accept = [];
|
||||
$videos = ['mp4', 'webm'];
|
||||
foreach ($extensions as $extension) {
|
||||
$type = in_array($extension, $videos) ? 'video' : 'image';
|
||||
$accept[] = "$type/$extension";
|
||||
}
|
||||
|
||||
return implode(',', $accept);
|
||||
}
|
||||
|
||||
public static function resize(
|
||||
string $source,
|
||||
?string $destination,
|
||||
@@ -1210,7 +1279,10 @@ class Image
|
||||
$values['is_approved'] = 1;
|
||||
}
|
||||
$insert = DB::insert('images', $values);
|
||||
$disk_space_used = $values['size'] + $values['thumb_size'] + $values['medium_size'];
|
||||
$disk_space_used = $values['size']
|
||||
+ $values['thumb_size']
|
||||
+ $values['medium_size']
|
||||
+ $values['frame_size'];
|
||||
Stat::track([
|
||||
'action' => 'insert',
|
||||
'table' => 'images',
|
||||
@@ -1255,7 +1327,10 @@ class Image
|
||||
public static function delete(int $id, bool $update_user = true): int
|
||||
{
|
||||
$image = self::getSingle(id: $id, pretty: true);
|
||||
$disk_space_used = $image['size'] + ($image['thumb']['size'] ?? 0) + ($image['medium']['size'] ?? 0);
|
||||
$disk_space_used = $image['size']
|
||||
+ $image['thumb_size']
|
||||
+ $image['medium_size']
|
||||
+ $image['frame_size'];
|
||||
if ($image['file_resource']['type'] == 'path') {
|
||||
foreach ($image['file_resource']['chain'] as $file_delete) {
|
||||
if (file_exists($file_delete) && !unlinkIfExists($file_delete)) {
|
||||
@@ -1375,60 +1450,13 @@ class Image
|
||||
$medium_size = getSetting('upload_medium_size');
|
||||
$medium_fixed_dimension = getSetting('upload_medium_fixed_dimension');
|
||||
if ($targets['type'] == 'path') {
|
||||
if ($image['size'] == 0) {
|
||||
$get_image_fileinfo = GGet_image_fileinfo($targets['chain']['image']);
|
||||
$update_missing_values = [
|
||||
'width' => $get_image_fileinfo['width'],
|
||||
'height' => $get_image_fileinfo['height'],
|
||||
'size' => $get_image_fileinfo['size'],
|
||||
];
|
||||
foreach (['thumb', 'medium'] as $k) {
|
||||
if (!array_key_exists($k, $targets['chain'])) {
|
||||
continue;
|
||||
}
|
||||
if ($image[$k . '_size'] == 0) {
|
||||
$update_missing_values[$k . '_size'] = GGet_image_fileinfo($targets['chain'][$k])['size'];
|
||||
}
|
||||
}
|
||||
self::update($image['id'], $update_missing_values);
|
||||
$image = array_merge($image, $update_missing_values);
|
||||
}
|
||||
$is_animated = isset($targets['chain']['image']) && is_animated_image($targets['chain']['image']);
|
||||
if (count($targets['chain']) > 0 && !isset($targets['chain']['thumb'])) {
|
||||
try {
|
||||
$targets['chain']['thumb'] = self::resize(
|
||||
$targets['chain']['image'],
|
||||
pathinfo($targets['chain']['image'], PATHINFO_DIRNAME),
|
||||
$image['name'] . '.th',
|
||||
[
|
||||
'width' => getSetting('upload_thumb_width'),
|
||||
'height' => getSetting('upload_thumb_height'),
|
||||
'forced' => $image['extension'] == 'gif' && $is_animated
|
||||
]
|
||||
)['file'];
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
if ($image[$medium_fixed_dimension] > $medium_size
|
||||
&& count($targets['chain']) > 0
|
||||
&& !isset($targets['chain']['medium'])
|
||||
) {
|
||||
try {
|
||||
$targets['chain']['medium'] = self::resize(
|
||||
$targets['chain']['image'],
|
||||
pathinfo($targets['chain']['image'], PATHINFO_DIRNAME),
|
||||
$image['name'] . '.md',
|
||||
[
|
||||
$medium_fixed_dimension => $medium_size,
|
||||
'forced' => $image['extension'] == 'gif' && $is_animated
|
||||
]
|
||||
)['file'];
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
$is_animated = $image['is_animated'];
|
||||
if (!$is_animated) {
|
||||
$is_animated = isset($targets['chain']['image']) && is_animated_image($targets['chain']['image']);
|
||||
}
|
||||
if (count($targets['chain']) > 0) {
|
||||
$original_md5 = $image['md5'];
|
||||
$image = array_merge($image, get_image_fileinfo($targets['chain']['image']));
|
||||
$image = array_merge($image, get_fileinfo($targets['chain']['image']));
|
||||
$image['md5'] = $original_md5;
|
||||
}
|
||||
if ($is_animated && !$image['is_animated']) {
|
||||
@@ -1441,8 +1469,10 @@ class Image
|
||||
'size' => (int) $image['size'],
|
||||
'size_formatted' => format_bytes($image['size'])
|
||||
];
|
||||
$image = array_merge($image, get_image_fileinfo($targets['chain']['image']), $image_fileinfo);
|
||||
|
||||
$image = array_merge($image, get_fileinfo($targets['chain']['image']), $image_fileinfo);
|
||||
}
|
||||
|
||||
$image['file_resource'] = $targets;
|
||||
$image['url_viewer'] = self::getUrlViewer(
|
||||
$image['id_encoded'],
|
||||
@@ -1454,14 +1484,17 @@ class Image
|
||||
$image['url_short'] = self::getUrlViewer($image['id_encoded']);
|
||||
foreach ($targets['chain'] as $k => $v) {
|
||||
if ($targets['type'] == 'path') {
|
||||
$image[$k] = file_exists($v) ? get_image_fileinfo($v) : null;
|
||||
$image[$k] = file_exists($v) ? get_fileinfo($v) : null;
|
||||
} else {
|
||||
$image[$k] = get_image_fileinfo($v);
|
||||
$image[$k] = get_fileinfo($v);
|
||||
}
|
||||
$image[$k]['size'] = $image[($k == 'image' ? '' : $k . '_') . 'size'];
|
||||
}
|
||||
$image['url_frame'] = $image['frame']['url'] ?? '';
|
||||
$image['size_formatted'] = format_bytes($image['size']);
|
||||
$display_url = $image['url'] ?? '';
|
||||
$display_url = $image['frame']['url']
|
||||
?? $image['url']
|
||||
?? '';
|
||||
$display_width = $image['width'];
|
||||
$display_height = $image['height'];
|
||||
if (!empty($image['medium'])) {
|
||||
@@ -1479,15 +1512,24 @@ class Image
|
||||
|
||||
break;
|
||||
}
|
||||
// if (!$image["is_animated"]) {
|
||||
// // $display_url = $image['url'] ?? '';
|
||||
// }
|
||||
} elseif ($image['size'] > get_bytes('200 KB')) {
|
||||
} elseif (
|
||||
$image['size'] > get_bytes('200 KB')
|
||||
&& $image['type'] === 1
|
||||
) {
|
||||
$display_url = $image['thumb']['url'] ?? '';
|
||||
$display_width = getSetting('upload_thumb_width');
|
||||
$display_height = getSetting('upload_thumb_height');
|
||||
}
|
||||
|
||||
$image['duration'] = (int) ($image['duration'] ?? 0);
|
||||
$seconds = $image['duration'] ?? 0;
|
||||
if ($seconds > 0) {
|
||||
$minutes = floor($seconds / 60);
|
||||
$duration_time = sprintf('%02d', $minutes) . ':' . sprintf('%02d', $seconds % 60);
|
||||
} else {
|
||||
$duration_time = '';
|
||||
}
|
||||
$image['duration_time'] = $duration_time;
|
||||
$image['type'] = self::$types[$image['type']];
|
||||
$image['display_url'] = $display_url;
|
||||
$image['display_width'] = $display_width;
|
||||
$image['display_height'] = $display_height;
|
||||
@@ -1500,6 +1542,8 @@ class Image
|
||||
$image['title_truncated'] = truncate($image['title'] ?? '', 28);
|
||||
$image['title_truncated_html'] = safe_html($image['title_truncated']);
|
||||
$image['is_use_loader'] = getSetting('image_load_max_filesize_mb') !== '' ? ($image['size'] > get_bytes(getSetting('image_load_max_filesize_mb') . 'MB')) : false;
|
||||
$image['display_title'] = $image['title']
|
||||
?? ($image['name'] . '.' . $image['extension']);
|
||||
}
|
||||
|
||||
public static function formatArray(array $dbRow, bool $safe = false): array
|
||||
@@ -1530,4 +1574,16 @@ class Image
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public static function getVideoFrame(string $file, int $time): string
|
||||
{
|
||||
$frameFile = Upload::getTempNam(sys_get_temp_dir());
|
||||
$ffmpeg = FFMpeg::create();
|
||||
$video = $ffmpeg->open($file);
|
||||
$video
|
||||
->frame(TimeCode::fromSeconds($time))
|
||||
->save($frameFile);
|
||||
|
||||
return $frameFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +328,10 @@ class Listing
|
||||
}
|
||||
if ($this->type == 'images' && isset($this->params_hidden['is_animated']) && $this->params_hidden['is_animated'] == 1) {
|
||||
$whereClauses[] = 'image_is_animated = 1';
|
||||
$whereClauses[] = 'image_type = 1';
|
||||
}
|
||||
if ($this->type == 'images' && isset($this->params_hidden['is_video']) && $this->params_hidden['is_video'] == 1) {
|
||||
$whereClauses[] = 'image_type = 2';
|
||||
}
|
||||
if (!empty($whereClauses)) {
|
||||
$whereClauses = implode(' AND ', $whereClauses);
|
||||
@@ -646,7 +650,7 @@ class Listing
|
||||
'sort' => 'date_desc',
|
||||
],
|
||||
'trending' => [
|
||||
'icon' => 'fas fa-poll',
|
||||
'icon' => 'fas fa-chart-simple',
|
||||
'label' => _s('Trending'),
|
||||
'content' => 'all',
|
||||
'sort' => 'views_desc',
|
||||
@@ -736,8 +740,8 @@ class Listing
|
||||
'content' => 'users',
|
||||
],
|
||||
'images' => [
|
||||
'icon' => 'fas fa-image',
|
||||
'label' => _s('Images'),
|
||||
'icon' => 'fas fa-photo-film',
|
||||
'label' => _n('File', 'Files', 20),
|
||||
'content' => 'images',
|
||||
],
|
||||
'albums' => [
|
||||
@@ -763,11 +767,11 @@ class Listing
|
||||
$contents = [
|
||||
'images' => [
|
||||
'icon' => $listings['images']['icon'],
|
||||
'label' => _s('Images'),
|
||||
'label' => $listings['images']['label'],
|
||||
],
|
||||
'albums' => [
|
||||
'icon' => $listings['albums']['icon'],
|
||||
'label' => _n('Album', 'Albums', 20),
|
||||
'label' => $listings['albums']['label'],
|
||||
],
|
||||
];
|
||||
if ((bool) env()['CHEVERETO_ENABLE_USERS']) {
|
||||
|
||||
@@ -176,7 +176,7 @@ class Settings
|
||||
'enable_powered_by' => true,
|
||||
'akismet' => false,
|
||||
'stopforumspam' => false,
|
||||
'upload_enabled_image_formats' => 'jpg,png,bmp,gif,webp',
|
||||
'upload_enabled_image_formats' => 'jpg,png,bmp,gif,webp,mp4,webm',
|
||||
'hostname' => null,
|
||||
'theme_show_embed_content_for' => 'all',
|
||||
'moderatecontent' => false,
|
||||
@@ -249,7 +249,7 @@ class Settings
|
||||
'listing_safe_count' => 100,
|
||||
'image_title_max_length' => 100,
|
||||
'album_name_max_length' => 100,
|
||||
'upload_available_image_formats' => 'jpg,jpeg,png,bmp,gif,webp',
|
||||
'upload_available_image_formats' => 'jpg,jpeg,png,bmp,gif,webp,mp4,webm',
|
||||
]);
|
||||
if (!array_key_exists('active_storage', $settings)) {
|
||||
$settings['active_storage'] = null;
|
||||
|
||||
@@ -26,6 +26,7 @@ use function Chevereto\Legacy\G\get_file_extension;
|
||||
use function Chevereto\Legacy\G\get_filename;
|
||||
use function Chevereto\Legacy\G\get_image_fileinfo;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\get_video_fileinfo;
|
||||
use function Chevereto\Legacy\G\is_animated_webp;
|
||||
use function Chevereto\Legacy\G\is_image_url;
|
||||
use function Chevereto\Legacy\G\is_url;
|
||||
@@ -90,6 +91,8 @@ class Upload
|
||||
'ftp'
|
||||
];
|
||||
|
||||
public string $mediaType = 'image';
|
||||
|
||||
public function uploaded(): array
|
||||
{
|
||||
return $this->uploaded;
|
||||
@@ -256,7 +259,9 @@ class Upload
|
||||
* External storage will be allocated to the temp directory
|
||||
*/
|
||||
if (isset($this->storage_id)) {
|
||||
$this->uploaded_file = forward_slash(dirname($this->downstream)) . '/' . Storage::getStorageValidFilename($this->fixed_filename, $this->storage_id, $this->options['filenaming'], $this->destination);
|
||||
$this->uploaded_file = forward_slash(dirname($this->downstream))
|
||||
. '/'
|
||||
. Storage::getStorageValidFilename($this->fixed_filename, $this->storage_id, $this->options['filenaming'], $this->destination);
|
||||
} else {
|
||||
$this->uploaded_file = name_unique_file($this->destination, $this->fixed_filename, $this->options['filenaming']);
|
||||
}
|
||||
@@ -265,7 +270,8 @@ class Upload
|
||||
'filename' => $this->source_filename, // file.ext
|
||||
'name' => $this->source_name, // file
|
||||
'image_exif' => $this->source_image_exif,
|
||||
'fileinfo' => get_image_fileinfo($this->downstream),
|
||||
'type' => $this->mediaType,
|
||||
'fileinfo' => $this->source_image_fileinfo,
|
||||
];
|
||||
if (stream_resolve_include_path($this->downstream) == false) {
|
||||
throw new Exception('Concurrency: Downstream gone, aborting operation', 666);
|
||||
@@ -291,16 +297,28 @@ class Upload
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
}
|
||||
$fileInfo = get_image_fileinfo($this->uploaded_file);
|
||||
$fileInfo = $this->mediaType === 'video'
|
||||
? get_video_fileinfo($this->uploaded_file)
|
||||
: get_image_fileinfo($this->uploaded_file);
|
||||
if ($fileInfo === []) {
|
||||
throw new Exception("Can't get uploaded info", 610);
|
||||
}
|
||||
$fileInfo['is_360'] = $is_360;
|
||||
$frameFile = null;
|
||||
if ($this->mediaType === 'video') {
|
||||
$frameFile = Image::getVideoFrame(
|
||||
$this->uploaded_file,
|
||||
(int) ($fileInfo['duration'] / 4)
|
||||
);
|
||||
}
|
||||
$this->uploaded = [
|
||||
'file' => $this->uploaded_file,
|
||||
'filename' => get_filename($this->uploaded_file),
|
||||
'name' => get_basename_without_extension($this->uploaded_file),
|
||||
'type' => $this->mediaType,
|
||||
'fileinfo' => $fileInfo,
|
||||
'frame' => $frameFile,
|
||||
'frameinfo' => $frameFile ? get_image_fileinfo($frameFile) : [],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -311,9 +329,16 @@ class Upload
|
||||
return explode(',', $formats);
|
||||
}
|
||||
|
||||
public static function getEnabledImageFormats(): array
|
||||
public static function getAvailableTypes(): array
|
||||
{
|
||||
return Image::getEnabledImageFormats();
|
||||
// 0: all
|
||||
return [
|
||||
'image', // 2^0
|
||||
'video', // 2^1
|
||||
// 'audio', // 2^2
|
||||
// 'document', // 2^3
|
||||
// 'other' // 2^4
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,7 +420,7 @@ class Upload
|
||||
throw new Exception(sprintf('Unwanted extension for %s', $filename), 600);
|
||||
}
|
||||
$extension = get_file_extension($filename);
|
||||
if (!in_array($extension, self::getEnabledImageFormats())) {
|
||||
if (!in_array($extension, Image::getEnabledImageExtensions())) {
|
||||
throw new Exception(sprintf('Unable to handle upload for %s', $filename), 600);
|
||||
}
|
||||
}
|
||||
@@ -463,7 +488,10 @@ class Upload
|
||||
if (!file_exists($this->downstream)) {
|
||||
throw new Exception("Can't fetch target upload source (downstream)", 600);
|
||||
}
|
||||
$this->source_image_fileinfo = get_image_fileinfo($this->downstream);
|
||||
$this->mediaType = str_starts_with($this->source['type'], 'video/') ? 'video' : 'image';
|
||||
$this->source_image_fileinfo = $this->mediaType === 'video'
|
||||
? get_video_fileinfo($this->downstream)
|
||||
: get_image_fileinfo($this->downstream);
|
||||
if ($this->source_image_fileinfo === []) {
|
||||
throw new Exception("Can't get target upload source info", 610);
|
||||
}
|
||||
@@ -476,8 +504,8 @@ class Upload
|
||||
if (!in_array($this->source_image_fileinfo['extension'], $this->options['allowed_formats'])) {
|
||||
throw new Exception(sprintf('Disabled image format (%s)', $this->source_image_fileinfo['extension']), 614);
|
||||
}
|
||||
if (!$this->isValidImageMime($this->source_image_fileinfo['mime'])) {
|
||||
throw new Exception('Invalid image mimetype', 612);
|
||||
if (!$this->isValidMime($this->source_image_fileinfo['mime'])) {
|
||||
throw new Exception('Invalid mimetype', 612);
|
||||
}
|
||||
if (!$this->options['max_size']) {
|
||||
$this->options['max_size'] = self::getDefaultOptions()['max_size'];
|
||||
@@ -497,6 +525,10 @@ class Upload
|
||||
throw new Exception('Animated WebP is not supported', 400);
|
||||
}
|
||||
|
||||
if ($this->mediaType === 'video') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings::get('arachnid')) {
|
||||
$arachnid = new Arachnid(
|
||||
authorization: Settings::get('arachnid_key'),
|
||||
@@ -594,11 +626,29 @@ class Upload
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function isValidMime(string $mime): bool
|
||||
{
|
||||
if (str_starts_with($mime, 'video/')) {
|
||||
return $this->isValidVideoMime($mime);
|
||||
}
|
||||
|
||||
return $this->isValidImageMime($mime);
|
||||
}
|
||||
|
||||
protected function isValidImageMime(string $mime): bool
|
||||
{
|
||||
if (str_starts_with($mime, 'video/')) {
|
||||
return $this->isValidVideoMime($mime);
|
||||
}
|
||||
|
||||
return preg_match("#image\/(gif|pjpeg|jpeg|png|x-png|bmp|x-ms-bmp|x-windows-bmp|webp)$#", $mime) === 1;
|
||||
}
|
||||
|
||||
protected function isValidVideoMime(string $mime): bool
|
||||
{
|
||||
return preg_match("#video\/(mp4|webm)$#", $mime) === 1;
|
||||
}
|
||||
|
||||
protected function isValidNamingOption(string $string): bool
|
||||
{
|
||||
return in_array($string, ['mixed', 'random', 'original']);
|
||||
|
||||
@@ -189,7 +189,7 @@ class User
|
||||
|
||||
public static function getStreamName(string $username): string
|
||||
{
|
||||
return _s("%t by %s", ['%t' => _s('Images'), '%s' => $username]);
|
||||
return _s("%t by %s", ['%t' => _s('Media'), '%s' => $username]);
|
||||
}
|
||||
|
||||
public static function getUrl(array|string $handle)
|
||||
|
||||
@@ -258,7 +258,8 @@ class DB
|
||||
string $clause = 'AND',
|
||||
array $sort = [],
|
||||
int $limit = null,
|
||||
int $fetch_style = PDO::FETCH_ASSOC
|
||||
int $fetch_style = PDO::FETCH_ASSOC,
|
||||
array $valuesOperators = []
|
||||
): mixed {
|
||||
if (!is_array($values) && $values !== 'all') {
|
||||
throw new Exception('Expecting array values, ' . gettype($values) . ' given');
|
||||
@@ -279,7 +280,8 @@ class DB
|
||||
if (is_null($v)) {
|
||||
$query .= '`' . $k . '` IS :' . $k . ' ' . $clause . ' ';
|
||||
} else {
|
||||
$query .= '`' . $k . '`=:' . $k . ' ' . $clause . ' ';
|
||||
$operator = $valuesOperators[$k] ?? '=';
|
||||
$query .= '`' . $k . '`' . $operator . ':' . $k . ' ' . $clause . ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use CurlHandle;
|
||||
use DateInterval;
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
use FFMpeg\FFProbe;
|
||||
use GdImage;
|
||||
use LogicException;
|
||||
use function Safe\curl_exec;
|
||||
@@ -1933,6 +1934,8 @@ function mime_to_extension(string $mime): string
|
||||
'image/x-icon' => 'ico',
|
||||
'image/vnd.microsoft.icon' => 'ico',
|
||||
'image/webp' => 'webp',
|
||||
'video/mp4' => 'mp4',
|
||||
'video/webm' => 'webm',
|
||||
][$mime] ?? '';
|
||||
}
|
||||
|
||||
@@ -1947,9 +1950,50 @@ function extension_to_mime(string $ext): string
|
||||
'tiff' => 'image/tiff',
|
||||
'ico' => 'image/vnd.microsoft.icon',
|
||||
'webp' => 'image/webp',
|
||||
'mp4' => 'video/mp4',
|
||||
'webm' => 'video/webm',
|
||||
][$ext] ?? '';
|
||||
}
|
||||
|
||||
function get_video_fileinfo(string $file): array
|
||||
{
|
||||
clearstatcache(true, $file);
|
||||
$ffprobe = FFProbe::create();
|
||||
if (!$ffprobe->isValid($file)) {
|
||||
throw new Exception("Invalid video file provided", 610);
|
||||
}
|
||||
$all = $ffprobe
|
||||
->streams($file)
|
||||
->videos()
|
||||
->first()
|
||||
->all();
|
||||
$codecLong = strtolower($all['codec_long_name'] ?? '');
|
||||
$extension = str_contains($codecLong, 'mpeg-4') ? 'mp4' : 'webm';
|
||||
$filesize = filesize($file);
|
||||
$duration = $all['duration'] ?? null;
|
||||
if ($duration === null) {
|
||||
$format = $ffprobe->format($file)->all();
|
||||
$duration = $format['duration'] ?? null;
|
||||
}
|
||||
|
||||
return [
|
||||
'filename' => basename($file),
|
||||
'name' => basename($file, '.' . $extension),
|
||||
'width' => $all['width'],
|
||||
'height' => $all['height'],
|
||||
'ratio' => $all['width'] / $all['height'],
|
||||
'size' => intval($filesize),
|
||||
'size_formatted' => format_bytes($filesize),
|
||||
'mime' => 'video/' . $extension,
|
||||
'extension' => $extension,
|
||||
'bits' => $all['bits_per_raw_sample'] ?? 0,
|
||||
'channels' => '',
|
||||
'url' => absolute_to_url($file),
|
||||
'md5' => md5_file($file),
|
||||
'duration' => (int) $duration,
|
||||
];
|
||||
}
|
||||
|
||||
function get_image_fileinfo(string $file): array
|
||||
{
|
||||
clearstatcache(true, $file);
|
||||
|
||||
@@ -93,14 +93,16 @@ function theme_file_exists($var)
|
||||
function get_html_tags()
|
||||
{
|
||||
$palette = Handler::var('theme_palette_handle');
|
||||
$font = Handler::var('theme_font');
|
||||
$device = 'device-' . (Handler::cond('mobile_device') ? 'mobile' : 'nonmobile');
|
||||
$nsfwBlur = 'unsafe-blur-' . (getSetting('theme_nsfw_blur') ? 'on' : 'off');
|
||||
$classes = strtr(
|
||||
'%device %palette %nsfwBlur',
|
||||
'%device %palette %nsfwBlur %font',
|
||||
[
|
||||
'%device' => $device,
|
||||
'%palette' => 'palette-' . $palette,
|
||||
'%nsfwBlur' => $nsfwBlur,
|
||||
'%font' => 'font-' . $font,
|
||||
]
|
||||
);
|
||||
if (getSetting('captcha')) {
|
||||
@@ -168,7 +170,7 @@ function get_captcha_invisible_html()
|
||||
.then(function(token) {
|
||||
fetch(recaptchaLocal + "/?action=" + recaptchaAction + "&token="+token).then(function(response) {
|
||||
response.json().then(function(data) {
|
||||
console.log(data);
|
||||
// console.log(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -514,14 +516,18 @@ function get_peafowl_item_list($item, $template, $tools, $tpl = 'image', array $
|
||||
$show_admin_tools = true;
|
||||
}
|
||||
}
|
||||
if (($item['duration_time'] ?? '') === '') {
|
||||
$template['tpl_list_item/item_duration_time'] = null;
|
||||
}
|
||||
$stock_tpl_lower = strtolower($stock_tpl);
|
||||
if (!$show_item_public_tools) {
|
||||
$template['tpl_list_item/item_' . strtolower($stock_tpl) . '_public_tools'] = null;
|
||||
$template['tpl_list_item/item_' . $stock_tpl_lower . '_public_tools'] = null;
|
||||
}
|
||||
if (!$show_item_edit_tools) {
|
||||
$template['tpl_list_item/item_' . strtolower($stock_tpl) . '_edit_tools'] = null;
|
||||
$template['tpl_list_item/item_' . $stock_tpl_lower . '_edit_tools'] = null;
|
||||
}
|
||||
if (!$show_admin_tools) {
|
||||
$template['tpl_list_item/item_' . strtolower($stock_tpl) . '_admin_tools'] = null;
|
||||
$template['tpl_list_item/item_' . $stock_tpl_lower . '_admin_tools'] = null;
|
||||
}
|
||||
foreach ($conditional_replaces as $k => $v) {
|
||||
$template[$k] = $v;
|
||||
@@ -552,7 +558,7 @@ function get_peafowl_item_list($item, $template, $tools, $tpl = 'image', array $
|
||||
$placeholder = $stock_tpl == 'IMAGE' ? 'IMAGE_FLAG' : 'ALBUM_COVER_FLAG';
|
||||
$replacements[$placeholder] = $nsfw ? 'unsafe' : 'safe';
|
||||
}
|
||||
$object = array_filter_array($item, ['id_encoded', 'image', 'medium', 'thumb', 'name', 'title', 'display_url', 'extension', 'filename', 'height', 'how_long_ago', 'size_formatted', 'url', 'path_viewer', 'url_viewer', 'url_short', 'width', 'is_360']);
|
||||
$object = array_filter_array($item, ['id_encoded', 'image', 'medium', 'thumb', 'name', 'title', 'display_url', 'display_title', 'extension', 'filename', 'height', 'how_long_ago', 'size_formatted', 'url', 'path_viewer', 'url_viewer', 'url_frame', 'url_short', 'width', 'is_360', 'type']);
|
||||
if (isset($item['user'])) {
|
||||
$object['user'] = [];
|
||||
foreach (['avatar', 'url', 'username', 'name_short_html'] as $k) {
|
||||
@@ -1034,26 +1040,41 @@ function getThemeLogo(): string
|
||||
}
|
||||
}
|
||||
|
||||
function badgePaid(bool $isPaid = true): string
|
||||
function badgePaid(string $edition): string
|
||||
{
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES'] || $isPaid === false) {
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES']) {
|
||||
return '';
|
||||
}
|
||||
if (in_array($edition, editionCombo()[env()['CHEVERETO_EDITION']])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return sprintf('<span class="badge badge--paid"><i class="fa-solid fa-dollar-sign"></i> %s</span>', _s('Pro'));
|
||||
return sprintf('<span class="badge badge--paid"><i class="fa-solid fa-dollar-sign"></i> %s</span>', $edition);
|
||||
}
|
||||
|
||||
function echoBadgePaid(bool $isPaid = true): void
|
||||
function linkPaid(string $edition): ?string
|
||||
{
|
||||
echo badgePaid($isPaid);
|
||||
}
|
||||
|
||||
function echoInputDisabledPaid(bool $disabled = true): void
|
||||
{
|
||||
if ($disabled === false) {
|
||||
return;
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES']) {
|
||||
return null;
|
||||
}
|
||||
echo ' disabled="disabled" title="' . _s('This is a paid feature') . '"';
|
||||
if (in_array($edition, editionCombo()[env()['CHEVERETO_EDITION']])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return 'https://chevereto.com/pricing';
|
||||
}
|
||||
|
||||
function inputDisabledPaid(string $edition): string
|
||||
{
|
||||
if (in_array($edition, editionCombo()[env()['CHEVERETO_EDITION']])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return ' disabled="disabled" title="'
|
||||
. _s('This is a paid feature (%s edition)', $edition)
|
||||
. '"'
|
||||
. ' rel="tooltip"'
|
||||
. ' data-tiptip="right"';
|
||||
}
|
||||
|
||||
function getIpButtonsArray(array $bannedIp, string $ip): array
|
||||
|
||||
@@ -650,7 +650,7 @@ function get_users_image_url(string $filename): string
|
||||
return get_content_url('images/users/' . $filename);
|
||||
}
|
||||
|
||||
function get_image_fileinfo(string $file): array
|
||||
function get_fileinfo(string $file): array
|
||||
{
|
||||
$extension = get_file_extension($file);
|
||||
$return = [
|
||||
@@ -1330,3 +1330,13 @@ function getLicenseKey(): string
|
||||
|
||||
return $licenseKey;
|
||||
}
|
||||
|
||||
function editionCombo(): array
|
||||
{
|
||||
return [
|
||||
'free' => ['free'],
|
||||
'lite' => ['free', 'lite'],
|
||||
'pro' => ['free', 'lite', 'pro'],
|
||||
'enterprise' => ['free', 'lite', 'pro', 'enterprise'],
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user