- Created Articles.php for rendering article views including full articles, miniature lists, and news sections. - Added Banners.php for handling banner displays. - Introduced Languages.php for rendering language options. - Implemented Menu.php for dynamic menu rendering. - Developed Newsletter.php for newsletter view rendering. - Created Scontainers.php for rendering specific containers. - Added ShopCategory.php for category descriptions and product listings. - Introduced ShopClient.php for managing client-related views such as address editing and order history. - Implemented ShopPaymentMethod.php for displaying payment methods in the basket. - Created ShopProduct.php for generating product URLs. - Added ShopSearch.php for rendering a simple search form. - Added .htaccess file to enhance security by restricting access to sensitive files and directories.
495 lines
17 KiB
PHP
495 lines
17 KiB
PHP
<?php
|
|
namespace admin\Support\Forms;
|
|
|
|
use admin\ViewModels\Forms\FormEditViewModel;
|
|
use admin\ViewModels\Forms\FormField;
|
|
use admin\ViewModels\Forms\FormFieldType;
|
|
|
|
/**
|
|
* Renderer pól formularza
|
|
*/
|
|
class FormFieldRenderer
|
|
{
|
|
private FormEditViewModel $form;
|
|
|
|
public function __construct(FormEditViewModel $form)
|
|
{
|
|
$this->form = $form;
|
|
}
|
|
|
|
/**
|
|
* Renderuje pojedyncze pole
|
|
*/
|
|
public function renderField(FormField $field): string
|
|
{
|
|
$method = 'render' . ucfirst($field->type);
|
|
|
|
if (method_exists($this, $method)) {
|
|
return $this->$method($field);
|
|
}
|
|
|
|
// Fallback dla nieznanych typów - renderuj jako text
|
|
return $this->renderText($field);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole tekstowe
|
|
*/
|
|
public function renderText(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
|
|
$params = [
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
];
|
|
|
|
if ($field->placeholder) {
|
|
$params['placeholder'] = $field->placeholder;
|
|
}
|
|
|
|
if ($error) {
|
|
$params['class'] .= ' error';
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole number
|
|
*/
|
|
public function renderNumber(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
|
|
$params = [
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'number',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
];
|
|
|
|
if ($error) {
|
|
$params['class'] .= ' error';
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole email
|
|
*/
|
|
public function renderEmail(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
|
|
$params = [
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'email',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
];
|
|
|
|
if ($error) {
|
|
$params['class'] .= ' error';
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole password
|
|
*/
|
|
public function renderPassword(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
return \Shared\Html\Html::input([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'password',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole daty
|
|
*/
|
|
public function renderDate(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
|
|
$params = [
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'class' => 'date ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
];
|
|
|
|
if ($error) {
|
|
$params['class'] .= ' error';
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole daty i czasu
|
|
*/
|
|
public function renderDatetime(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
return \Shared\Html\Html::input([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'class' => 'datetime ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje przełącznik (switch)
|
|
*/
|
|
public function renderSwitch(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
// Domyślna wartość dla nowego rekordu
|
|
if ($value === null && $field->value === true) {
|
|
$checked = true;
|
|
} else {
|
|
$checked = (bool) $value;
|
|
}
|
|
|
|
return \Shared\Html\Html::input_switch([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'checked' => $checked,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje select
|
|
*/
|
|
public function renderSelect(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
|
|
$params = [
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'values' => $field->options,
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
];
|
|
|
|
if ($error) {
|
|
$params['class'] .= ' error';
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::select($params), $error);
|
|
}
|
|
|
|
/**
|
|
* Renderuje textarea
|
|
*/
|
|
public function renderTextarea(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
return \Shared\Html\Html::textarea([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'rows' => $field->attributes['rows'] ?? 4,
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje edytor (CKEditor)
|
|
*/
|
|
public function renderEditor(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
return \Shared\Html\Html::textarea([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'rows' => max(10, ($field->attributes['rows'] ?? 10)),
|
|
'class' => 'editor ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole obrazu z filemanagerem
|
|
*/
|
|
public function renderImage(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($field->id);
|
|
|
|
return \Shared\Html\Html::input_icon([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'icon_content' => 'przeglądaj',
|
|
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole pliku
|
|
*/
|
|
public function renderFile(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
if ($field->useFilemanager) {
|
|
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($field->id);
|
|
|
|
return \Shared\Html\Html::input_icon([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'icon_content' => 'przeglądaj',
|
|
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
|
|
]);
|
|
}
|
|
|
|
return \Shared\Html\Html::input([
|
|
'label' => $field->label,
|
|
'name' => $field->name,
|
|
'id' => $field->id,
|
|
'type' => 'file',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Renderuje ukryte pole
|
|
*/
|
|
public function renderHidden(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
|
|
return '<input type="hidden" name="' . htmlspecialchars($field->name) . '" ' .
|
|
'id="' . htmlspecialchars($field->id) . '" ' .
|
|
'value="' . htmlspecialchars($value ?? '') . '">';
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole koloru (color picker + text input)
|
|
*/
|
|
public function renderColor(FormField $field): string
|
|
{
|
|
$value = $this->form->getFieldValue($field);
|
|
$error = $this->form->getError($field->name);
|
|
$colorValue = htmlspecialchars($value ?? '#000000', ENT_QUOTES, 'UTF-8');
|
|
$fieldName = htmlspecialchars($field->name, ENT_QUOTES, 'UTF-8');
|
|
$fieldId = htmlspecialchars($field->id, ENT_QUOTES, 'UTF-8');
|
|
$label = htmlspecialchars($field->label, ENT_QUOTES, 'UTF-8');
|
|
|
|
$html = '<div class="form-group row">';
|
|
$html .= '<label class="col-lg-4 control-label">' . $label . ':</label>';
|
|
$html .= '<div class="col-lg-8">';
|
|
$html .= '<div style="display:flex;align-items:center;gap:8px;">';
|
|
$html .= '<input type="color" id="' . $fieldId . '_picker" value="' . $colorValue . '" style="width:40px;height:34px;padding:2px;border:1px solid #ccc;cursor:pointer;" />';
|
|
$html .= '<input type="text" name="' . $fieldName . '" id="' . $fieldId . '" value="' . $colorValue . '" class="form-control" style="max-width:150px;" />';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '<script>$(function(){'
|
|
. 'var $p=$("#' . $fieldId . '_picker"),$t=$("#' . $fieldId . '");'
|
|
. '$p.on("input",function(){$t.val(this.value);});'
|
|
. '$t.on("input",function(){var v=this.value;if(/^#[0-9a-fA-F]{6}$/.test(v))$p.val(v);});'
|
|
. '});</script>';
|
|
|
|
return $this->wrapWithError($html, $error);
|
|
}
|
|
|
|
public function renderCustom(FormField $field): string
|
|
{
|
|
return (string)($field->customHtml ?? '');
|
|
}
|
|
|
|
/**
|
|
* Renderuje sekcję językową
|
|
*/
|
|
public function renderLangSection(FormField $section): string
|
|
{
|
|
if ($section->langFields === null || $this->form->languages === null) {
|
|
return '';
|
|
}
|
|
|
|
$out = '<div id="languages-' . $section->name . '" class="languages-tabs">';
|
|
|
|
// Zakładki języków
|
|
$out .= '<ul class="resp-tabs-list languages-tabs htabs">';
|
|
foreach ($this->form->languages as $lang) {
|
|
if ($lang['status']) {
|
|
$out .= '<li>' . htmlspecialchars($lang['name']) . '</li>';
|
|
}
|
|
}
|
|
$out .= '</ul>';
|
|
|
|
// Kontenery języków
|
|
$out .= '<div class="resp-tabs-container languages-tabs">';
|
|
foreach ($this->form->languages as $lang) {
|
|
if ($lang['status']) {
|
|
$out .= '<div>';
|
|
foreach ($section->langFields as $field) {
|
|
$out .= $this->renderLangField($field, $lang['id'], $section->name);
|
|
}
|
|
$out .= '</div>';
|
|
}
|
|
}
|
|
$out .= '</div>';
|
|
|
|
$out .= '</div>';
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Renderuje pole w sekcji językowej
|
|
*/
|
|
private function renderLangField(FormField $field, $languageId, string $sectionName): string
|
|
{
|
|
$value = $this->form->getFieldValue($field, $languageId, $field->name);
|
|
$error = $this->form->getError($sectionName . '_' . $field->name, $languageId);
|
|
|
|
$name = $field->getLocalizedName($languageId);
|
|
$id = $field->getLocalizedId($languageId);
|
|
|
|
switch ($field->type) {
|
|
case FormFieldType::IMAGE:
|
|
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($id);
|
|
return $this->wrapWithError(\Shared\Html\Html::input_icon([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'value' => $value ?? '',
|
|
'type' => 'text',
|
|
'icon_content' => 'przeglądaj',
|
|
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
|
|
]), $error);
|
|
|
|
case FormFieldType::TEXTAREA:
|
|
case FormFieldType::EDITOR:
|
|
return $this->wrapWithError(\Shared\Html\Html::textarea([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'value' => $value ?? '',
|
|
'rows' => $field->type === FormFieldType::EDITOR ? 10 : ($field->attributes['rows'] ?? 4),
|
|
'class' => $field->type === FormFieldType::EDITOR ? 'editor' : '',
|
|
]), $error);
|
|
|
|
case FormFieldType::SWITCH:
|
|
return \Shared\Html\Html::input_switch([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'checked' => (bool) $value,
|
|
]);
|
|
|
|
case FormFieldType::SELECT:
|
|
return $this->wrapWithError(\Shared\Html\Html::select([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'value' => $value ?? '',
|
|
'values' => $field->options,
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]), $error);
|
|
|
|
default: // TEXT, URL, etc.
|
|
if (!empty($field->attributes['icon_content'])) {
|
|
$iconJs = (string)($field->attributes['icon_js'] ?? '');
|
|
if ($iconJs !== '') {
|
|
$iconJs = str_replace('{lang}', (string)$languageId, $iconJs);
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input_icon([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'value' => $value ?? '',
|
|
'type' => $field->type === FormFieldType::EMAIL ? 'email' : 'text',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
'icon_content' => (string)$field->attributes['icon_content'],
|
|
'icon_class' => (string)($field->attributes['icon_class'] ?? ''),
|
|
'icon_js' => $iconJs,
|
|
]), $error);
|
|
}
|
|
|
|
return $this->wrapWithError(\Shared\Html\Html::input([
|
|
'label' => $field->label,
|
|
'name' => $name,
|
|
'id' => $id,
|
|
'value' => $value ?? '',
|
|
'type' => $field->type === FormFieldType::EMAIL ? 'email' : 'text',
|
|
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
|
|
]), $error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generuje URL do filemanagera
|
|
*/
|
|
private function generateFilemanagerUrl(string $fieldId): string
|
|
{
|
|
$rfmAkey = $_SESSION['rfm_akey'] ?? bin2hex(random_bytes(16));
|
|
$_SESSION['rfm_akey'] = $rfmAkey;
|
|
$_SESSION['rfm_akey_expires'] = time() + 20 * 60;
|
|
$_SESSION['can_use_rfm'] = true;
|
|
|
|
$fieldIdParam = rawurlencode($fieldId);
|
|
$akeyParam = rawurlencode($rfmAkey);
|
|
return "/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id={$fieldIdParam}&akey={$akeyParam}";
|
|
}
|
|
|
|
/**
|
|
* Opakowuje pole w kontener błędu
|
|
*/
|
|
private function wrapWithError(string $html, ?string $error): string
|
|
{
|
|
if ($error) {
|
|
return '<div class="field-with-error">' . $html .
|
|
'<span class="error-message">' . htmlspecialchars($error) . '</span></div>';
|
|
}
|
|
return $html;
|
|
}
|
|
}
|