Skip to content

Instantly share code, notes, and snippets.

@EscApp2
Last active December 7, 2023 12:46
Show Gist options
  • Save EscApp2/0af0ecf1c274fbd6b20681f1191c46bb to your computer and use it in GitHub Desktop.
Save EscApp2/0af0ecf1c274fbd6b20681f1191c46bb to your computer and use it in GitHub Desktop.
favorite, favorite class for bitrix| favorites v2 на свойстве UF_FAVORITES
<?
define("NO_KEEP_STATISTIC", true); // Не собираем стату по действиям AJAX
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
$action = (string)$_REQUEST['action'];
if($action == "addToFav"){
$id = (int)$_REQUEST['id'];
if($id>0){
nav_favorite::addToFav($id);
}
$return = array();
$favItems = nav_favorite::getFavItems();
$return['count'] = count($favItems);
echo CUtil::PhpToJSObject($return);
die();
}
if($action == "removeFromFav"){
$id = (int)$_REQUEST['id'];
if($id>0){
nav_favorite::removeFromFav($id);
}
$return = array();
$favItems = nav_favorite::getFavItems();
$return['count'] = count($favItems);
echo CUtil::PhpToJSObject($return);
die();
}
<?
class nav_favorite{
const iblock_id = 19;
const cookie = "FAV_ID";
const prefix = "FAV_CUSTOM";
function init(){
//pre($_SESSION[self::prefix][self::cookie]);
//die();
//if(
//!isset($_SESSION[self::prefix][self::cookie]) ||
//!is_array($_SESSION[self::prefix][self::cookie])
//){
global $USER;
global $APPLICATION;
$Cookie_full = false;
//if(!isset($_SESSION[self::prefix][self::cookie])){
$Cookie = $APPLICATION->get_cookie(self::cookie,self::prefix);
$arCookie = unserialize($Cookie);
if(!is_array($arCookie)){
$arCookie = array();
}
if(empty($arCookie)){
$_SESSION[self::prefix][self::cookie] = array();
}else{
$Cookie_full = true;
$_SESSION[self::prefix][self::cookie] = $arCookie;
}
//}
if($USER->IsAuthorized()){
if($Cookie_full){
//pre('cookies_full');
$CookieFavItems = $_SESSION[self::prefix][self::cookie];
//pre($CookieFavItems);
$arFilter = array();
$arFilter['PROPERTY_USER_ID'] = $USER->GetID();
$_SESSION[self::prefix][self::cookie] = self::getFavItemsFromIblock($arFilter);
//pre($_SESSION[self::prefix][self::cookie]);
foreach($CookieFavItems as $ItemId){
self::addToFav($ItemId);
}
$APPLICATION->set_cookie(self::cookie, serialize(array()), false, "/",false, false ,true ,self::prefix);
}else{
$arFilter = array();
$arFilter['PROPERTY_USER_ID'] = $USER->GetID();
$_SESSION[self::prefix][self::cookie] = self::getFavItemsFromIblock($arFilter);
}
}
//}
//pre($_SESSION[self::prefix][self::cookie]);
}
function debug(){
global $APPLICATION;
$Cookie = $APPLICATION->get_cookie(self::cookie,self::prefix);
$ar = array(
"session"=>$_SESSION[self::prefix][self::cookie],
"cookie"=> $Cookie,
"cookie_array"=>unserialize($Cookie),
);
return $ar;
}
function getFavItemsFromIblock($arFilter){
$FavItems = array();
if(CModule::IncludeModule('iblock')){
$arFilter['IBLOCK_ID'] = self::iblock_id;
$res_elem = CIBlockElement::GetList(
array(),
$arFilter,
false,
false,
array("ID","IBLOCK_ID","CODE","NAME","PROPERTY_PRODUCT_ID"));
while($ar_elem = $res_elem->Fetch()){
if(!empty($ar_elem["PROPERTY_PRODUCT_ID_VALUE"])){
$FavItems[] = $ar_elem["PROPERTY_PRODUCT_ID_VALUE"];
}
}
}
return $FavItems;
}
/* get */
function getFavItems(){
return self::getFavItemsFromSession();
}
function getFavItemsFromSession(){
return $_SESSION[self::prefix][self::cookie];
}
/* is */
function isInFav($ItemId){
$FavItems = self::getFavItemsFromSession();
if(in_array($ItemId,$FavItems)){
return true;
}
return false;
}
/* add */
function addToFav($ItemId){
if(empty($ItemId)){
return false;
}
if(self::isInFav($ItemId)){
return true;
}
global $USER;
if($USER->IsAuthorized()){
return self::addToFavIblock($ItemId);
}else{
return self::addToFavCookie($ItemId);
}
}
function addToFavIblock($ItemId){
if(CModule::IncludeModule('iblock')){
$el = new CIBlockElement;
global $USER;
$arFields = array(
"NAME"=>"favorite_".randString(10),
"CODE"=>"favorite_".randString(10),
"IBLOCK_ID"=>self::iblock_id,
"PROPERTY_VALUES" => array(
"USER_ID"=>$USER->GetID(),
"PRODUCT_ID"=>$ItemId,
),
);
$bool = $el->Add($arFields);
if($bool){
$_SESSION[self::prefix][self::cookie][] = $ItemId;
return true;
}else{
return false;
}
}
}
function addToFavCookie($ItemId){
//pre('addToFavCookie');
$FavItems = self::getFavItems();
//pre($FavItems);
$FavItems[] = $ItemId;
self::setFavItemsCookie($FavItems);
return true;
}
function setFavItemsCookie($FavItems){
$cookie = serialize($FavItems);
global $APPLICATION;
$APPLICATION->set_cookie(self::cookie, $cookie, false, "/",false, false ,true ,self::prefix);
$_SESSION[self::prefix][self::cookie] = $FavItems;
return true;
}
/* remove */
function removeFromFav($ItemId){
if(empty($ItemId)){
return false;
}
if(!self::isInFav($ItemId)){
return true;
}
global $USER;
if($USER->IsAuthorized()){
return self::removeFromFavIblock($ItemId);
}else{
return self::removeFromFavCookie($ItemId);
}
}
function removeFromFavCookie($ItemId){
$FavItems = self::getFavItems();
foreach($FavItems as $key=>$item){
if($item == $ItemId){
unset($FavItems[$key]);
}
}
self::setFavItemsCookie($FavItems);
return true;
}
function removeFromFavSession($ItemId){
$FavItems = self::getFavItems();
foreach($FavItems as $key=>$item){
if($item == $ItemId){
unset($FavItems[$key]);
}
}
$_SESSION[self::prefix][self::cookie] = $FavItems;
return true;
}
function removeFromFavIblock($ItemId){
if(CModule::IncludeModule('iblock')){
$el = new CIBlockElement;
global $USER;
$FavItems = array();
if(CModule::IncludeModule('iblock')){
$arFilter = array();
$arFilter['IBLOCK_ID'] = self::iblock_id;
$arFilter['PROPERTY_USER_ID'] = $USER->GetID();
$arFilter['PROPERTY_PRODUCT_ID'] = $ItemId;
$res_elem = CIBlockElement::GetList(
array(),
$arFilter,
false,
false,
array("ID"));
if($ar_elem = $res_elem->Fetch()){
$bool = CIBlockElement::Delete($ar_elem['ID']);
if($bool){
self::removeFromFavSession($ItemId);
return true;
}
}
}
}
return false;
}
}
<?
/*
1)В шаблоны каталога и карточки товаров добавить js_favorite и data-id
2)В коде указать FAVORITES_PAGE и как определить товар в функции setUserUnFavorites
3)В скрипте шаблонов добавить правки к событиям onCatalogSectionChangeOffer (создать) и onCatalogElementChangeOffer(изменить)
4)У пользователя создать UF_FAVORITES
5) В хедере добавить js_favorite_count если нужно показывать количество и вывести count(getFavorites())
*/
AddEventHandler('main', 'OnProlog', 'includeFavorites',99999);
function includeFavorites() {
global $APPLICATION;
$dir = $APPLICATION->GetCurDir();
if(strpos($dir, '/bitrix/admin/') !== false){
return true;
}
if(strpos($dir, '/bitrix/gadgets/') !== false){
return true;
}
if(strpos($dir, '/upload/') !== false){
return true;
}
if(defined('ADMIN_SECTION')){
return true;
}
if(
!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
){
return true;
}
if($_SERVER['REQUEST_METHOD'] != "GET"){
return true;
}
ob_start();
?><script class="includeFavorites" >
(function(window) {
var __favorites = {
init:function(){
let that = this;
that.AJAX_FAVORITES = [];
that.FAVORITES_PAGE = "/wishlist/";
that.__debounce_fn_timer = false;
that.makeGetUserAjaxFavorites(function(){
$(document).ready(function(){
that.render();
$(document).off('click', '.js_favorite');
$(document).on('click', '.js_favorite', function(){
that.makeUserFavoritesAction($(this).attr('data-id'));
});
});
});
return that;
},
isItemInFavorites: function (product_id){
let elements = this.getUserFavorites();
if(jQuery.inArray(parseInt(product_id), elements) !== -1){
return true;
}
return false;
},
setUserFavorites: function (product_id){
product_id = parseInt(product_id);
if(!!product_id){
this.AJAX_FAVORITES.push(product_id);
window.FAVORITES.render(product_id);
this.makeSaveUserAjaxFavorites();
}
},
setUserUnFavorites: function (product_id){
let that = this;
product_id = parseInt(product_id);
if(!!product_id){
var toRemove = [product_id];
this.AJAX_FAVORITES = this.AJAX_FAVORITES.filter(function(el){
return toRemove.indexOf( el ) < 0;
});
window.FAVORITES.render(product_id);
if(window.location.pathname == that.FAVORITES_PAGE){
$('.js_favorite[data-id='+product_id+']').closest('[data-entity="item"]').fadeOut();
}
this.makeSaveUserAjaxFavorites();
}
},
makeUserFavoritesAction:function (product_id){
let that = this;
if(that.isItemInFavorites(product_id)){
that.setUserUnFavorites(product_id);
}else{
that.setUserFavorites(product_id);
}
},
getUserFavorites: function (){
return this.AJAX_FAVORITES;
},
makeGetUserAjaxFavorites: function (callback){
let that = this;
$.ajax({
url: '/ajax/index.php',
type: "post",
dataType: "json",
data: {'module':'favorites',"action": "get_user_favorites"},
cache : false,
}).done(function(json){
that.AJAX_FAVORITES = json;
$(document).ready(function(){
if(!!callback){
callback.apply(that);
}
});
}).fail(function( jqXHR, textStatus, errorThrown){
}).always(function( jqXHR, textStatus, errorThrown){
});
},
debounce: function(callback, waitTimeMS) {
let that = this;
return function(...args){
clearTimeout(that.__debounce_fn_timer);
that.__debounce_fn_timer = setTimeout(() => {
callback(...args);
}, waitTimeMS);
};
},
makeSetUserAjaxFavorites: function (callback){
let that = window.FAVORITES;
let $a = $.ajax({
url: '/ajax/index.php',
type: "post",
dataType: "json",
data: {'module':'favorites', "action": "set_user_favorites", 'ids':that.AJAX_FAVORITES },
cache : false,
}).done(function(json){
//that.AJAX_FAVORITES = json;
var count = window.FAVORITES.AJAX_FAVORITES.length
$('.js_favorite_count').html(count);
$(document).ready(function(){
if(!!callback){
callback.apply(that);
}
});
}).fail(function( jqXHR, textStatus, errorThrown){
}).always(function( jqXHR, textStatus, errorThrown){
});
},
makeSaveUserAjaxFavorites: function (){
let that = this;
that.debounce(that.makeSetUserAjaxFavorites ,500).call(that);
},
render: function(product){
let that = this;
let selector = ".js_favorite";
if(!!product){
selector = ".js_favorite[data-id='"+product+"']";
}
$(selector).each(function(){
let product_id = $(this).attr('data-id');
if(!!product_id){
if(that.isItemInFavorites(product_id)){
$(this).addClass('active');
}else{
$(this).removeClass('active');
}
}
})
}
}
if(!window.FAVORITES){
window.FAVORITES = __favorites.init();
BX.addCustomEvent('onCatalogSectionChangeOffer', function(eventData, offer, element){
if(!!element){
$('#'+element.visual.ID).find('.js_favorite').attr('data-id',eventData.newId);
setTimeout(function(){
window.FAVORITES.render(eventData.newId);
},10);
}
});
BX.addCustomEvent('onCatalogElementChangeOffer', function(eventData, offer, element){
if(!!element){
$('#'+element.visual.ID).find('.js_favorite').attr('data-id',eventData.newId);
setTimeout(function(){
window.FAVORITES.render(eventData.newId);
},10);
}
});
}
})(window);
</script><?
$HTML = ob_get_contents();
ob_end_clean();
\Bitrix\Main\Page\Asset::getInstance()->addString(
$HTML,
true,
\Bitrix\Main\Page\AssetLocation::AFTER_JS,
null
);
/*
changeInfo: function()
{
var index = -1,
j = 0,
boolOneSearch = true,
------add---------
eventData = {
currentId: (this.offerNum > -1 ? this.offers[this.offerNum].ID : 0),
newId: 0
};
------add end---------
.....
this.offerNum = index;
------add---------
eventData.newId = this.offers[this.offerNum].ID;
// only for compatible catalog.store.amount custom templates
BX.onCustomEvent('onCatalogStoreProductChange', [this.offers[this.offerNum].ID]);
// new event
BX.onCustomEvent('onCatalogElementChangeOffer', [eventData, this.offers[this.offerNum],this]);
BX.onCustomEvent('onCatalogSectionChangeOffer', [eventData, this.offers[this.offerNum],this]);
eventData = null;
------add end---------
*/
}
AddEventHandler('main', 'OnAjaxPageActionExec', 'favoritesActions');
function favoritesActions($module, $ajax_action, $action, $obRequest, $arRequest){
global $APPLICATION;
if($module == "favorites"){
if($action == "get_user_favorites"){
$favorites = getFavorites('UF_FAVORITES','favorites');
header('Content-Type: application/json');
echo json_encode($favorites);
}elseif($action == "set_user_favorites"){
global $USER;
$IDs = $arRequest['ids'];
if(empty($IDs)){
$IDs = array();
}
if(!$USER->IsAuthorized()) {
$context = Bitrix\Main\Application::getInstance()->getContext();
$cookie = new \Bitrix\Main\Web\Cookie("favorites" , json_encode($IDs), time()+86400*30);
$cookie->setPath("/"); // путь
$context->getResponse()->addCookie($cookie);
}else{
$idUser = $USER->GetID();
$USER->Update($idUser, ["UF_FAVORITES" => $IDs]);
clearActiveFavoritesCache();
}
$addResult = array('STATUS' => 'OK');
header('Content-Type: application/json');
echo json_encode($addResult);
}
}
}
// данные из сессии в бд
AddEventHandler("main", "OnAfterUserAuthorize", "favoriteFromCookiesToDB");
function favoriteFromCookiesToDB($arFields){
$arUser = $arFields['user_fields'];
if($arUser['ID']>0){
global $USER;
$user_id = $arUser['ID'];
$codeUser='UF_FAVORITES';
$codeCookie='favorites';
$favorites_cook = json_decode(Bitrix\Main\Application::getInstance()->getContext()->getRequest()->getCookie($codeCookie),1);
if (!$favorites_cook) $favorites_cook = [];
$rsUser = CUser::GetByID($user_id);
$arUser = $rsUser->Fetch();
$favorites = $arUser[$codeUser];
if (!$favorites) $favorites = [];
$favorites = array_merge($favorites,$favorites_cook);
$favorites = array_unique($favorites);
$USER->Update($user_id, [$codeUser => $favorites]);
// удалить куки
$context = Bitrix\Main\Application::getInstance()->getContext();
$cookie = new \Bitrix\Main\Web\Cookie("favorites" , json_encode(array()), time()-86400*30);
$cookie->setPath("/"); // путь
$context->getResponse()->addCookie($cookie);
}
}
if(!function_exists('getFavorites')){
function getFavorites($codeUser='UF_FAVORITES', $codeCookie='favorites',$withOutActiveCheck = false)
{
global $USER;
$favorites = [];
if(!$USER->IsAuthorized()) {
$favorites = json_decode(Bitrix\Main\Application::getInstance()->getContext()->getRequest()->getCookie($codeCookie),1);
} else {
$idUser = $USER->GetID();
$rsUser = CUser::GetByID($idUser);
$arUser = $rsUser->Fetch();
$favorites = $arUser[$codeUser];
}
if (!$favorites) $favorites = [];
if(!$withOutActiveCheck){
$favorites = getActiveFavorites($favorites);
}
$favorites = array_map('intval', $favorites);
return $favorites;
}
}
if(!function_exists('getActiveFavorites')){
function getActiveFavorites($favorites)
{
global $USER;
$user_id = $USER->GetID();
$IBLOCK_ID = MAIN_CATALOG__PRODUCTS;
return wrapPhpCache(
array(
'name'=>'getActiveFavorites',
'tag'=>array(
"user_".$user_id."__active_favorites_".SITE_ID,
$IBLOCK_ID,
),
'time'=>24*3600,
),
function($favorites, $IBLOCK_ID){
if(count($favorites)>0){
$ar_active_favorites = array();
$arOffersId = array();
CModule::IncludeModule('catalog');
CModule::IncludeModule('iblock');
$arProductsIds = array();
$arFavorites = array_combine($favorites,$favorites);
$favWithProducts = $favorites;
$catalogInfo = CCatalogSku::GetInfoByIBlock($IBLOCK_ID);
$SKU_IBLOCK_ID = $catalogInfo['IBLOCK_ID'];
$PRODUCT_IBLOCK_ID = $catalogInfo['PRODUCT_IBLOCK_ID'];
$arOfferToProduct = CCatalogSku::getProductList($favorites);
foreach($arOfferToProduct as $offer_id=>$arData){
$favWithProducts[] = $arData['ID'];
}
$arResult = array();
$res = \Bitrix\Iblock\ElementTable::getList(array(
'select'=>array('ID','ACTIVE', "CATALOG_TYPE"=>'CATALOG.TYPE'),
'filter'=>array('ID'=>$favWithProducts, "IBLOCK_ID"=>array($SKU_IBLOCK_ID,$PRODUCT_IBLOCK_ID)),
'runtime'=>array(
'CATALOG' => array(
'data_type' => 'Bitrix\Catalog\ProductTable',
'reference' => array('=this.ID' => 'ref.ID'),
)
),
'cache' => array(
'ttl' => 24*60*60,
'cache_joins' => true,
)
));
while($ar = $res->fetch()){
if($ar['CATALOG_TYPE'] == \Bitrix\Catalog\ProductTable::TYPE_OFFER){
$arOffers[$ar['ID']] = $ar;
}else{
if($ar['ACTIVE'] == "Y"){
$arProducts[$ar['ID']] = $ar;
}
}
}
// если нет товара, значит он неактивный, значит убираем ТП
foreach($arOfferToProduct as $offer_id=>$arData){
$product_id = $arData['ID'];
if(!$arProducts[$product_id]){
unset($arFavorites[$offer_id]);
}
}
foreach($arFavorites as $offer_or_product_id){
if(!$arOffers[$offer_or_product_id] && !$arProducts[$offer_or_product_id]){
unset($arFavorites[$offer_or_product_id]);
}
}
$favorites = array_values($arFavorites);
}
return $favorites;
},
array($favorites, $IBLOCK_ID)
);
}
}
if(!function_exists('clearActiveFavoritesCache')){
function clearActiveFavoritesCache(){
global $USER;
$user_id = $USER->GetID();
$taggedCache = \Bitrix\Main\Application::getInstance()->getTaggedCache();
$taggedCache->clearByTag("user_".$user_id."__active_favorites_".SITE_ID);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment