templatesPath(bff::adminTheme()); $this->setTemplateDir($templates); $this->recordID = 1; parent::init(); $this->wrapper()->hide(); $this->fieldsTitleSuffix = ':'; } /** * Загрузка данных для формы * @param array $fields массив требуемых полей * @throws \Exception */ public function load(array $fields = []) { bff::log('Error usage ' . __CLASS__ . '::' . __FUNCTION__); } /** * Сохранение данных формы * @param array $data данные для сохранения * @return bool * @throws \Exception */ public function save($data) { if (empty($data)) { return true; } bff::log('Error usage ' . __CLASS__ . '::' . __FUNCTION__); } /** Событие сабмита формы * @param integer $recordID * @param array $post данные для для сабмита, [] - взять из $_POST * @param array $response @ref массив для ajax ответа */ public function recordSubmit($recordID, array $post = [], array &$response = []) { $params = []; foreach ($this->tabs as $v) { $params[ $v['name'] ] = TYPE_ARRAY; } $data = $this->input->postm($params); return $this->submitSave($data); } /** * Сохранение данных при сабмите формы * @param $data * @return array */ protected function submitSave($data) { $response = []; do { # событие onSubmit if (isset($this->_onSubmit['callable']) && is_callable($this->_onSubmit['callable'])) { $result = call_user_func($this->_onSubmit['callable'], $this->recordID, [ 'data' => &$data, 'response' => &$response, ]); if ($result === false) { return []; } if (is_array($result)) { $response = $result; } } $update = []; foreach ($this->fields as $v) { if (! isset($this->tabs[ $v['tab'] ])) { continue; } if (! empty($v['group'])) { continue; } $tab = $this->tabs[ $v['tab'] ]['name']; /** @var Input $field */ $field = $v['field']; $field->validateAfter(false, []); $name = $field->name(); $clean = $field->clean(); if ($clean != TYPE_BOOL && ! isset($data[$tab][$name])) { continue; } $value = $this->input->clean($data[$tab][$name], $field->clean()); if (! $field->validate(['value' => &$value, 'update' => &$update])) { continue; } $update[$v['id']] = $value; } if (! empty($update) && $this->errors->no()) { foreach ($update as $k => $v) { $this->configUpdate($k, $v); } } } while (false); # событие onSubmitAfter if (isset($this->_onSubmitAfter['callable']) && is_callable($this->_onSubmitAfter['callable'])) { call_user_func($this->_onSubmitAfter['callable'], $this->recordID, [ 'data' => & $data, 'response' => & $response, ]); } $this->ajaxResponseForm($response); } /** * Построение формы * @param array $data доп. данные шаблона * @return string HTML */ public function view(array & $data = []) { $this->ajax(); if ($this->buttonsDefault()) { $this->buttonSubmit(); } $html = $this->content([ 'form' => true, 'settingsForm' => true, ]); $this->ajaxInitResponse($html); return $html; } /** * Событие удаления записи * @param integer $recordID */ public function recordDelete($recordID) { bff::log('Error usage ' . __CLASS__ . '::' . __FUNCTION__); } /** * Формирование имени для сохранения настроек * @param integer $fieldID ID поля * @return string */ public function configName($fieldID) { if ($this->onConfigName instanceof Closure) { return ($this->onConfigName)($fieldID); } if (isset($this->sysAdmin[$fieldID])) { return $this->sysAdmin[$fieldID]; } do { if (! isset($this->fields[$fieldID])) { break; } $f = $this->fields[$fieldID]; if (! isset($this->tabs[ $f['tab'] ])) { break; } $name = []; $name[] = $this->getControllerName(); $name[] = $this->getControllerAction(); $tab = $this->tabs[ $f['tab'] ]; if (! $tab['hidden']) { $name[] = $this->id(); $name[] = $tab['name']; } /** @var Input $field */ $field = $f['field']; $name[] = $field->name(); return join('.', $name); } while (false); return ''; } /** * Сохранение данных в конфиг * @param integer $fieldID ID поля * @param mixed $save данные * @param boolean $dynamic динамическая настройка */ public function configUpdate($fieldID, $save, $dynamic = false) { if ($this->onConfigUpdate instanceof Closure) { return ($this->onConfigUpdate)($fieldID, $save, $dynamic); } if (is_array($save)) { $save = json_encode($save, JSON_UNESCAPED_UNICODE); } $name = $this->configName($fieldID); if (empty($name)) { bff::log('Wrong config name ' . __CLASS__ . '::' . __FUNCTION__); return; } config::save($name, $save); } /** * Формирование значения атрибута name для тегов * @param integer $fieldID ID поля * @param string $prefix префикс * @return string */ public function _inputNameGenerator($fieldID, $prefix = '') { $name = ''; do { if (! isset($this->fields[ $fieldID ])) { break; } /** @var Input $field */ $field = $this->fields[ $fieldID ]['field']; if (empty($prefix)) { $tab = $this->fields[ $fieldID ]['tab']; if (! isset($this->tabs[ $tab ])) { break; } $name = $this->tabs[$tab]['name'] . '[' . $field->name() . ']'; } else { $name = $prefix . '[' . $field->name() . ']'; } } while (false); return $name; } /** * Получение сохраненных данных из конфига * @param integer $fieldID ID поля * @param mixed $default значение по умолчанию * @param mixed $opts * @return mixed */ public function config($fieldID, $default = '', $opts = []) { if ($this->onConfig instanceof Closure) { return ($this->onConfig)($fieldID, $default, $opts); } $name = $this->configName($fieldID); if (empty($name)) { bff::log('Wrong config name ' . __CLASS__ . '::' . __FUNCTION__); return $default; } $data = parent::config($name, $default, $opts); $field = $this->field($fieldID); $clean = $field->clean(); if (($clean == TYPE_ARRAY || $clean >= TYPE_ARRAY_BOOL) && is_string($data)) { $data = json_decode($data, true); } return $data; } /** * Получение значения поля из данных * @param integer $fieldID ID поля * @param mixed $default значение по умолчанию * @return mixed */ public function _fieldData($fieldID, $default = '') { $data = $this->config($fieldID, $default); return $data; } /** * Получение данных в ajax запросах * @param integer $fieldID ID поля * @param mixed $default значение по умолчанию * @param bool $reset сбросить кеш * @return mixed */ public function _ajaxData($fieldID, $default = '', $reset = false) { return $this->config($fieldID, $default); } /** * Сохранение данных в ajax запросах * @param integer $fieldID ID поля * @param mixed $value заначение * @throws \Exception */ public function _ajaxSave($fieldID, $value) { $this->configUpdate($fieldID, $value); } /** * Добавление поля типа FIELD_IMAGES * @param string $name имя * @param string $title заголовок * @param integer $limit максимальное количество изображений * @param integer $maxSize максимальный размер одного файла в байтах * @param array $sizes массив с размерами * @param array $opts опции ['folderByID' => false] раскладывать по папкам * @return Form|\bff\extend\extension\settings\Form|static */ public function images($name, $title = '', $limit = 100, $maxSize = 4194304, array $sizes = [], array $opts = []) { if ($maxSize <= 100) { $maxSize = $maxSize * 1048576; } $this->includeJS(['qquploader', 'ui.sortable'], true); if (! isset($opts['folderByID'])) { $opts['folderByID'] = false; } $params = array_merge([ 'title' => $title, 'limit' => $limit, 'maxSize' => $maxSize, 'clean' => TYPE_ARRAY, ], $opts); if (! empty($sizes)) { $params['sizes'] = $sizes; } $f = new Images($name, $params); $this->fieldAdd($f); return $this; } /** * Добавление поля типа FIELD_FILES * @param string $name имя * @param string $title заголовок * @param integer $limit максимальное количество файлов * @param integer $maxSize максимальный размер одного файла в байтах * @param bool $public публичное хранение @see $publicStore \bff\tpl\admin\FormFiles * @param string $extensions список разрешенных расширений, через ',' * @param array $opts опции ['folderByID' => false] раскладывать по папкам * @return Form|\bff\extend\extension\settings\Form|static */ public function files( $name, $title = '', $limit = 100, $maxSize = 10485760, $public = true, $extensions = '', array $opts = [] ) { $this->includeJS(['qquploader', 'ui.sortable'], true); if (! isset($opts['folderByID'])) { $opts['folderByID'] = false; } $params = array_merge([ 'title' => $title, 'limit' => $limit, 'maxSize' => $maxSize, 'publicStore' => $public, 'clean' => TYPE_ARRAY, 'extensions' => $extensions, ], $opts); $f = new Files($name, $params); $this->fieldAdd($f); return $this; } /** * Добавление группы полей * @param string $name имя * @param string $titlePlus текст ссылки с добавлением элемента группы +add * @param string $title заголовок * @param array $opts опции ['plus'] * 'plus'=>['position', 'type'] - атрибуты ссылки +add * 'position' => 'before', 'after' * 'type' => 'href', 'button' * @return Form */ public function group($name, $titlePlus = '', $title = '', array $opts = []) { $opts['title'] = $title; $opts['clean'] = TYPE_ARRAY; if ($titlePlus) { $opts['plus']['title'] = $titlePlus; } $f = new Group($name, $opts); $this->fieldAdd($f); $this->unionActive = $this->fieldActive; return $this; } /** * Добавление поля типа FIELD_DYNPROPS не возможно для settings\Form * @param Dynprops $dp * @param string $ownerName * @param string $dpKey * @param array $opts * @return Form */ public function dynprops(Dynprops $dp, $ownerName, $dpKey = 'd', array $opts = []) { return $this; } /** * Добавление предзагруженных данных (изображения, файлы, наборы групповых полей) * @param mixed $data * @return Form */ public function preload($data) { do { if (empty($data)) { break; } $field = $this->_activeField(false); if (method_exists($field, 'preload')) { $field->preload($data); } } while (false); return $this; } /** * Сохранение (дублирование для расширений) поля в системную настройку $name, при сохранении формы * @param string $name название системной настройки * @return Form */ public function sysAdmin(string $name) { do { if (empty($name)) { break; } if (! isset($this->fields[$this->fieldActive])) { break; } $this->sysAdmin[$this->fieldActive] = $name; } while (false); return $this; } /** * Установка обработчика события получения всех системных настроек и их значений * @param callable $callable * @return $this */ public function onSettingsSystemData(callable $callable) { $this->onSettingsSystemData = $callable; return $this; } /** * Получение всех системных настроек и их значений */ public function settingsSystemData() { $result = []; foreach ($this->fields as $v) { $result[$this->configName($v['id'])] = $this->config($v['id']); } if ($this->onSettingsSystemData instanceof Closure) { $data = ($this->onSettingsSystemData)(); if (! empty($data) && is_array($data)) { $result = array_merge($result, $data); } } return $result; } }