Files
2026-07-30 16:34:14 +03:00

242 lines
8.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/*
|--------------------------------------------------------------------------------------
| AVE.cms
|--------------------------------------------------------------------------------------
| @package AVE.cms
| @file adminx/modules/Media/ImagePresets.php
| @author AVE.cms <support@ave-cms.ru>
| @copyright 2007-2026 (c) AVE.cms
| @link https://ave-cms.ru
| @version 3.3
*/
namespace App\Adminx\Media;
defined('BASEPATH') || die('Direct access to this location is not allowed.');
use App\Common\DatabaseSchema;
use App\Content\ContentTables;
use DB;
/**
* Справочник «видов изображений»: именованные наборы параметров обрезки
* (режим + размер + формат + качество), которые подставляются в редактор
* медиа и привязываются к полям-картинкам рубрик.
*/
class ImagePresets
{
const MAX_SIDE = 2400;
public static function table()
{
return ContentTables::table('media_image_presets');
}
public static function available()
{
try { return DatabaseSchema::tableExists(self::table()); }
catch (\Throwable $e) { return false; }
}
public static function modes()
{
return array(
'cover' => 'Обрезать под размер',
'contain' => 'Вписать целиком',
'fit' => 'Уменьшить (без обрезки)',
'stretch' => 'Растянуть',
);
}
public static function formats()
{
return array(
'original' => 'Как есть',
'jpg' => 'JPG',
'png' => 'PNG',
'webp' => 'WebP',
);
}
public static function all()
{
if (!self::available()) { return array(); }
$rows = DB::query(
'SELECT * FROM ' . self::table() . ' ORDER BY sort_order ASC, title ASC, id ASC'
)->getAll() ?: array();
return array_map(array(__CLASS__, 'format'), $rows);
}
public static function one($id)
{
if (!self::available()) { return null; }
$row = DB::query('SELECT * FROM ' . self::table() . ' WHERE id=%i LIMIT 1', (int) $id)->getAssoc();
return $row ? self::format($row) : null;
}
public static function byCode($code)
{
$code = self::slug($code);
if ($code === '' || !self::available()) { return null; }
$row = DB::query('SELECT * FROM ' . self::table() . ' WHERE code=%s LIMIT 1', $code)->getAssoc();
return $row ? self::format($row) : null;
}
public static function count()
{
if (!self::available()) { return 0; }
return (int) DB::query('SELECT COUNT(*) FROM ' . self::table())->getValue();
}
/**
* Проверить и нормализовать вход. Возвращает [errors, data].
*/
public static function validate(array $input, $id = 0)
{
$errors = array();
$title = trim((string) (isset($input['title']) ? $input['title'] : ''));
if ($title === '') { $errors['title'] = 'Укажите название'; }
$code = self::slug(isset($input['code']) && trim((string) $input['code']) !== '' ? $input['code'] : $title);
if ($code === '') { $errors['code'] = 'Не удалось построить код из названия'; }
$mode = (string) (isset($input['mode']) ? $input['mode'] : 'cover');
if (!array_key_exists($mode, self::modes())) { $errors['mode'] = 'Неизвестный режим'; }
$format = (string) (isset($input['format']) ? $input['format'] : 'original');
if (!array_key_exists($format, self::formats())) { $errors['format'] = 'Неизвестный формат'; }
$width = (int) (isset($input['width']) ? $input['width'] : 0);
$height = (int) (isset($input['height']) ? $input['height'] : 0);
foreach (array('width' => $width, 'height' => $height) as $key => $value) {
if ($value < 0 || $value > self::MAX_SIDE) {
$errors[$key] = 'Размер от 0 до ' . self::MAX_SIDE;
}
}
// «Вписать/растянуть/обрезать» требуют обе стороны, «уменьшить» — хотя бы одну.
if ($mode === 'fit') {
if ($width < 1 && $height < 1) { $errors['width'] = 'Для «уменьшить» задайте ширину или высоту'; }
} elseif ($width < 1 || $height < 1) {
$errors['width'] = 'Задайте ширину и высоту';
}
$quality = (int) (isset($input['quality']) ? $input['quality'] : 82);
if ($quality < 1 || $quality > 100) { $errors['quality'] = 'Качество 1100'; }
if (empty($errors) && self::codeExists($code, (int) $id)) {
$errors['code'] = 'Вид с таким кодом уже есть';
}
return array($errors, array(
'code' => $code,
'title' => mb_substr($title, 0, 190, 'UTF-8'),
'group_label' => mb_substr(trim((string) (isset($input['group_label']) ? $input['group_label'] : '')), 0, 120, 'UTF-8'),
'mode' => $mode,
'width' => $width,
'height' => $height,
'format' => $format,
'quality' => $quality,
'webp_twin' => empty($input['webp_twin']) ? 0 : 1,
'sort_order' => max(0, min(9999, (int) (isset($input['sort_order']) ? $input['sort_order'] : 100))),
));
}
public static function save($id, array $data)
{
$id = (int) $id;
$now = time();
if ($id > 0) {
$data['updated_at'] = $now;
DB::Update(self::table(), $data, 'id=%i', $id);
return $id;
}
$data['created_at'] = $now;
$data['updated_at'] = $now;
DB::Insert(self::table(), $data);
return (int) DB::insertId();
}
public static function delete($id)
{
if (!self::available()) { return false; }
$exists = (int) DB::query('SELECT COUNT(*) FROM ' . self::table() . ' WHERE id=%i', (int) $id)->getValue();
if ($exists < 1) { return false; }
DB::Delete(self::table(), 'id=%i', (int) $id);
return true;
}
/** Опции для выпадающих списков (редактор, настройки поля). */
public static function options()
{
$out = array();
foreach (self::all() as $preset) {
$out[] = array(
'code' => $preset['code'],
'title' => $preset['title'],
'group_label' => $preset['group_label'],
'mode' => $preset['mode'],
'width' => $preset['width'],
'height' => $preset['height'],
'format' => $preset['format'],
'quality' => $preset['quality'],
'webp_twin' => $preset['webp_twin'],
'label' => $preset['label'],
);
}
return $out;
}
protected static function codeExists($code, $exceptId = 0)
{
if (!self::available()) { return false; }
return (bool) DB::query(
'SELECT id FROM ' . self::table() . ' WHERE code=%s AND id!=%i LIMIT 1',
self::slug($code),
(int) $exceptId
)->getValue();
}
protected static function format(array $row)
{
$modes = self::modes();
$width = (int) (isset($row['width']) ? $row['width'] : 0);
$height = (int) (isset($row['height']) ? $row['height'] : 0);
$mode = (string) (isset($row['mode']) ? $row['mode'] : 'cover');
$size = $width && $height ? ($width . '×' . $height) : ($width ? ($width . '×авто') : ($height ? ('авто×' . $height) : 'авто'));
return array(
'id' => (int) $row['id'],
'code' => (string) $row['code'],
'title' => (string) $row['title'],
'group_label' => (string) (isset($row['group_label']) ? $row['group_label'] : ''),
'mode' => $mode,
'mode_label' => isset($modes[$mode]) ? $modes[$mode] : $mode,
'width' => $width,
'height' => $height,
'format' => (string) (isset($row['format']) ? $row['format'] : 'original'),
'quality' => (int) (isset($row['quality']) ? $row['quality'] : 82),
'webp_twin' => (int) (isset($row['webp_twin']) ? $row['webp_twin'] : 1),
'sort_order' => (int) (isset($row['sort_order']) ? $row['sort_order'] : 100),
'label' => $row['title'] . ' · ' . $size,
);
}
protected static function slug($value)
{
$value = mb_strtolower(trim((string) $value), 'UTF-8');
$map = array(
'а'=>'a','б'=>'b','в'=>'v','г'=>'g','д'=>'d','е'=>'e','ё'=>'e','ж'=>'zh','з'=>'z','и'=>'i','й'=>'y',
'к'=>'k','л'=>'l','м'=>'m','н'=>'n','о'=>'o','п'=>'p','р'=>'r','с'=>'s','т'=>'t','у'=>'u','ф'=>'f',
'х'=>'h','ц'=>'c','ч'=>'ch','ш'=>'sh','щ'=>'sch','ъ'=>'','ы'=>'y','ь'=>'','э'=>'e','ю'=>'yu','я'=>'ya',
);
$value = strtr($value, $map);
$value = preg_replace('/[^a-z0-9]+/', '-', $value);
return substr(trim((string) $value, '-'), 0, 64);
}
}