mirror of
https://github.com/avecms/AVE.cms.git
synced 2026-08-01 08:45:44 +00:00
315 lines
9.4 KiB
PHP
315 lines
9.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------------------
|
|
| AVE.cms
|
|
|--------------------------------------------------------------------------------------
|
|
| @package AVE.cms
|
|
| @file adminx/modules/Settings/Constants.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\Settings;
|
|
|
|
defined('BASEPATH') || die('Direct access to this location is not allowed.');
|
|
|
|
use DB;
|
|
use App\Common\SystemTables;
|
|
use App\Frontend\Media\ThumbnailPresetPolicy;
|
|
use App\Helpers\Json;
|
|
|
|
class Constants
|
|
{
|
|
public static function table()
|
|
{
|
|
return SystemTables::table('constants');
|
|
}
|
|
|
|
public static function groups()
|
|
{
|
|
return array(
|
|
'_CONST_URL' => 'Формирование URL',
|
|
'_CONST_THEMES' => 'Оформление',
|
|
'_CONST_FOLDERS' => 'Папки',
|
|
'_CONST_THUMBS' => 'Генерация миниатюр',
|
|
'_CONST_WATERMARKS' => 'Водяные знаки',
|
|
'_CONST_SESSIONS' => 'Session и Cookie',
|
|
'_CONST_DEV' => 'Разработка',
|
|
'_CONST_CACHE' => 'Кеширование',
|
|
'_CONST_COMPRESSION' => 'Компрессия',
|
|
'_CONST_MEMCACHED' => 'Memcached',
|
|
'_CONST_REQUEST' => 'Запросы',
|
|
'_CONST_OTHER' => 'Прочее',
|
|
'custom' => 'Пользовательские',
|
|
);
|
|
}
|
|
|
|
public static function typeLabels()
|
|
{
|
|
return array(
|
|
'string' => 'Строка',
|
|
'bool' => 'Да/нет',
|
|
'int' => 'Целое число',
|
|
'select' => 'Список выбора',
|
|
'path' => 'Путь',
|
|
'tags' => 'Теги',
|
|
);
|
|
}
|
|
|
|
public static function all()
|
|
{
|
|
$rows = DB::query('SELECT * FROM ' . self::table() . ' ORDER BY group_code ASC, sort_order ASC, name ASC')->getAll();
|
|
$typeLabels = self::typeLabels();
|
|
foreach ($rows as $i => $row) {
|
|
$rows[$i]['options_array'] = self::decodeOptions($row['options']);
|
|
$rows[$i]['value_display'] = self::displayValue($row['value'], $row['type'], $row['name']);
|
|
$rows[$i]['type_label'] = isset($typeLabels[$row['type']]) ? $typeLabels[$row['type']] : $row['type'];
|
|
$rows[$i] = array_merge($rows[$i], self::auditStatus($row['name']));
|
|
}
|
|
|
|
$order = self::groupOrder();
|
|
usort($rows, function ($a, $b) use ($order) {
|
|
$ag = isset($order[$a['group_code']]) ? $order[$a['group_code']] : 999;
|
|
$bg = isset($order[$b['group_code']]) ? $order[$b['group_code']] : 999;
|
|
if ($ag !== $bg) return $ag - $bg;
|
|
if ((int) $a['sort_order'] !== (int) $b['sort_order']) return (int) $a['sort_order'] - (int) $b['sort_order'];
|
|
return strcmp($a['name'], $b['name']);
|
|
});
|
|
return $rows;
|
|
}
|
|
|
|
public static function grouped()
|
|
{
|
|
$labels = self::groups();
|
|
$out = array();
|
|
foreach (self::all() as $row) {
|
|
$group = (string) $row['group_code'];
|
|
if (!isset($out[$group])) {
|
|
$out[$group] = array(
|
|
'code' => $group,
|
|
'label' => isset($labels[$group]) ? $labels[$group] : $group,
|
|
'items' => array(),
|
|
);
|
|
}
|
|
|
|
$out[$group]['items'][] = $row;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
public static function one($name)
|
|
{
|
|
$row = DB::query('SELECT * FROM ' . self::table() . ' WHERE name = %s LIMIT 1', (string) $name)->getAssoc();
|
|
if (!$row) {
|
|
return null;
|
|
}
|
|
|
|
$typeLabels = self::typeLabels();
|
|
$row['options_array'] = self::decodeOptions($row['options']);
|
|
$row['type_label'] = isset($typeLabels[$row['type']]) ? $typeLabels[$row['type']] : $row['type'];
|
|
return $row;
|
|
}
|
|
|
|
public static function save(array $input)
|
|
{
|
|
$name = strtoupper(trim((string) (isset($input['name']) ? $input['name'] : '')));
|
|
if (!preg_match('/^[A-Z][A-Z0-9_]*$/', $name)) {
|
|
throw new \InvalidArgumentException('Некорректное имя константы');
|
|
}
|
|
|
|
$type = self::normalizeType(isset($input['type']) ? $input['type'] : 'string');
|
|
$rawValue = isset($input['value']) ? $input['value'] : '';
|
|
if ($name === 'THUMBNAIL_SIZES') {
|
|
$type = 'tags';
|
|
$invalid = ThumbnailPresetPolicy::invalidList($rawValue);
|
|
if ($invalid) {
|
|
throw new \InvalidArgumentException('Некорректные размеры: ' . implode(', ', $invalid));
|
|
}
|
|
|
|
$presets = ThumbnailPresetPolicy::normalizeList($rawValue);
|
|
if (!$presets) {
|
|
throw new \InvalidArgumentException('Добавьте хотя бы один разрешённый размер миниатюр');
|
|
}
|
|
|
|
$rawValue = implode(',', $presets);
|
|
}
|
|
|
|
$value = self::normalizeValue($rawValue, $type);
|
|
$options = self::normalizeOptions(isset($input['options']) ? $input['options'] : '');
|
|
|
|
$data = array(
|
|
'name' => $name,
|
|
'value' => self::storeValue($value, $type),
|
|
'type' => $type,
|
|
'group_code' => trim((string) (isset($input['group_code']) ? $input['group_code'] : 'custom')) ?: 'custom',
|
|
'label' => trim((string) (isset($input['label']) ? $input['label'] : $name)),
|
|
'description' => trim((string) (isset($input['description']) ? $input['description'] : '')),
|
|
'options' => Json::encode($options, JSON_UNESCAPED_UNICODE),
|
|
'is_system' => !empty($input['is_system']) ? 1 : 0,
|
|
'sort_order' => isset($input['sort_order']) ? (int) $input['sort_order'] : 100,
|
|
'updated_at' => date('Y-m-d H:i:s'),
|
|
);
|
|
|
|
DB::query(
|
|
'INSERT INTO ' . self::table() . ' (name, value, type, group_code, label, description, options, is_system, sort_order, updated_at)
|
|
VALUES (%s, %?, %s, %s, %s, %?, %?, %i, %i, %s)
|
|
ON DUPLICATE KEY UPDATE
|
|
value = VALUES(value),
|
|
type = VALUES(type),
|
|
group_code = VALUES(group_code),
|
|
label = VALUES(label),
|
|
description = VALUES(description),
|
|
options = VALUES(options),
|
|
is_system = VALUES(is_system),
|
|
sort_order = VALUES(sort_order),
|
|
updated_at = VALUES(updated_at)',
|
|
$data['name'],
|
|
$data['value'],
|
|
$data['type'],
|
|
$data['group_code'],
|
|
$data['label'],
|
|
$data['description'],
|
|
$data['options'],
|
|
$data['is_system'],
|
|
$data['sort_order'],
|
|
$data['updated_at']
|
|
);
|
|
|
|
return $name;
|
|
}
|
|
|
|
public static function delete($name)
|
|
{
|
|
$row = self::one($name);
|
|
if (!$row) {
|
|
return false;
|
|
}
|
|
|
|
if ((int) $row['is_system'] === 1) {
|
|
throw new \RuntimeException('Системную константу нельзя удалить');
|
|
}
|
|
|
|
DB::Delete(self::table(), 'name = %s', (string) $name);
|
|
return true;
|
|
}
|
|
|
|
protected static function normalizeType($type)
|
|
{
|
|
$type = strtolower((string) $type);
|
|
if ($type === 'integer') return 'int';
|
|
if ($type === 'dropdown') return 'select';
|
|
if ($type === 'folder') return 'path';
|
|
if (!in_array($type, array('bool', 'int', 'string', 'select', 'path', 'tags'), true)) {
|
|
return 'string';
|
|
}
|
|
|
|
return $type;
|
|
}
|
|
|
|
protected static function normalizeValue($value, $type)
|
|
{
|
|
if ($type === 'bool') {
|
|
return in_array((string) $value, array('1', 'true', 'on'), true);
|
|
}
|
|
|
|
if ($type === 'int') {
|
|
return (int) $value;
|
|
}
|
|
|
|
return (string) $value;
|
|
}
|
|
|
|
protected static function storeValue($value, $type)
|
|
{
|
|
if ($type === 'bool') return $value ? '1' : '0';
|
|
return (string) $value;
|
|
}
|
|
|
|
protected static function decodeOptions($json)
|
|
{
|
|
return Json::toArray((string) $json);
|
|
}
|
|
|
|
protected static function normalizeOptions($raw)
|
|
{
|
|
if (is_array($raw)) {
|
|
return array_values(array_map('strval', $raw));
|
|
}
|
|
|
|
$lines = preg_split('/[\\r\\n,]+/', (string) $raw);
|
|
$out = array();
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if ($line !== '') {
|
|
$out[] = $line;
|
|
}
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
protected static function groupOrder()
|
|
{
|
|
$order = array();
|
|
$i = 0;
|
|
foreach (array_keys(self::groups()) as $code) {
|
|
$order[$code] = $i++;
|
|
}
|
|
|
|
return $order;
|
|
}
|
|
|
|
protected static function auditStatus($name)
|
|
{
|
|
$compatibility = array(
|
|
'CACHE_DOC_FILE', 'CACHE_DOC_FULL', 'CACHE_DOC_FULL_ADMIN', 'CACHE_DOC_TPL',
|
|
'MEMORY_LIMIT_PANIC', 'PROFILING', 'REQUEST_BREAK_WORDS', 'REQUEST_ETC',
|
|
'REQUEST_STRIP_TAGS', 'SEND_SQL_ERROR', 'SQL_QUERY_SANITIZE',
|
|
'USE_ENCODE_SERIALIZE', 'USE_GET_FIELDS', 'USE_STATIC_DATA',
|
|
);
|
|
if (in_array((string) $name, $compatibility, true)) {
|
|
return array('usage_status' => 'compatibility', 'usage_label' => 'Совместимость', 'usage_reason' => 'Используется только переходным публичным или legacy-слоем.');
|
|
}
|
|
|
|
return array('usage_status' => 'active', 'usage_label' => 'Используется', 'usage_reason' => 'Есть обращения из текущего framework, Adminx или публичного runtime.');
|
|
}
|
|
|
|
protected static function displayValue($value, $type, $name = '')
|
|
{
|
|
if ((string) $name === 'THUMBNAIL_SIZES') {
|
|
$count = count(ThumbnailPresetPolicy::normalizeList($value));
|
|
return $count . ' ' . self::pluralSizes($count);
|
|
}
|
|
|
|
if ($type === 'bool') {
|
|
return ((string) $value === '1') ? 'Да' : 'Нет';
|
|
}
|
|
|
|
return (string) $value;
|
|
}
|
|
|
|
protected static function pluralSizes($count)
|
|
{
|
|
$mod100 = (int) $count % 100;
|
|
$mod10 = (int) $count % 10;
|
|
if ($mod100 >= 11 && $mod100 <= 14) {
|
|
return 'размеров';
|
|
}
|
|
|
|
if ($mod10 === 1) {
|
|
return 'размер';
|
|
}
|
|
|
|
if ($mod10 >= 2 && $mod10 <= 4) {
|
|
return 'размера';
|
|
}
|
|
|
|
return 'размеров';
|
|
}
|
|
|
|
}
|