Добро пожаловать на сайт <БагБД>, где вы можете задавать вопросы о программировании и разработке на Битрикс и Битрикс24, и получать быстрые и квалифицированные ответы от профессионалов!

Удаление значений множественного свойства типа ФАЙЛ

00 голосов
5
Проблема в следующем:
у меня есть множественное свойство типа файл - MORE_PHOTO.
В другое множественное свойство PHOTO_SM я копирую картинки из свойства MORE_PHOTO поэлементно, при этом уменьшая их.
Всё формируется, всё работает, но когда я сохраняю изменения через CIBlockElement::SetPropertyValues - набор свойств постоянно множится, удваиваясь.
Я пришел к выводу, что необходимо ПОЛНОСТЬЮ чистить это свойство перед тем, как что-либо туда записывать.
Но вот загвоздка - как это сделать?
Прочитал, что для файлового массива необходимо добавить ["del"]="Y", тогда, вроде как, файл будет удален.
Вот кусок кода. Может быть, кто-нибудь подскажет, как, что и где исправить?
Код
$db_props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $arFields['ID'], "sort", "asc", Array("CODE"=>"PHOTO_SM"));

   while($ar_props = $db_props->Fetch())
   {
   
   if ($ar_props["VALUE"])
      {
     $ar_val = $ar_props["VALUE"];
      $ar_val_id = $ar_props["PROPERTY_VALUE_ID"];
      // формируем путь к файлу картинки путем сложения адреса сайта и внутреннего пути к картинке
      $img_path2 = $_SERVER['DOCUMENT_ROOT'].CFile::GetPath($ar_props["VALUE"]);
   $new_make_file = CFile::MakeFileArray($img_path2);
     $new_make_file["del"]="Y";
     CIBlockElement::SetPropertyValueCode($arFields["ID"], "PHOTO", Array ($ar_val_id => $new_make_file) );
   

      }      
   } 
спросил 15 Ноя, 13 от CeBep (300 баллов)

5 Ответы

00 голосов
Привожу весь текст скрипта.
Назначение его такого. У нас имеется множественное свойство MORE_PHOTO. Скрипт должен сгенерировать привьюшки для всех изображений этого свойства, а затем эти привьюшки записать в свойство PHOTO_SM.
Скрипт удалось заставить заработать, но не без маленького глюка. Первый раз отрабатывает прекрасно. Но вот при повторном сохранении элемента инфоблока в полях PHOTO_SM вылазят пустые поля, причем, количество их в точности совпадает с количеством элементов в MORE_PHOTO.

Кто сможет помочь это исправить - буду благодарен.
Код
<?
function BXIBlockAfterSave($arFields)
{
// Вначале ПОЛНОСТЬЮ очищаем свойство PHOTO_SM
$db_props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $arFields['ID'], "sort", "asc", Array("CODE"=>"PHOTO_SM"));
//print_r ($db_props);die();
   while($ar_props = $db_props->Fetch())
   {

   if ($ar_props["VALUE"])
      {
     $ar_val = $ar_props["VALUE"];
      $ar_val_id = $ar_props["PROPERTY_VALUE_ID"];

      // формируем путь к файлу картинки путем сложения адреса сайта и внутреннего пути к картинке
      $img_path2 = $_SERVER['DOCUMENT_ROOT'].CFile::GetPath($ar_props["VALUE"]);
     $new_make_file = CFile::MakeFileArray($img_path2);
     $new_make_file["del"]="Y";
      CIBlockElement::SetPropertyValueCode($arFields["ID"], "PHOTO_SM", Array ($ar_val_id => Array("VALUE"=>$new_make_file) ) );
      @unlink($new_make_file);

      }      
   }
   


// Стандартный пример - создание изображения для PRIVIEW_PICTURE из DETAIL_PICTURE
if(1==1 || $_POST['MAKE_PREVIEW_PICTURE']=='Y')
    {
        $dbr = CIBlockElement::GetByID($arFields['ID']);
        if(($ar = $dbr->Fetch()) && $ar['DETAIL_PICTURE']>0)
        {
            $img_path = $_SERVER['DOCUMENT_ROOT'].CFile::GetPath($ar['DETAIL_PICTURE']);
            $width = 200;
            $height = 200;
            list($width_orig, $height_orig) = getimagesize($img_path);
            if($width && ($width_orig < $height_orig))
               $width = ($height / $height_orig) * $width_orig;
            else
               $height = ($width / $width_orig) * $height_orig;
            $image_p = imagecreatetruecolor($width, $height);
            $image = imagecreatefromjpeg($img_path);
            imagecopyresized($image_p, $image, 0, 0, 0, 0, 
                             $width, $height, $width_orig, $height_orig);
$tmpnm = mt_rand();
            $new_img_path = tempnam("/tmp", "FOO").$tmpnm.".jpg";

            imagejpeg($image_p, $new_img_path);
            $be = new CIBlockElement();
            $be->Update($arFields['ID'], 
                        Array('PREVIEW_PICTURE' => CFile::MakeFileArray($new_img_path)), 
                        false);
            @unlink($new_img_path);
        }
    }


// Самое интересное - берем элементы из MORE_PHOTO, ресайзим и добавляем в PHOTO_SM
$db_props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $arFields['ID'], "sort", "asc", Array("CODE"=>"MORE_PHOTO"));

