Битрикс — Автогенерация символьного кода при импорте инфоблока в XML

Хочу поделиться с вами решением, которое мне подсказала тех-поддержка.

Основная задача состояла в том, чтобы при импорте в инфоблок (в формате ХМЛ) у нас автоматически формировался символьный код. Все что нужно сделать это поменять код файла init.php .
Он находится в » Файлы и папки -> bitrix -> php_interface -> init.php » .

Сначала напишу как ответила тех поддержка, она направила меня на ссылку:
http://dev.1c-bitrix.ru/api_help/iblock/events/onbeforeiblockelementadd.php
там в комментариях говориться о том что нужно просто дописать:

// файл /bitrix/php_interface/init.php 

// регистрируем обработчик, при сохранении инфоблока, заполнаем поле "Символьный код" транслитерацией имени заголовка новости 
AddEventHandler("iblock", "OnBeforeIBlockElementAdd", Array("CymCode", "OnBeforeIBlockElementAddHandler")); 

class CymCode 
{ 

// создаем обработчик события "OnBeforeIBlockElementAdd" 
function OnBeforeIBlockElementAddHandler(&$arFields) 
{ 
   if(strlen($arFields["CODE"])<=0) 
   { 
   $arFields["CODE"] = CymCode::imTranslite($arFields["NAME"])."_".date('dmY'); 
        log_array($arFields); // убрать после отладки 

   return; 
   } 
  } 

// записывает все что передадут в /bitrix/log.txt 
function log_array() { 
   $arArgs = func_get_args(); 
   $sResult = ''; 
   foreach($arArgs as $arArg) { 
   $sResult .= "\n\n".print_r($arArg, true); 
   } 

   if(!defined('LOG_FILENAME')) { 
   define('LOG_FILENAME', $_SERVER['DOCUMENT_ROOT'].'/bitrix/log.txt'); 
   } 
   AddMessage2Log($sResult, 'log_array -> '); 
} 

function imTranslite($str){ 
// транслитерация корректно работает на страницах с любой кодировкой 
// ISO 9-95 
   static $tbl= array(
   'а'=>'a', 'б'=>'b', 'в'=>'v', 'г'=>'g', 'д'=>'d', 'е'=>'e', 'ж'=>'g', 'з'=>'z',
   'и'=>'i', 'й'=>'y', 'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 'о'=>'o', 'п'=>'p',
   'р'=>'r', 'с'=>'s', 'т'=>'t', 'у'=>'u', 'ф'=>'f', 'ы'=>'y', 'э'=>'e', 'А'=>'A',
   'Б'=>'B', 'В'=>'V', 'Г'=>'G', 'Д'=>'D', 'Е'=>'E', 'Ж'=>'G', 'З'=>'Z', 'И'=>'I',
   'Й'=>'Y', 'К'=>'K', 'Л'=>'L', 'М'=>'M', 'Н'=>'N', 'О'=>'O', 'П'=>'P', 'Р'=>'R',
   'С'=>'S', 'Т'=>'T', 'У'=>'U', 'Ф'=>'F', 'Ы'=>'Y', 'Э'=>'E', 'ё'=>"yo", 'х'=>"h",
   'ц'=>"ts", 'ч'=>"ch", 'ш'=>"sh", 'щ'=>"shch", 'ъ'=>"", 'ь'=>"", 'ю'=>"yu", 'я'=>"ya",
   'Ё'=>"YO", 'Х'=>"H", 'Ц'=>"TS", 'Ч'=>"CH", 'Ш'=>"SH", 'Щ'=>"SHCH", 'Ъ'=>"", 'Ь'=>"",
   'Ю'=>"YU", 'Я'=>"YA", ' '=>"_", '№'=>"", '«'=>"<", '»'=>">", '—'=>"-" 
   ); 
    return strtr($str, $tbl); 
 } 
}

но скажу сразу, мне пришлось затереть строчку где написано

log_array($arFields); // убрать после отладки

что не удивительно :)
После этого все заработало. Можно дописать по своему желанию, например мы планируем поменять большие буквы на маленькие то есть:

 'Ю'=>"yu", 'Я'=>"ya",

и т.д.

ПС это корректно работает только при импорте в новый инфоблок а не в текущий!

Проверял только в XML формате, про CSV не знаю.
На всякий случай вот вам полный код файла init.php:

<?

// файл /bitrix/php_interface/init.php 

// регистрируем обработчик, при сохранении инфоблока, заполнаем поле "Символьный код" транслитерацией имени заголовка новости 
AddEventHandler("iblock", "OnBeforeIBlockElementAdd", Array("CymCode", "OnBeforeIBlockElementAddHandler")); 

class CymCode 
{ 

// создаем обработчик события "OnBeforeIBlockElementAdd" 
function OnBeforeIBlockElementAddHandler(&$arFields) 
{ 
   if(strlen($arFields["CODE"])<=0) 
   { 
      $arFields["CODE"] = CymCode::imTranslite($arFields["NAME"])."_".date('dmY'); 


      return; 
   } 
  } 

// записывает все что передадут в /bitrix/log.txt 
function log_array() { 
   $arArgs = func_get_args(); 
   $sResult = ''; 
   foreach($arArgs as $arArg) { 
      $sResult .= "\n\n".print_r($arArg, true); 
   } 

   if(!defined('LOG_FILENAME')) { 
      define('LOG_FILENAME', $_SERVER['DOCUMENT_ROOT'].'/bitrix/log.txt'); 
   } 
   AddMessage2Log($sResult, 'log_array -> '); 
} 

function imTranslite($str){ 
// транслитерация корректно работает на страницах с любой кодировкой 
// ISO 9-95 
   static $tbl= array(
      'а'=>'a', 'б'=>'b', 'в'=>'v', 'г'=>'g', 'д'=>'d', 'е'=>'e', 'ж'=>'g', 'з'=>'z',
      'и'=>'i', 'й'=>'y', 'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 'о'=>'o', 'п'=>'p',
      'р'=>'r', 'с'=>'s', 'т'=>'t', 'у'=>'u', 'ф'=>'f', 'ы'=>'y', 'э'=>'e', 'А'=>'A',
      'Б'=>'B', 'В'=>'V', 'Г'=>'G', 'Д'=>'D', 'Е'=>'E', 'Ж'=>'G', 'З'=>'Z', 'И'=>'I',
      'Й'=>'Y', 'К'=>'K', 'Л'=>'L', 'М'=>'M', 'Н'=>'N', 'О'=>'O', 'П'=>'P', 'Р'=>'R',
      'С'=>'S', 'Т'=>'T', 'У'=>'U', 'Ф'=>'F', 'Ы'=>'Y', 'Э'=>'E', 'ё'=>"yo", 'х'=>"h",
      'ц'=>"ts", 'ч'=>"ch", 'ш'=>"sh", 'щ'=>"shch", 'ъ'=>"", 'ь'=>"", 'ю'=>"yu", 'я'=>"ya",
      'Ё'=>"YO", 'Х'=>"H", 'Ц'=>"TS", 'Ч'=>"CH", 'Ш'=>"SH", 'Щ'=>"SHCH", 'Ъ'=>"", 'Ь'=>"",
      'Ю'=>"YU", 'Я'=>"YA", ' '=>"_", '№'=>"", '«'=>"<", '»'=>">", '—'=>"-" 
   ); 
    return strtr($str, $tbl); 
 } 
}


/*Version 0.3 2011-04-25*/
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "DoIBlockAfterSave");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceUpdate", "DoIBlockAfterSave");

 //Регистрируем обработчик OnBeforeIBlockElementAdd
AddEventHandler("iblock", "OnBeforeIBlockElementAdd",  "Deactivate_Import_Element");

function Deactivate_Import_Element($arFields)
{    
   if (isset($_REQUEST['mode'])  && $_REQUEST['mode']=='import' )  
   {
       $arFields['ACTIVE']='N';
   }
}



function DoIBlockAfterSave($arg1, $arg2 = false)
{
   $ELEMENT_ID = false;
   $IBLOCK_ID = false;
   $OFFERS_IBLOCK_ID = false;
   $OFFERS_PROPERTY_ID = false;
   if (CModule::IncludeModule('currency'))
      $strDefaultCurrency = CCurrency::GetBaseCurrency();
   
   //Check for catalog event
   if(is_array($arg2) && $arg2["PRODUCT_ID"] > 0)
   {
      //Get iblock element
      $rsPriceElement = CIBlockElement::GetList(
         array(),
         array(
            "ID" => $arg2["PRODUCT_ID"],
         ),
         false,
         false,
         array("ID", "IBLOCK_ID")
      );
      if($arPriceElement = $rsPriceElement->Fetch())
      {
         $arCatalog = CCatalog::GetByID($arPriceElement["IBLOCK_ID"]);
         if(is_array($arCatalog))
         {
            //Check if it is offers iblock
            if($arCatalog["OFFERS"] == "Y")
            {
               //Find product element
               $rsElement = CIBlockElement::GetProperty(
                  $arPriceElement["IBLOCK_ID"],
                  $arPriceElement["ID"],
                  "sort",
                  "asc",
                  array("ID" => $arCatalog["SKU_PROPERTY_ID"])
               );
               $arElement = $rsElement->Fetch();
               if($arElement && $arElement["VALUE"] > 0)
               {
                  $ELEMENT_ID = $arElement["VALUE"];
                  $IBLOCK_ID = $arCatalog["PRODUCT_IBLOCK_ID"];
                  $OFFERS_IBLOCK_ID = $arCatalog["IBLOCK_ID"];
                  $OFFERS_PROPERTY_ID = $arCatalog["SKU_PROPERTY_ID"];
               }
            }
            //or iblock which has offers
            elseif($arCatalog["OFFERS_IBLOCK_ID"] > 0)
            {
               $ELEMENT_ID = $arPriceElement["ID"];
               $IBLOCK_ID = $arPriceElement["IBLOCK_ID"];
               $OFFERS_IBLOCK_ID = $arCatalog["OFFERS_IBLOCK_ID"];
               $OFFERS_PROPERTY_ID = $arCatalog["OFFERS_PROPERTY_ID"];
            }
            //or it's regular catalog
            else
            {
               $ELEMENT_ID = $arPriceElement["ID"];
               $IBLOCK_ID = $arPriceElement["IBLOCK_ID"];
               $OFFERS_IBLOCK_ID = false;
               $OFFERS_PROPERTY_ID = false;
            }
         }
      }
   }
   //Check for iblock event
   elseif(is_array($arg1) && $arg1["ID"] > 0 && $arg1["IBLOCK_ID"] > 0)
   {
      //Check if iblock has offers
      $arOffers = CIBlockPriceTools::GetOffersIBlock($arg1["IBLOCK_ID"]);
      if(is_array($arOffers))
      {
         $ELEMENT_ID = $arg1["ID"];
         $IBLOCK_ID = $arg1["IBLOCK_ID"];
         $OFFERS_IBLOCK_ID = $arOffers["OFFERS_IBLOCK_ID"];
         $OFFERS_PROPERTY_ID = $arOffers["OFFERS_PROPERTY_ID"];
      }
   }

   if($ELEMENT_ID)
   {
      static $arPropCache = array();
      if(!array_key_exists($IBLOCK_ID, $arPropCache))
      {
         //Check for MINIMAL_PRICE property
         $rsProperty = CIBlockProperty::GetByID("MINIMUM_PRICE", $IBLOCK_ID);
         $arProperty = $rsProperty->Fetch();
         if($arProperty)
            $arPropCache[$IBLOCK_ID] = $arProperty["ID"];
         else
            $arPropCache[$IBLOCK_ID] = false;
      }

      if($arPropCache[$IBLOCK_ID])
      {
         //Compose elements filter
         if($OFFERS_IBLOCK_ID)
         {
            $rsOffers = CIBlockElement::GetList(
               array(),
               array(
                  "IBLOCK_ID" => $OFFERS_IBLOCK_ID,
                  "PROPERTY_".$OFFERS_PROPERTY_ID => $ELEMENT_ID,
               ),
               false,
               false,
               array("ID")
            );
            while($arOffer = $rsOffers->Fetch())
               $arProductID[] = $arOffer["ID"];
               
            if (!is_array($arProductID))
               $arProductID = array($ELEMENT_ID);
         }
         else
            $arProductID = array($ELEMENT_ID);

         $minPrice = false;
         $maxPrice = false;
         //Get prices
         $rsPrices = CPrice::GetList(
            array(),
            array(
               "PRODUCT_ID" => $arProductID,
            )
         );
         while($arPrice = $rsPrices->Fetch())
         {
            if (CModule::IncludeModule('currency') && $strDefaultCurrency != $arPrice['CURRENCY'])
               $arPrice["PRICE"] = CCurrencyRates::ConvertCurrency($arPrice["PRICE"], $arPrice["CURRENCY"], $strDefaultCurrency);
            
            $PRICE = $arPrice["PRICE"];

            if($minPrice === false || $minPrice > $PRICE)
               $minPrice = $PRICE;

            if($maxPrice === false || $maxPrice < $PRICE)
               $maxPrice = $PRICE;
         }

         //Save found minimal price into property
         if($minPrice !== false)
         {
            CIBlockElement::SetPropertyValuesEx(
               $ELEMENT_ID,
               $IBLOCK_ID,
               array(
                  "MINIMUM_PRICE" => $minPrice,
                  "MAXIMUM_PRICE" => $maxPrice,
               )
            );
         }
      }
   }
}
?>
Если на вашем проекте необходимо выполнить перегенерацию символьных кодов или просто настроить ЧПУ, обращайтесь ко мне за помощью

автор: Dmitriy

Занимаюсь веб-разработкой с 2011 года. Посмотреть некоторые из моих работ, а также узнать чуть больше обо мне, вы можете на forwww.ru.

- Создание сайтов на 1С-Битрикс любой сложности
- Вёрстка макетов Figma, Photoshop, Zeplin
- Поддержка проектов на Битриксе
- Разработка нового функционала для сайта
- Парсинг данных
- Выгрузка \ Загрузка файлов в формате XML, YML, XLS, XLSX, CSV, JSON
- Интеграция по API со сторонними сервисами
и многое другое

E-mail: dmitriyribka@gmail.com

2 комментария

    1. Вы правы) сейчас уже незачем. Данный код применялся лишь однажды для очень специфической задачи, когда не устраивала стандартная функция транслитерации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *