<?php
namespace icms\traits\controllers\actions;
use cmsUser;
use cmsCore;
use cmsForm;
use cmsEventsManager;
/**
* Трейт для экшена поля типа контента формы
*
* @property \cmsTemplate $cms_template
* @property \cmsRequest $request
* @property \modelContent $model_content
*
*/
trait formFieldItem {
/**
* Имя формы
* @required
* @var string
*/
protected $form_name = '';
/**
* URL, на который будет редирект после сохранения формы
* @required
* @var string
*/
protected $success_url = '';
/**
* Имя шаблона для вывода формы
* @required
* @var string
*/
protected $tpl_name = '';
/**
* Хуки формы, куда передаётся только объект формы
* @var array
*/
protected $form_hooks = [];
/**
* Хуки формы, куда передаётся объект формы и тип контента
* @var array
*/
protected $form_ctype_hooks = [];
public function run($ctype_id = null, $field_id = null, $is_copy = null) {
if (!$ctype_id) {
return cmsCore::error404();
}
// id типа контента
if (is_numeric($ctype_id)) {
$ctype = $this->model_content->getContentType($ctype_id);
if (!$ctype) {
return cmsCore::error404();
}
$controller_name = 'content';
$this->dispatchEvent('ctype_loaded', [$ctype, 'field']);
} else { // Контроллер
if (!$this->isControllerInstalled($ctype_id)) {
return cmsCore::error404();
}
cmsCore::loadControllerLanguage($ctype_id);
$ctype = [
'title' => string_lang($ctype_id . '_controller'),
'name' => $ctype_id === 'users' ? '{users}' : $ctype_id, // таблица юзеров
'id' => null
];
$this->model_content->setTablePrefix('');
$controller_name = $ctype_id;
}
$do = 'add';
// Если передан
if($field_id){
$field = $this->model_content->localizedOff()->getContentField($ctype['name'], $field_id);
if (!$field) {
return cmsCore::error404();
}
$this->model_content->localizedRestore();
if(!$is_copy){
$do = 'edit';
} else {
// Системные не можем копировать
if ($field['is_system']) {
return cmsCore::error404();
}
$field['title'] .= ' (copy)';
}
} else {
$field = [
'ctype_id' => $ctype['id'],
'is_fixed_type' => null
];
}
$form = $this->getForm($this->form_name, [$do, $ctype['name']]);
// Общий хук
list($form, $ctype, $field) = cmsEventsManager::hook('content_form_field', [$form, $ctype, $field]);
// Применяем хуки
if($this->form_hooks){
$form = cmsEventsManager::hook($this->form_hooks, $form);
}
if($this->form_ctype_hooks){
foreach ($this->form_ctype_hooks as $hook_name) {
list($form, $ctype) = cmsEventsManager::hook(string_replace_keys_values($hook_name, $ctype), [$form, $ctype]);
}
}
// При редактировании скрываем ненужные поля
if($do === 'edit'){
// скроем поле "Системное имя" для фиксированных полей
if ($field['is_fixed']) {
$form->hideField('basic', 'name');
}
// Скроем для системных и фиксированных полей тип поля
if ($field['is_system'] || $field['is_fixed_type']) {
// Для валидации списка меняем на все доступные поля
$form->setFieldProperty('type', 'type', 'generator', function () use($controller_name) {
return cmsForm::getAvailableFormFields(false, $controller_name);
});
$form->hideField('type', 'type');
}
// скроем лишние опции для системных полей
if ($field['is_system']) {
$form->hideField('basic', 'hint');
$form->hideField('visibility', 'options:relation_id');
$form->setFieldProperty('visibility', 'options:visible_depend', 'is_visible', false);
$form->setFieldProperty('visibility', 'options:is_in_item_pos', 'is_visible', false);
$form->hideFieldset('group');
$form->hideFieldset('format');
$form->hideFieldset('values');
$form->hideFieldset('labels');
$form->hideFieldset('wrap');
$form->hideFieldset('edit_access');
}
// скроем лишние опции для виртуальных полей
if ($field['parser']->is_virtual) {
$form->hideField('basic', 'hint');
$form->hideField('visibility', 'options:relation_id');
$form->setFieldProperty('visibility', 'options:visible_depend', 'is_visible', false);
$form->hideFieldset('group');
$form->hideFieldset('format');
$form->hideFieldset('values');
$form->hideFieldset('add_access');
$form->hideFieldset('author_access');
$form->hideFieldset('edit_access');
}
}
if ($this->request->has('submit')) {
// добавляем поля настроек типа поля в общую форму
// чтобы они были обработаны парсером и валидатором
// вместе с остальными полями
$field_type = $this->request->get('type', '');
$field_class = 'field' . string_to_camel('_', $field_type);
if (!class_exists($field_class)) {
return cmsCore::error(ERR_CLASS_NOT_FOUND);
}
$field_object = new $field_class(null, [
'subject_name' => $ctype['name']
]);
$field_options = $field_object->getOptions();
$form->addFieldsetAfter('type', LANG_CP_FIELD_TYPE_OPTS, 'field_settings');
$form->mergeForm($this->makeForm(function ($form) use ($field_options) {
$form->addFieldset(LANG_CP_FIELD_TYPE_OPTS, 'field_settings');
foreach ($field_options as $field_field) {
$field_field->setName("options:{$field_field->name}");
$form->addField('field_settings', $field_field);
}
return $form;
}));
$defaults = ['ctype_id' => $ctype['id']];
if($field['is_fixed_type']){
$defaults['type'] = $field['type'];
}
$_field = array_merge($form->parse($this->request, true), $defaults);
$errors = $form->validate($this, $_field);
if (!$errors) {
if($do === 'edit'){
$this->model_content->updateContentField($ctype['name'], $field_id, $_field);
cmsUser::addSessionMessage(LANG_SUCCESS_MSG, 'success');
} else {
$field_id = $this->model_content->addContentField($ctype['name'], $_field, $field_object->is_virtual);
cmsUser::addSessionMessage(sprintf(LANG_CP_FIELD_CREATED, $_field['title']), 'success');
}
return $this->redirect(string_replace_keys_values($this->success_url, $ctype));
}
if ($errors) {
cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error');
$field = array_merge($field, $_field);
}
}
$form->show_unsave_notice = false;
return $this->cms_template->render($this->tpl_name, [
'do' => $do,
'ctype' => $ctype,
'field' => $field,
'form' => $form,
'errors' => $errors ?? false
]);
}
}