Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Сохранение объекта древовидного модуля
- public function saveItem($args, $currentPage) {
- // Сначала смотрим, что пытаемся сохранить вообще, и валиден ли урл
- $alias = $args['alias'][count($args['alias'])-1];
- $item_id = $this->master->getItemIdByAlias($alias);
- // Получаем реальные данные
- $item = $this->master->item = $this->master->getOne($item_id);
- if (is_object($item)) $item = $item->fields;
- if (FALSE === $item_id) {
- throw new AF_Exception_404;
- exit;
- }
- // Довольно тупая проверка на то, наши ли это данные
- if (isset($_POST[md5('module')]) && $_POST[md5('module')] === md5($this->master->name)) {
- $post = $_POST;
- $this->master->fireEvent($this->master->name.'BeforeEntrySave', new AF_Event_Context($currentPage, $args));
- // Смотрим поля, которые можно заполнять:
- $defined_fields = $this->master->getOptions('modules.'.$this->master->getPathToModule().'.fields');
- //Если вообще есть поля:
- if (count($defined_fields)>0) {
- // Отсеиваем редактируемые поля
- $editable_fields = array_filter(array_keys($defined_fields),
- function($f) use ($defined_fields) {
- return $defined_fields[$f]['is_editable'];
- });
- // Поля, которые получили:
- foreach ($post as $field=>$value) {
- if (FALSE === array_search($field, $editable_fields)) unset ($post[$field]);
- }
- // Оставляем только те поля, которые изменились
- $post = array_diff_assoc($post, $item);
- if (count($post) === 0) { // ничего не менялось
- throw new AF_Redirect_Exception($this->buildUrlByMethod('editItem', $item_id).'?success=true');
- exit;
- }
- // Заполняем правила валидации
- $rules = array();
- foreach ($editable_fields as $field) {
- // Если нам пришло значения этого поля в $_POST и оно требует валидации
- if (isset($post[$field]) && isset($defined_fields[$field]['validate'])) {
- // Добавляем новое правило валидации
- $rules[$field] = $defined_fields[$field]['validate'];
- }
- }
- // Если пользователь очистил поле "алиас", то сгенерируем новый алиас (по только что введенному названию
- // или, если его нет, по старому)
- if (
- isset($post[$this->master->service_fields['alias_field']]) &&
- $post[$this->master->service_fields['alias_field']]===''
- ) {
- $name = (isset($post[$this->master->service_fields['name_field']])) ?
- $post[$this->master->service_fields['name_field']] : // берем из введенных только что данных
- $item[$this->master->service_fields['name_field']]; // берем из старых данных
- $post[$this->master->service_fields['alias_field']] = $this->master->createAlias($name);
- }
- // Запускаем валидатор c только что заполненными правилами
- $errors = AF_Validator::validate($post, $rules);
- if (count($errors) > 0) { // есть ошибки
- // Отдаем обратно те значения, которые пытались ввести
- $currentPage->raw_data_invalid[$this->master->name] = $post;
- // Отдаем отформатированные сообщения об ошибках
- $error_messages = array();
- foreach($errors as $field=>$rules) {
- foreach ($rules as $rule=>$marker) {
- // Находим шаблон сообщения, в который подставим всякую гадость
- $text = (isset(AF_Validator::$messages[$rule]) ? AF_Validator::$messages[$rule] : AF_Validator::$messages['default_message']);
- // Дополнительные параметры, которые подставляются в шаблон (к примеру, для правила minlength - минимальное значение)
- if (is_array($defined_fields[$field]['validate'])) $additional_params = (array)$defined_fields[$field]['validate'][$rule];
- else $additional_params = array();
- $text_params = array($text, $defined_fields[$field]['comment']);
- $params = array_merge($text_params, $additional_params);
- $error_messages[$field] = call_user_func_array('sprintf', $params);
- }
- }
- $currentPage->error_messages = $error_messages;
- $this->editItem($args, $currentPage);
- }
- else { // Данные прошли валидацию, победа!
- $this->master->item[$this->master->service_fields['key_field']] = $item_id;
- // Теперь смотрим, какие из полей наследуются, и их надо перезаписать у дочерних элементов.
- // Параллельно заполним основной сохраняемый объект и таки сохраним его
- // как в switchItemVisibility, все сделаем через.. анонимную функцию
- // чтобы _отделить алгоритм сохранения от внешних проверок и выполнять это сохранение несколько раз
- $clone = clone $this;
- $updateItemsCharacteristic = function($ids, $field, $new_value) use ($clone) {
- // для оптимизации здесь не используется метод save объекта,
- // а сохранение новых данных идет одним запросом
- // напишем условие для апдейта
- $where_statement = "`".$this->getMaster()->service_fields['key_field']."` IN ('".implode("', '", $ids)."')";
- sql_update($this->getMaster()->getTable(), // делаем банальный апдейт
- array(
- $field, // название поля
- $new_value // новое значение
- ),
- $where_statement
- );
- };
- // Соберем детей этого элемента:
- $children = $this->master->getChildrenIdsRecursive($item_id);
- // берем все определенные поля
- $defined_fields = $this->master->getOptions('modules.'.$this->master->getPathToModule().'.fields');
- // проходим пришедшие значения
- foreach ($post as $field=>$val) {
- $this->master->item[$field] = $val;
- // это поле наследуется?
- if (isset($defined_fields[$field]['inherited'] && $defined_fields[$field]['inherited'] === TRUE) {
- // значит, выставим у всех детей новое значение
- if (count($children)>0) {
- // вот тут-то нам и пригодится та анонимная функция
- call_user_func($updateItemsCharacteristic, $children, $field, $val);
- }
- }
- }
- // Наконец-то сохраняем объект, с которого все заварилось
- $this->master->item->save();
- $this->master->fireEvent($this->master->name.'AfterEntrySave', new AF_Event_Context($currentPage, $args));
- // Кидаем на страницу редактирования
- throw new AF_Redirect_Exception($this->buildUrlByMethod('editItem', $item_id).'?success=true');
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment