Услуги профессионального Битрикс-программиста

Избранные товары


Избранные товары
многие делают их на отложенных товарах в корзине
но моя задача была сделать по-другому, потому что кладем без указания размера (именно избранный товар, а не офферс)
Храним для не авторизованных в сессии FAVORITES, для авторизованных в доп свойстве пользователя UF_FAVORITES типа строка (у меня 2 инфоблока, не могла поэтому сделать привязкой к элементам). При авторизации из сессии перемещаем в свойство

в иконке выводим в атрибуте data-id id товара в шаблонах компонентов

на иконку "сердечко" вешаем обработчик
BX.ready(function(){    
    $(document).on("click", '.icon-heart_active', function() {
        let action;
        if($(this).hasClass('infavor')){
            $(this).removeClass('infavor');
            //удаляем
            action = 'delete';
        }
        else{
            //добавляем
            $(this).addClass('infavor');
            action = 'add';
        }
        let id = $(this).data('id');
        
        var postData = {        
            'sessid': BX.bitrix_sessid(),
            'site_id': BX.message('SITE_ID'),       
            'id': id,
            'action': action
        };
        BX.ajax({
            url: '/ajaxtools/favorites.php',
            method: 'POST',
            data: postData,
            dataType: 'json',
            onsuccess: function(result){
               ShowCountFavorites(result);

            }
        });
        
    });   
});

файл на сервере /ajaxtools/favorites.php
<?define("STOP_STATISTICS", true);
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
global $USER, $APPLICATION, $CACHE_MANAGER;
if (!check_bitrix_sessid() || $_SERVER["REQUEST_METHOD"] != "POST" ){
   return;
}
$arFavorites = [];

if(isset($_REQUEST['action'])){

   if($USER->IsAuthorized()){      
      $dbUsers = CUser::GetList(($by="sort"), ($order="asc"), array("ID" => $USER->GetID()), array("SELECT"=>array("UF_FAVORITES")));      
      if($arUser = $dbUsers->Fetch()){         
         $arFavorites = json_decode($arUser["UF_FAVORITES"]);             

         if(($_REQUEST['action']=='delete')&&(intval($_REQUEST["id"])>0)){

               if(is_array($arFavorites) && in_array($_REQUEST["id"], $arFavorites)){                  
                  $temp = [];
                  foreach ($arFavorites as  $favorId) {
                     if($favorId != $_REQUEST["id"]){
                        $temp[] = $favorId*1;
                        
                     }
                  }
                  $arFavorites = $temp;
                  $user = new CUser;            
               $user->Update($USER->GetID(), array("UF_FAVORITES"=>json_encode($arFavorites)));            
               //$CACHE_MANAGER->ClearByTag("favorites_".$USER->GetID());
               }
         }
         elseif(($_REQUEST['action']=='add')&&(intval($_REQUEST["id"])>0)){
            //add            
            if(empty($arFavorites) && !is_array($arFavorites)){
               $arFavorites = [];
            }
            if(!in_array($_REQUEST["id"], $arFavorites)){
               $arFavorites[] = intval($_REQUEST["id"]);         
               $user = new CUser;            
               $user->Update($USER->GetID(), array("UF_FAVORITES"=>json_encode($arFavorites)));            
               //$CACHE_MANAGER->ClearByTag("favorites_".$USER->GetID());
            }            
         }
      }            
               
   }
   else{
      if(isset($_SESSION['FAVORITES'])){
         $arFavorites = json_decode($_SESSION['FAVORITES']);                        
      }
      else{
         $arFavorites = [];
      }
      
      if(($_REQUEST['action']=='delete')&&(intval($_REQUEST["id"])>0)){      
         if(is_array($arFavorites) && in_array($_REQUEST["id"], $arFavorites)){
               $temp = [];
               foreach ($arFavorites as  $favorId) {
                  if($favorId != $_REQUEST["id"]){
                     $temp[] = $favorId*1;
                     
                  }
               }
               $arFavorites = $temp;
               $_SESSION['FAVORITES'] = json_encode($arFavorites);
               
            }

      }
      elseif(($_REQUEST['action']=='add')&&(intval($_REQUEST["id"])>0)){
         if(empty($arFavorites)&&!is_array($arFavorites)){
            $arFavorites = [];            
         }
         if(!in_array($_REQUEST["id"], $arFavorites)){
            $arFavorites[] = intval($_REQUEST["id"]);   
            $_SESSION['FAVORITES'] = json_encode($arFavorites);
         }

      }                        
   }
}

?>

<?$APPLICATION->RestartBuffer();?>
<?
echo json_encode($arFavorites);
die();
?>


при загрузке помечаем товары избранными
BX.ready(function(){
    var postData = {        
        'sessid': BX.bitrix_sessid(),
        'site_id': BX.message('SITE_ID'),              
        'action': 'getlist'
    };
    
    BX.ajax({
        url: '/ajaxtools/favorites.php',
        method: 'POST',
        data: postData,
        dataType: 'json',
        onsuccess: function(result){            
            ShowCountFavorites(result);
            if(result){
                $('.icon-heart_active').each(function(ind,el){
                    let id = $(el).data('id');
                    if(id && result.includes(id)){
                        $(el).addClass('infavor');
                    }
                });
            }
        }
    });

});
функция которая обновляет количество избранных в шапке
function ShowCountFavorites(items){    
    if(items && items.length>0){
        $('#top-icon-heart').html(items.length);
        $('#top-icon-heart').show();
    }
    else{
        $('#top-icon-heart').html('');   
        $('#top-icon-heart').hide();
    }
}
обработчик при авторизации пользователя в init.php, который из куков переносить в свойство
AddEventHandler("main", "OnAfterUserAuthorize", "MyOnAfterUserAuthorize");
function MyOnAfterUserAuthorize($arUser){    
    if(isset($_SESSION['FAVORITES'])){
        $arFavorites = json_decode($_SESSION['FAVORITES']); 
        if(!empty($arFavorites) && is_array($arFavorites)){
            $dbUsers = CUser::GetList(($by="sort"), ($order="asc"), array("ID" => $arUser['user_fields']["ID"]), array("SELECT"=>array("UF_FAVORITES")));     
            if($arUser1 = $dbUsers->Fetch()){            
                $arFavorites2 = json_decode($arUser1["UF_FAVORITES"]); 
                $arFavorites = array_unique(array_merge($arFavorites2,$arFavorites));               
                $user = new CUser;              
                $user->Update($arUser['user_fields']["ID"], array("UF_FAVORITES"=>json_encode($arFavorites)));    
               
               unset($_SESSION['FAVORITES']);
            }
        }
    }
        
}
компонент, который формирует фильтр из id избранных товаров, его помещаем перед выводом товаров на странице
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
//@var array $arParams
//@var array $arResult 
//global $USER, $APPLICATION;

$arParams["FILTER_NAME"] = trim($arParams["FILTER_NAME"]);
if ($arParams["FILTER_NAME"] === '' || !preg_match("/^[A-Za-z_][A-Za-z01-9_]*$/", $arParams["FILTER_NAME"])){
    $arParams["FILTER_NAME"] = "arrFilter";
}
$arParams['FILTER_NAME'] = $arParams['FILTER_NAME'] ?? 'arrFilter';
global ${$arParams['FILTER_NAME']};
$arrFilter = &${$arParams['FILTER_NAME']};
$arFavorites = array();


if($USER->IsAuthorized()){   
   $dbUsers = CUser::GetList(($by="sort"), ($order="asc"), array("ID" => $USER->GetID()), array("SELECT"=>array("UF_FAVORITES")));      
   if($arUser = $dbUsers->Fetch()){         
      $arFavorites = json_decode($arUser["UF_FAVORITES"]);       
   }
}
else{
   $arFavorites = json_decode($_SESSION['FAVORITES']);   
}
if(count($arFavorites)>0){
   $arrFilter = array("ID" => $arFavorites);
}
else{
   $arrFilter = array("ID" => "-1");
}?>