$arFils=array();
while($ar_prop1 = $db_props->Fetch())
{
   $ar_prop=$ar_prop1["VALUE"];

    $k=CFile::GetPath($ar_prop);


    $img_path2 = $_SERVER['DOCUMENT_ROOT'].$k;
   $width  = 200;
      $height = 150;
      list($width_orig, $height_orig) = getimagesize($img_path2);

      if ($width_orig > $width || $height_orig > $height)
         {
         if($width && ($width_orig < $height_orig))
            $width = ($height / $height_orig) * $width_orig;
         else
            $height = ($width / $width_orig) * $height_orig;
         $image_p = imagecreatetruecolor($width, $height);
         $image = imagecreatefromjpeg($img_path2);
         imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
$tmpnm = mt_rand();
       $new_img_path = tempnam("/tmp", "FOO").$tmpnm.".jpg";;
         imagejpeg($image_p, $new_img_path);
       $new_make_file = CFile::MakeFileArray($new_img_path);
       echo "New path:".$new_img_path."<br>";
                 
       $arFils=array(
          'VALUE' => $new_make_file);
       CIBlockElement::SetPropertyValues( $arFields['ID'], $arFields["IBLOCK_ID"], $arFils, "PHOTO_SM");
            @unlink($new_img_path);
      }

}
}?>
ответил 30 Дек, 13 от CeBep (300 баллов)
00 голосов
Чистить перед записью ничего не надо. Чтобы не удваивалось, нужно использовать ID записи свойства (PROPERTY_VALUE_ID) в качестве ключа масива для изменения.
Для удаеления ключу VALUE нужно присвоить Array("del" => "Y").
Пример: $arr[$ar_props['PROPERTY_VALUE_ID']] = Array("VALUE" => Array("del" => "Y"));
Таким образом будет удалена запись в множественном свойстве.
Файл нужно удалять отдельно.
CFile::Delete($ar_props['VALUE']),
где props['VALUE'] - идентификатор зарегистрированного в Битрикс файла, это то, что хранится в записи множественного свойства.
ответил 15 Апр, 14 от ufoman (390 баллов)
00 голосов
Спасибо огромное! всё заработало прекрасно!
ответил 08 Авг, 14 от CeBep (300 баллов)
00 голосов
nietzschean Расскажите как в вашем примере вы применили совет
nikki21

У меня точно такая же задача как у nietzschean.
ответил 12 Дек, 14 от Manakus (160 баллов)
00 голосов
Вот полный код написанного скрипта, глюков, подобных описанным, в нём не обнаружил.

В начале я чищу все значения множественного свойства, сразу замечу - я сделал на форме "флажок", и только когда он включен - происходит данный механизм
Код
<?
function BXIBlockAfterSave($arFields)
{

if($_POST['MAKE_SM_PREVIEW_PICTURES']=='Y')
{
    $db_props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $arFields['ID'], "sort", "asc", Array("CODE"=>"PHOTO_SM"));
   while($ar_props = $db_props->Fetch())
   {

   if ($ar_props["VALUE"])
      {
      $ar_val = $ar_props["VALUE"];
      $ar_val_id = $ar_props["PROPERTY_VALUE_ID"];

      $arr[$ar_props['PROPERTY_VALUE_ID']] = Array("VALUE" => Array("del" => "Y"));
      CIBlockElement::SetPropertyValueCode($arFields["ID"], "PHOTO_SM", $arr );
      CFile::Delete($ar_props['VALUE']);
      @unlink($new_make_file);

      }      
   }

То есть, в соответствии с советом, я создаю массив $arr и в нем прописываю поле "del", затем через SetProperyValueCode сохраняю изменения, далее - удаляю файл:
Код
      $arr[$ar_props['PROPERTY_VALUE_ID']] = Array("VALUE" => Array("del" => "Y"));
      CIBlockElement::SetPropertyValueCode($arFields["ID"], "PHOTO_SM", $arr );
      CFile::Delete($ar_props['VALUE']);


На втором этапе - записываю все файлы заново



Код
$db_props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $arFields['ID'], "sort", "asc", Array("CODE"=>"MORE_PHOTO"));

$arFils=array();
while($ar_prop1 = $db_props->Fetch())
{
    $ar_prop=$ar_prop1["VALUE"];

    $k=CFile::GetPath($ar_prop);


    $img_path2 = $_SERVER['DOCUMENT_ROOT'].$k;
    $width  = 200;
      $height = 150;
      list($width_orig, $height_orig) = getimagesize($img_path2);

      if ($width_orig > $width || $height_orig > $height)
         {
         if($width && ($width_orig < $height_orig))
            $width = ($height / $height_orig) * $width_orig;
         else
            $height = ($width / $width_orig) * $height_orig;
         $image_p = imagecreatetruecolor($width, $height);
         $image = imagecreatefromjpeg($img_path2);
         imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
$tmpnm = mt_rand();
         $new_img_path = tempnam("/tmp", "FOO").$tmpnm.".jpg";;
         imagejpeg($image_p, $new_img_path);
         $new_make_file = CFile::MakeFileArray($new_img_path);
                 
         $arFils=array(
            'VALUE' => $new_make_file);
         CIBlockElement::SetPropertyValues( $arFields['ID'], $arFields["IBLOCK_ID"], $arFils, "PHOTO_SM");
            @unlink($new_img_path);
        }
}
}
}?> 
ответил 03 Апр, 15 от CeBep (300 баллов)

Похожие вопросы

0 голосов
6 ответов
0 голосов
1 ответ
0 голосов
2 ответов
0 голосов
1 ответ
спросил 05 Апр, 14 от cRaNk (100 баллов)