| @copyright 2007-2026 (c) AVE.cms | @link https://ave-cms.ru | @version 3.3 */ namespace App\Content\Fields; defined('BASEPATH') || die('Direct access to this location is not allowed.'); use App\Frontend\Media\ThumbnailUrl; use App\Common\Lifecycle; /** * Native public field runtime. * * Значения читаются в legacy-формате (пайп/serialize) — renderView типов их * понимает, поэтому вывод не требует миграции данных. */ class PublicFieldRuntime { public static function configure($mode) { } public static function mode() { return 'native'; } /** * Отрендерить значение поля для публичной страницы (режим AVE 'doc'). * Возвращает HTML нативного обработчика поля. */ public static function renderDoc($type, $value, array $fieldRow = array(), $templateId = null) { $type = (string) $type; if (!FieldRegistry::has($type)) { return ''; } $rendering = self::rendering($type, 'document', $value, $fieldRow, $templateId); if ($rendering->cancelled()) { return (string) $rendering->result(); } $value = $rendering->value('value', $value); $fieldRow = $rendering->value('field', $fieldRow); // Паритет с legacy: непустой per-field шаблон (rubric_field_template) с // tpl_field_empty=0 применяется как есть — [tag:parametr:N] заменяется // на N-ю часть значения по разделителю «|». Иначе — дефолтный renderView. $tpl = isset($fieldRow['rubric_field_template']) ? trim((string) $fieldRow['rubric_field_template']) : ''; $tplEmpty = !empty($fieldRow['tpl_field_empty']); if ($tpl !== '' && !$tplEmpty) { return self::rendered($type, 'document', $value, $fieldRow, $templateId, self::applyTemplate($tpl, $value, $fieldRow), 'database_template'); } $fileTemplate = PublicFieldTemplateResolver::render($type, 'doc', $value, $fieldRow, $templateId); if ($fileTemplate !== null) { return self::rendered($type, 'document', $value, $fieldRow, $templateId, $fileTemplate, 'file_template'); } $definition = $fieldRow; $definition['rubric_field_type'] = $type; $ctx = new FieldContext($value, $definition, 'view'); return self::rendered($type, 'document', $value, $fieldRow, $templateId, (string) FieldRegistry::get($type)->renderView($ctx), 'field_type'); } /** Render a field inside a legacy request/teaser template. */ public static function renderRequest($type, $value, array $fieldRow = array(), $templateId = null) { $type = (string) $type; if (!FieldRegistry::has($type)) { return ''; } $rendering = self::rendering($type, 'request', $value, $fieldRow, $templateId); if ($rendering->cancelled()) { return (string) $rendering->result(); } $value = $rendering->value('value', $value); $fieldRow = $rendering->value('field', $fieldRow); $tpl = isset($fieldRow['rubric_field_template_request']) ? trim((string) $fieldRow['rubric_field_template_request']) : ''; $tplEmpty = !empty($fieldRow['tpl_req_empty']); if ($tpl !== '' && !$tplEmpty) { return self::rendered($type, 'request', $value, $fieldRow, $templateId, self::applyTemplate($tpl, $value, $fieldRow), 'database_template'); } $fileTemplate = PublicFieldTemplateResolver::render($type, 'req', $value, $fieldRow, $templateId); if ($fileTemplate !== null) { return self::rendered($type, 'request', $value, $fieldRow, $templateId, $fileTemplate, 'file_template'); } $definition = $fieldRow; $definition['rubric_field_type'] = $type; $ctx = new FieldContext($value, $definition, 'filter'); return self::rendered($type, 'request', $value, $fieldRow, $templateId, self::renderRequestDefault($type, $ctx), 'field_type'); } protected static function rendering($type, $mode, $value, array $fieldRow, $templateId) { return Lifecycle::event('content.field.rendering', 'field', 'rendering', isset($fieldRow['Id']) ? (int) $fieldRow['Id'] : (isset($fieldRow['rubric_field_id']) ? (int) $fieldRow['rubric_field_id'] : 0), array( 'type' => (string) $type, 'mode' => (string) $mode, 'value' => $value, 'field' => $fieldRow, 'template_id' => $templateId, ), null, array(), 'public_field_runtime'); } protected static function rendered($type, $mode, $value, array $fieldRow, $templateId, $output, $renderer) { $event = Lifecycle::event('content.field.rendered', 'field', 'rendered', isset($fieldRow['Id']) ? (int) $fieldRow['Id'] : (isset($fieldRow['rubric_field_id']) ? (int) $fieldRow['rubric_field_id'] : 0), array( 'type' => (string) $type, 'mode' => (string) $mode, 'value' => $value, 'field' => $fieldRow, 'template_id' => $templateId, 'renderer' => (string) $renderer, ), (string) $output, array(), 'public_field_runtime'); return (string) $event->result(); } protected static function renderRequestDefault($type, FieldContext $ctx) { $plugin = FieldRegistry::get($type); $fieldId = $ctx->fieldId(); // Legacy request mode emitted media collections only through an // explicit per-field request template. Generic document galleries // must not be injected into product cards and other request items. if (in_array($type, array('image_multi', 'image_mega'), true)) { return ''; } if ($type === 'image_single') { $image = MediaFieldValue::imageSingle($ctx->value); if ($image['url'] === '') { return ''; } $url = htmlspecialchars($image['url'], ENT_QUOTES, 'UTF-8'); $alt = htmlspecialchars($image['description'], ENT_QUOTES, 'UTF-8'); if ($fieldId === 159) { $webp = htmlspecialchars(preg_replace('/\.[^.\/]+$/', '.webp', $image['url']), ENT_QUOTES, 'UTF-8'); return "\n\t\n\t\""\n"; } $class = $fieldId === 14 ? ' class="--lazy"' : ($fieldId === 142 ? ' class="where_image_img"' : ''); return ''; } $html = (string) $plugin->renderFilter($ctx); if (in_array($type, array('teasers', 'analoque', 'doc_from_rub_all', 'doc_from_rub_check', 'doc_from_rub_multi', 'doc_from_rub_search'), true)) { return str_replace('