Довести до ума работу метода ConvertFromDB

Рейтинг: 20.6709  
На голосовании
Предложил Пользователь 32566 26.07.2014 01:07:24

Довести до ума работу метода ConvertFromDB

При разработке собственных свойств инфоблока создается метод ConvertFromDB, назначение которого - преобразовывать значения свойства в требуемый разработчику вид.
Создавая сложные свойства разработчики иногда используют дополнительное поле описания значения свойства - "DESCRIPTION", куда сохраняют сопутствующие значению данные в сериализованном виде.
То есть фактически получается, что значение свойства состоит из кортежа {VALUE,DESCRIPTION}.
Проблема в том, что при выборках CIBlockElement::GetList в метод свойства ConvertFromDB не поступает значение поля "DESCRIPTION" (передается почему-то пустая строка). Что не позволяет правильно сформировать полноценное значение свойства.
Проблема находится в файле: /bitrix/modules/iblock/classes/general/iblockresult.php (строка 196).
Нужно заменить вот это:
if(is_array($this->arIBlockConvProps))
{
   foreach($this->arIBlockConvProps as $strFieldName=>$arCallback)
   {
      if(is_array($res[$strFieldName]))
      {

         foreach($res[$strFieldName] as $key=>$value)
         {
            $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$value,"DESCRIPTION"=>"")));
            $res[$strFieldName][$key] = $arValue["VALUE"];
         }
      }
      else
      {
         $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$res[$strFieldName],"DESCRIPTION"=>"")));
         $res[$strFieldName] = $arValue["VALUE"];
      }
   }
}
 
На примерно вот это:
if(is_array($this->arIBlockConvProps))
{
   foreach($this->arIBlockConvProps as $strFieldName=>$arCallback)
   {
      $propID = $arCallback["PROPERTY"]["ID"];
      $propCode = $arCallback["PROPERTY"]["CODE"];
      $desc = $res["DESCRIPTION_".$propID];
      if(empty($desc)) $desc = $res["PROPERTY_".$propID."_DESCRIPTION"];
      if(empty($desc)) $desc = $res["PROPERTY_".$propCode."_DESCRIPTION"];
      
      if(is_array($res[$strFieldName]))
      {

         foreach($res[$strFieldName] as $key=>$value)
         {
            $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$value,"DESCRIPTION"=>$desc[$key])));
            $res[$strFieldName][$key] = $arValue["VALUE"];
         }
      }
      else
      {
         $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$res[$strFieldName],"DESCRIPTION"=>$desc)));
         $res[$strFieldName] = $arValue["VALUE"];
      }
   }
}
То есть передаем в метод ConvertFromDB сопутствующее значению описание DESCRIPTION.

Для чего это всё.

Пример сложного свойства: вставки в ювелирные украшения. Значение представляет собой кортеж {типКамня,каратность,количество}. Тип камня (ID) хранится в поле VALUE, каратность и количество - в DESCRIPTION в сериализованном виде. Данная структура позволяет делать выборки элементов инфоблока по типу камня.
При текущем положении вещей постоянно приходится преобразовывать значения в нужный вид в result_modifier.php.
А если свойство входит в состав какого-то решения из маркетплейса, то разработчик, который использует это решение может только догадываться как преобразовать значения свойства в нормальный вид.

Создан тикет в техподдержку: 512438

Рейтинг: 0.2128  
Пользователь 32566 05.08.2014 22:12:16
Пожелание из техподдержки передали в отдел разработки.
Номер обращения в разработку: 52390
Ждемс.
Рейтинг: 0  
Пользователь 191258 11.08.2014 12:35:04
Удивлен что такая идея появилась только сейчас. Я был уверен, что пользовательские свойства нормально работают с DESCRIPTION. Но нет.

Кстати: Правильнее будет отдавать и новый DESCRIPTION

if(is_array($this->arIBlockConvProps))
{
    foreach($this->arIBlockConvProps as $strFieldName=>$arCallback)
    {
        $propID = $arCallback["PROPERTY"]["ID"];
        $propCode = $arCallback["PROPERTY"]["CODE"];
        $desc = $res["DESCRIPTION_".$propID];
        if(empty($desc)) $desc = $res["PROPERTY_".$propID."_DESCRIPTION"];
        if(empty($desc)) $desc = $res["PROPERTY_".$propCode."_DESCRIPTION"];

        if(is_array($res[$strFieldName]))
        {

            foreach($res[$strFieldName] as $key=>$value)
            {
                $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$value,"DESCRIPTION"=>$desc[$key])));
                $res[$strFieldName][$key] = $arValue["VALUE"];
                if(isset($res["PROPERTY_".$propID."_DESCRIPTION"])){
                    $res["PROPERTY_".$propID."_DESCRIPTION"][$key]=$arValue["DESCRIPTION"];
                }
                if(isset($res["PROPERTY_".$propCode."_DESCRIPTION"])){
                    $res["PROPERTY_".$propCode."_DESCRIPTION"][$key]=$arValue["DESCRIPTION"];
                }
            }
        }
        else
        {
            $arValue = call_user_func_array($arCallback["ConvertFromDB"], array($arCallback["PROPERTY"], array("VALUE"=>$res[$strFieldName],"DESCRIPTION"=>$desc)));
            $res[$strFieldName] = $arValue["VALUE"];
            if(isset($res["PROPERTY_".$propID."_DESCRIPTION"])){
                $res["PROPERTY_".$propID."_DESCRIPTION"]=$arValue["DESCRIPTION"];
            }
            if(isset($res["PROPERTY_".$propCode."_DESCRIPTION"])){
                $res["PROPERTY_".$propCode."_DESCRIPTION"]=$arValue["DESCRIPTION"];
            }
        }
    }
}
Рейтинг: 0  
Пользователь 32566 28.06.2016 22:55:34
Так же надо убрать ограничение для DESCRIPTION в 255 символов.