ajaxAction = 'union_action'; $this->setTemplateName('union'); $this->isUnionAllowed = false; return true; } /** * Генерация основного контента поля * @param array $data @ref данные * @return string HTML */ public function view(array &$data = []) { if (empty($this->fields)) { $data['no_content'] = true; return ''; } $this->form->_fieldActivate($this->id()); if (! isset($data['name'])) { $data['name'] = $this->form->_inputNameGenerator($this->id); } $data['fields'] = & $this->fields; if (empty($this->title)) { $data['wrapper'] = ['colspan' => 2]; } # порядок вывода полей $priority = []; foreach ($this->fields as $k => &$v) { $priority[$k] = $v['priority']; } unset($v); asort($priority, SORT_NUMERIC); $data['priority'] = $priority; $data['value'] = $this->value(); $data['box'] = $this->box; return $this->render($data); } /** * @param Input $field */ public function fieldAdd($field) { $id = sizeof($this->fields) + 1; $field->setID($id); $field->setUnion($this); $max = 0; foreach ($this->fields as $v) { if ($max < $v['priority']) { $max = $v['priority']; } } $this->fields[$id] = [ 'id' => $id, 'field' => $field, 'priority' => $max + 10, ]; $this->fieldActive = $id; } /** * Вернуть список полей * @return array */ public function fields() { return $this->fields; } /** * Возвращаем название CSS класса блока * @param string $name * @return string */ public function cssClass($name = '') { return $this->form->cssClass('union-' . $this->id() . '-' . $name); } /** * Генерация имени для javascript объекта * @return string */ public function jsObjectName() { return $this->form->jsObjectName('union' . $this->id()); } /** * Формирования ajax урл для вызова функции ajax из javascript * @param string $action название события * @return string */ public function ajaxUrl($action = '') { return $this->form->ajaxUrl() . 'field_action&union_id=' . $this->id() . '&' . $this->ajaxAction . '=' . $action; } /** * Обработка ajax запросов * @return array|bool данные для ajax ответа */ public function ajax() { $id = $this->input->getpost('union_id', TYPE_UINT); if ($id != $this->id()) { return false; } $this->ajaxHandler('field_action', function () { $fieldID = $this->input->getpost('field_id', TYPE_UINT); if ($fieldID && isset($this->fields[$fieldID])) { /** @var Input $field */ $field = $this->fields[$fieldID]['field']; return $field->ajax(); } return []; }); return parent::ajax(); } /** * Установка названия ключа при сохранении данных в БД * @param string $key */ public function activateSavedKey($key = 'data') { $this->savedKey = $key; } /** * Прверка наличия мультиязычных полей внутри группы * @return bool */ public function langForm() { foreach ($this->fields as $v) { /** @var Input $field */ $field = $v['field']; if ($field->lang() !== false) { return true; } } return false; } /** * Формирование значения атрибута name для тегов * @param int $fieldID ID поля * @param string $prefix префикс * @return string */ public function _inputNameGenerator($fieldID, $prefix = '') { if (isset($this->fields[ $fieldID ])) { /** @var Input $field */ $field = $this->fields[ $fieldID ]['field']; if (empty($prefix)) { return $this->form->_inputNameGenerator($this->id()).'['.$field->name().']'; } else { return $prefix.'['.$field->name().']'; } } return ''; } /** * Проверка значения поля проверим значение всех входящих полей * @param array $data ['value' => &$value], 'value' - ссылка на значение поля * @return bool true - значение корректно, false - значение некорректно, пропустить (не сохраняется в БД) */ public function validate($data) { do { $result = $data['value']; unset($result['__empty__']); foreach ($this->fields as $f) { /** @var Input $field */ $field = $f['field']; $name = $field->name(); $clean = $field->clean(); if (! isset($result[$name])) { $result[$name] = $clean == TYPE_BOOL ? 0 : false; } if (! $field->validate(['value' => &$result[$name]])) { unset($result[$name]); } } if (isset($this->onValidate['callable']) && is_callable($this->onValidate['callable'])) { if (! call_user_func($this->onValidate['callable'], ['value' => &$result, 'origin' => &$data], $this)) { break; } } if ($this->isRequired()) { if (empty($result)) { $this->errors->set($this->required['message']); return false; } } $saved = $this->form->_ajaxData($this->id(), []); if (! is_array($saved)) $saved = []; $saved = array_merge($saved, $result); $data['value'] = $saved; return true; } while(false); return false; } /** * Проверка значения или выполнение действий после сохранения прокидываем события для входящих полей * @param bool $isInserted - была добавленна новая запись false - редактирование существующей * @param array $data */ public function validateAfter($isInserted, $data) { foreach ($this->fields as $f) { /** @var Input $field */ $field = $f['field']; $field->validateAfter($isInserted, $data); } } /** * Обработка события удаления записи формой, прокидываем для входящих полей * @param int $recordID ID записи */ public function recordDelete($recordID) { foreach ($this->fields as $f) { /** @var Input $field */ $field = $f['field']; if (method_exists($field, 'recordDelete')) { $field->recordDelete($recordID); } } } /** * Получения объекта активного поля * @return Input|bool */ public function _activeField() { if (! isset($this->fields[$this->fieldActive])) { return false; } return $this->fields[$this->fieldActive]['field']; } /** * Выбор поля по имени или ID * @param string $name имя поля или ID * @return int ID поля */ public function _fieldSelector($name) { if (is_numeric($name) && isset($this->fields[$name])) { return (int)$name; } foreach ($this->fields as $k => $v) { /** @var Input $field */ $field = $v['field']; if ($field->name() == $name) { return $k; } } return false; } /** * Сделать поле активным, выбор поля по имени или ID * @param string $name имя поля или ID * @return \bff\tpl\admin\Form */ public function _fieldActivate($name) { $fieldID = $this->_fieldSelector($name); if ($fieldID) { $this->fieldActive = $fieldID; } return $this->form; } /** * Получения объекта поля по имени или ID * @param string $name имя поля или ID * @return Input|bool */ public function field($name) { $fieldID = $this->_fieldSelector($name); if ($fieldID) { return $this->fields[$fieldID]['field']; } return false; } /** * Чтение или запись параметра для активного поля * @param string $name имя параметра * @param mixed $value значение, если null - чтение * @return \bff\tpl\admin\Form|mixed */ public function param($name, $value = null) { do { if (! isset($this->fields[$this->fieldActive])) { break; } /** @var Input $field */ $field = $this->fields[$this->fieldActive]['field']; if (is_null($value)) { if (method_exists($field, $name)) { return $field->$name(); } } $field->setProperties([$name => $value]); } while (false); return $this->form; } /** * Переместить активное поле относительно поля с именем или ID $name на позицию согласно $offset * @param string $fieldName имя поля или таб/поле * @param int $offset */ public function priorityChange($fieldName, $offset) { do { $fieldID = $this->_fieldSelector($fieldName); if (! isset($this->fields[ $this->fieldActive ])) { break; } if (! isset($this->fields[ $fieldID ])) { break; } $priority = $this->fields[ $fieldID ]['priority']; $this->fields[ $this->fieldActive ]['priority'] = $priority + $offset; $priority = []; foreach ($this->fields as $k => $v) { $priority[$k] = $v['priority']; } asort($priority, SORT_NUMERIC); $counter = 10; foreach ($priority as $k => $v) { if (! isset($this->fields[$k])) { continue; } $this->fields[$k]['priority'] = $counter; $counter += 10; } } while (false); } /** * Объединить вместе с полем (поле разместится в одной TD после указанного поля значение параметра title игнорируется) * @param string $fieldName имя поля * @param array $opt ['newLine' => false] вывести с новой строки */ public function togetherAssign($fieldName, array $opt = []) { do { $active = $this->_activeField(); $target = $this->field($fieldName); if (! $active || ! $target) { break; } $together = $target->together(); if (isset($together['target'])) { $target = $together['target']; } if (! isset($this->fields[ $target->id() ])) { break; } $this->priorityChange($target->id(), -1); if (empty($opt['newLine'])) { $active->stretch(false); $target->stretch(false); } $opt['target'] = $target; $active->setProperties(['together' => $opt]); } while(false); } }