DigitalWand / digitalwand.admin_helper

API для сборки кастомных админок в Битриксе
MIT License
156 stars 52 forks source link

Проблема с типом Дата со временем #28

Open 111ypuk opened 8 years ago

111ypuk commented 8 years ago
class CourseAdminInterface extends AdminInterface {
     public function fields() {
        return array(
            'MAIN' => array(             
                'FIELDS' => array(                    
                       "UF_DATE_LESSON" => array(
                        'WIDGET' => new HLIBlockFieldWidget()                       
                    )
                ))
        );
    } 
    public function helpers() {
        return array(
            '\Pam\HLcourse\Course\AdminInterface\CourseListHelper',
            '\Pam\HLcourse\Course\AdminInterface\CourseEditHelper'
        );
    }
}

UF_DATE_LESSON является типом Дата со временем в HighLoad ИБ, множественным и не объязательным. При сохранение нового элемента в сгнерированной админке появляется сообщение Значение поля «UF_DATE_LESSON» не является корректной датой/временем. При этом само поле может быть пустым или заполеным датой из календаря. Я только смог понять что не србатывает CheckFields

niksamokhvalov commented 8 years ago

По хайлоад-блокам лучше к @ASGAlex, он делал интеграцию с ними.

111ypuk commented 8 years ago

Поправил виджет сам. CheckFields для CUserTypeDateTime не может принимать массив, когда множественное значение. Плюс не надо запускать для этого класса modifyValueBeforeSave

  if (is_callable(array($className, 'CheckFields'))) {
            if (!is_array($value)) {
                $arrValue = array($value);
            }
            else {
                $arrValue = $value;
            }

            foreach ($arrValue as $checkValue) {                
                $errors = $className::CheckFields($fieldInfo, $checkValue);
                if (!empty($errors)) {
                    $this->addError($errors);
                    return;
                }
            }
        }

        // use save modifiers
        $field = $entity_data_class::getEntity()->getField($this->getCode());
        if ($fieldInfo['USER_TYPE']['CLASS_NAME'] != 'CUserTypeDateTime') $value = $field->modifyValueBeforeSave($value, $data);
ASGAlex commented 8 years ago

У меня устранение $value = $field->modifyValueBeforeSave($value, $data); не решает проблему: при сохранении множественной даты с полем без значения всё равно выскакивает ошибка. $value и в том и в другом случае будет array(0 => ""), ошибка появится.

111ypuk commented 8 years ago

для этого выше идёт foreach для перебора массива. И ещё, я выставил в настройках HL ИБ семь обязательных полей, так и в function fields() прописал у них 'REQUIRED' => true, но при сохранение ошибка пишится только для трёх полей, и если их заполнить, то ошибок больше не возникает, а если повтроно редактировать элемент, то можно даже стереть информацию в этих полях и сохранить, и ошибок не возникнет. Нет ошибок для Привязка к разделам инф. блоков и привязка к пользователю и список. Правда так же происходит при создании эдемента в маом HL ИБ

111ypuk commented 7 years ago

в итоге немного исправленный метод processEditAction в HLIBlockFieldWidget выглядит у меня так.

 public function processEditAction() {
        /** @var \CAllUserTypeManager $USER_FIELD_MANAGER */
        global $USER_FIELD_MANAGER;
        $iblockId = 'HLBLOCK_' . $this->getHLId();
        //Чтобы не терялись старые данные
        if (!isset($this->data[$this->getCode()]) AND isset($_REQUEST[$this->getCode() . '_old_id'])) {
            $this->data[$this->getCode()] = $_REQUEST[$this->getCode() . '_old_id'];
        }

        //Функция работает для всех полей, так что запускаем её только один раз, результат кешируем.
        static $data = array();
        if (empty($data)) {
            $data = $this->data;
            $USER_FIELD_MANAGER->EditFormAddFields($iblockId, $data);
        }

        $value = $data[$this->getCode()];

        $entity_data_class = AdminBaseHelper::getHLEntity($this->getSettings('MODEL'));

        $oldData = $this->getOldFieldData($entity_data_class);
        $fieldsInfo = $USER_FIELD_MANAGER->getUserFieldsWithReadyData($iblockId, $oldData, LANGUAGE_ID, false, 'ID');
        $fieldInfo = $fieldsInfo[$this->getCode()];

        $className = $fieldInfo['USER_TYPE']['CLASS_NAME'];
        if (is_callable(array($className, 'CheckFields'))) {
            if (!is_array($value)) {
                $arrValue = array($value);
            }
            else {
                $arrValue = $value;
            }

            foreach ($arrValue as $checkValue) {
                $errors = $className::CheckFields($fieldInfo, $checkValue);
                if (!empty($errors)) {
                    $this->addError($errors);
                    return;
                }
            }
        }

        // use save modifiers
        $field = $entity_data_class::getEntity()->getField($this->getCode());
        //hack для множественных значений Дата и Дата со временем
        if ($fieldInfo['USER_TYPE']['CLASS_NAME'] != 'CUserTypeDateTime' && $fieldInfo['USER_TYPE']['CLASS_NAME'] != 'CUserTypeDate') $value = $field->modifyValueBeforeSave($value, $data);

        //Типоспецифичные хаки
        if ($unserialized = unserialize($value)) {
            //Список значений прилетает сериализованным
            $this->data[$this->getCode()] = $unserialized;
        }
        else if ($className == 'CUserTypeFile' AND ! is_array($value)) {
            //Если не сделать intval, то при сохранении с ранее добавленным файлом будет выскакивать ошибка
            $this->data[$this->getCode()] = intval($value);
        }
        else {
            //Все остальные поля - сохраняем как есть.
            $this->data[$this->getCode()] = $value;
        }
    }