Битрикс – Автогенерация символьного кода при импорте инфоблока в 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 року займаюся веб-розробкою. Зараз я – PHP Full Stack Developer.
Обговорити ваш проект, а також дізнатися більше про мене ви можете на цьому сайті:
dev.forwww.com

Email: dmitriyribka@gmail.com

2 коментаря

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

Залишити коментар до Dmitriy Скасувати коментар