
MyFavorites 
MyFavorites – компонент, который позволяет добавить на сайт списки избранного. Основной упор сделан на работу с анонимными пользователями, аналитикой и защитой от ботов
Основные возможности компонента 
- Создание различных списков избранного.
 - Работа как с анонимными пользователями, так и только с зарегистрированными.
 - Пользовательские списки избранного (пользователь может сам создавать/переименовывать и удалять свои списки).
 - Очистка сессий сайта и удаление кук пользователем не влияют на список избранного у анонимных пользователей.
 - Идентификация анонимного пользователя и, как следствие, его списка избранного, посетившего сайт с разных браузеров (метод не срабатывает во всех 100% случаев. На сайте должна быть подключена Google Analytics или Яндекс.Метрика).
 - Привязка списка избранного анонимного пользователя к зарегистрированному пользователю при его авторизации или создании заказа на сайте.
 - Синхронизация избранного на разных устройствах/браузерах, если ранее не было определено, что они принадлежат одному и тому же пользователю.
 - Передача данных о событиях добавления/удаления и очистки списка избранного в Google Analytics и Яндекс.Метрика.
 - Черные списки IP.
 - Защита от CSRF-атаки.
 - Защита с помощью reCAPTCHA 3.
 - Лимит на запросы для анонимных и зарегистрированных пользователей.
 - Уведомление на Email о подозрительной активности пользователя.
 - Доступ в админке сайта к информации о пользователях, их списках избранного и активности.
 - Экспорт информации о пользователях и избранном в CSV, XLSX и ODS.
 - Корректная работа с Cloudflare.
 - Быстрая кастомизация стилей через CSS переменные.
 - Возможность подписываться на JS события компонента для кастомизации его работы.
 - Нативный js.
 
Видео-обзор 
Быстрый старт 
Вызов сниппетов 
Для возможности добавления/удаления в список избранного используйте сниппет MyFavorites.btn.
Для вывода количества ресурсов в списке избранного используйте сниппет *MyFavorites.counter.
Для получения всех ID ресурсов, находящихся в списке избранного, используйте сниппет MyFavorites.ids.
Для вывода ресурсов, находящихся в списке избранного, добавьте следующий код:
[[!MyFavorites.ids? &toPlaceholder=`myf.ids`]]
[[!+myf.ids:is=`-0`:then=`
  [[%myfavorites_info_list_empty]]
`:else=`
  [[!pdoPage?
    &element=`msProducts`
    &parents=`0`
    &limit=`12`
    &resources=`[[!+myf.ids]]`
  ]]
  <button class="btn btn-primary" data-myfavorites-clear>[[%myfavorites_clear_list]]</button>
  [[!+page.nav]]
`]]Подробную информацию по всем параметрам каждого сниппета смотрите в разделе "Сниппеты".
Стилизация 
Чтобы изменить цветовую гамму, укажите значения для следующих CSS переменных:
--myf-primary-color--myf-secondary-color
Пример 
:root {
  --myf-primary-color:red;
  --myf-secondary-color:silver;
}Для более тонкой настройки смотрите названия остальных переменных в разделе "Настройка CSS стилей".
Автоматическая очистка мусора 
Для автоматической очистки лога, истекших блокировок IP и временных файлов экспорта, добавьте в CRON вызов скрипта раз в неделю.
полный_путь/core/components/myfavorites/cron/clear.phpСистемные настройки 
Основные 

Безопасность 
В данном разделе вы можете:
- Запретить анонимным пользователям добавлять в избранное.
 - Включить черный список IP для блокировки запросов с недоверенных адресов.
 - Включить reCAPTCHA 3 для защиты от спама (reCAPTCHA должна быть предварительно настроена в соответствующем разделе).
 - Настроить лимит запросов для анонимных и авторизированных пользователей.
 

reCAPTCHA 3 

Уведомления 
В данном разделе вы можете включить и настроить типы событий, о которых следует уведомлять.

Аналитика 
В данном разделе вы можете включить передачу данных в Google Analytics или Яндекс.Метрика о добавлении, удалении и очистке списка избранного.

Экспорт 
В данном разделе вы можете:
- Задать формат файла экспорта.
 - Включить сохранение файла экспорта на сервере вместо вывода в браузере.
 - Указать путь, где будут сохраняться файлы экспорта.
 - Указать классы экспорта.
 

Админ панель 






Сниппеты 
MyFavorites.btn - Вывод кнопки для добавления/удаления избранного 
Параметры 
| Имя | Описание | 
|---|---|
id | ID товара, для которого нужно вернуть данные. | 
list | Идентификатор списка. По умолчанию: default. | 
tpl | Имя чанка для оформления результата. По умолчанию: tpl.MyFavorites.btn. | 
remove | Нужно ли удалять или перезагрузить страницу при удалении из избранного. Если нужна перезагрузка страницы, укажите 1. Если удаление HTML элемента, то укажите префикс его ID, к которому через дефис будет добавлен ID ресурса. | 
label | Метка для аналитики. Текст из этого параметра будет передан в событие Google Analytics или Яндекс.Метрика. | 
classes | CSS классы, которые следует добавить к HTML элементу кнопки. | 
Пример вызова в чанке 
[[!MyFavorites.btn? &id=`[[+id]]`]]Пример вызова в шаблоне 
[[!MyFavorites.btn? &id=`[[*id]]`]]Пример вызова, когда необходимо перезагрузить страницу, может выглядеть так 
[[!MyFavorites.btn? &id=`[[*id]]` &remove=`1`]]Пример вызова, когда необходимо удалить HTML элемент 
<div id="product-item-[[+id]]">
[[!MyFavorites.btn? &id=`[[+id]]` &remove=`product-item`]]
.
.
.
</divПример вызова, когда необходимо передать название ресурса в событие аналитики, может выглядеть так 
[[!MyFavorites.btn? &id=`[[+id]]` &label=`[[+pagetitle]]`]]MyFavorites.counter - Вывод счетчика с количеством элементов в избранном 
Параметры 
| Имя | Описание | 
|---|---|
id | ID страницы, на которой выводиться список избранного. | 
list | Идентификатор списка. По умолчанию: default. | 
tpl | Имя чанка для оформления результата. По умолчанию: tpl.MyFavorites.counter | 
Пример вызова 
[[!MyFavorites.counter? &id=`5`]]MyFavorites.lists - Вывод списков избранного с количеством в них элементов 
Параметры 
| Имя | Описание | 
|---|---|
user | ID пользователя Modx. По умолчанию 0. | 
withItems | В чанке доступен массив ID элементов. По умолчанию 1. | 
limit | Лимит выборки результатов. По умолчанию: 0. | 
offset | Пропуск результатов с начала выборки. По умолчанию: 0 | 
sortby | Сортировка выборки. По умолчанию: createdon. | 
sortdir | Направление сортировки. По умолчанию: DESC. | 
tpl | Имя чанка для оформления результата. По умолчанию: tpl.MyFavorites.lists | 
MyFavorites.ids - Возвращает ID элементов списка избранного 
Параметры 
| Имя | Описание | 
|---|---|
list | Идентификатор списка. По умолчанию: default. | 
return | Формат возвращаемых данных. Допустимые значения: data - массив ID; str - строка ID через запятую. По умолчанию: str. | 
toPlaceholder | Если не пусто, сниппет сохранит все данные в плейсхолдер с этим именем, вместо вывода не экран. | 
Пример вывода списка избранных элементов 
[[!MyFavorites.ids? &toPlaceholder=`myf.ids`]]
[[!+myf.ids:is=`-0`:then=`
<div class="alert alert-primary d-flex align-items-center" role="alert">
    <svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img" aria-label="Info:"><use xlink:href="#info-fill"></use></svg>
    <div>[[%myfavorites_info_list_empty]]</div>
</div>
`:else=`
<div class="row">
    [[!pdoPage?
    &element=`msProducts`
    &parents=`0`
    &limit=`12`
    &resources=`[[!+myf.ids]]`
    ]]
</div>
<div class="row">
    <div class="col">
        <button class="btn btn-primary" data-myfavorites-clear>[[%myfavorites_clear_list]]</button>
    </div>
</div>
<div class="row">
    <div class="col text-center">
    [[!+page.nav]]
    </div>
</div>
`]]{set $ids = $_modx->runSnippet('!MyFavorites.ids')}
{if $ids != '-0'}
<div class="row">
    {$_modx->runSnippet('!pdoPage', [
    'element'=>'msProducts',
    'parents' => 0,
    'resources' => $ids,
    'limit' => 12,
    ])}
</div>
<div class="row">
    <div class="col">
        <button class="btn btn-primary" data-myfavorites-clear>{'myfavorites_clear_list' | lexicon}</button>
    </div>
</div>
<div class="row">
    <div class="col text-center">
        {'page.nav' | placeholder}
    </div>
</div>
{else}
<div class="alert alert-primary d-flex align-items-center" role="alert">
    <svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img" aria-label="Info:"><use xlink:href="#info-fill"></use></svg>
    <div>{'myfavorites_info_list_empty' | lexicon}</div>
</div>
{/if}Настройка CSS стилей 
Изменение стилей элементов осуществляется через CSS переменные.
Быстрое изменение цветовой гаммы элементов 
--myf-primary-color--myf-secondary-color
:root {
  --myf-primary-color:red;
  --myf-secondary-color:silver;
}Тонкая настройка 
Кнопка добавления/удаления в избранное 
--myf-btn-size- размер кнопки--myf-btn-icon-color- цвет иконки--myf-btn-added-icon-color- цвет иконки, когда ресурс добавлен в избранное--myf-btn-icon-color-hover- цвет иконки при наведении--myf-btn-icon- svg иконка в base64--myf-btn-added-icon- svg иконка виде base64, когда ресурс добавлен в избранное--myf-btn-animate- анимация при клике для добавления в избранное--myf-btn-transition- transition
Счетчик количества в избранном 
--myf-counter-size- размер кнопки--myf-counter-icon-color- цвет иконки--myf-counter-icon-color-hover- цвет иконки при наведении--myf-counter-icon- svg иконка в base64--myf-counter-transition- transition--myf-counter-value-size- размер для элемента, содержащего значение счетчика--myf-counter-value-offset- смещение элемента относительно иконки--myf-counter-value-bg- цвет фона--myf-counter-value-color- цвет текста--myf-counter-value-opacity- прозрачность--myf-counter-value-opacity-hover- прозрачность при наведении
js 
Общий список событий 
initaddremoveclearListaccessDeniedAntonymsbeforeRequestsuccessRequestfailureRequestafterRequest
Переопределение класса уведомлений 
По умолчанию показ уведомлений происходит через нативный alert, а если установлен MiniShop2, то через его класс сообщений.
Что для того, что бы добавить сою реализацию, необходимо подписаться на событие init компонента и через вызов функции setNotifier передать объект своего класса уведомлений.
Пример 
class MyNotifier {
    success(msg) {
        console.info(msg);
    }
    error(msg) {
        console.error(msg);
    }
}
window.addEventListener('DOMContentLoaded', e => {
    myFavorites.on('init',(self)=>{
        const notifier = new MyNotifier()
        self.setNotifier(notifier);
    });
 });Показ окна регистрации/авторизации для анонимных пользователей 
Если для анонимных пользователей системной настройкой запрещено добавлять в избранное, то по умолчанию им будет показано соответствующее уведомление.
Для того, что бы для такого случая показать свое модальное окно регистрации/авторизации, необходимо подписаться на событие accessDeniedAntonyms, в котором реализовать всю логику.
Пример 
window.addEventListener('DOMContentLoaded', e => {
    myFavorites.on('accessDeniedAntonyms',(self, el, data)=>{
       // showAutModal();
    });
 });Пользовательские списки избранного 
Если в системных настройках пакета разрешены пользовательские списки избранного (по умолчанию запрещены), то Вам самостоятельно необходимо реализовать обработку соответствующих действий пользователя и вызов определенных методов у объекта myFavorites.
Список методов для работы с пользовательскими листами избранного:
- createList - создание листа избранного
 - renameList - переименования листа избранного
 - removeList - удаление листа избранного
 
Пример 
window.addEventListener('DOMContentLoaded', e => {
    document.getElementById('new-list')?.addEventListener('click', ()=>{
        myFavorites.createList('my list', (self, res) => {
        });
    });
   document.getElementById('rename-list')?.addEventListener('click', ()=>{
     myFavorites.renameList('01hv1yjq6drnrn0hk2vmyn1wez', 'new list name', (self, res)=>{
         console.log(res);
     });
  });
   document.getElementById('remove-list')?.addEventListener('click', ()=>{
     myFavorites.removeList('01hv1yjq6drnrn0hk2vmyn1wez', (self, res) => {
         console.log(res);
     });
  });
});Своя передача данных в аналитику 
Если вас не устаивает коробочная реализация и вам нужна своя. То необходимо, во-первых, если была включена опция передачи данных в аналитику отключить ее, а во-вторых реализовать свою.
Для этого необходимо обрабатывать события:
addremoveclearList
Пример 
 window.addEventListener('DOMContentLoaded', e => {
    myFavorites.on('add',(self,el, data, payload) => {
    }).on('remove',(self,el, data, payload) => {
    }).on('clearList',(self,el, data, payload) => {
    });
 });Пример обработки событий запроса 
window.addEventListener('DOMContentLoaded', e => {
    myFavorites.on('beforeRequest',(self, el, payload) => {
    }).on('successRequest',(self, el, res, payload) => {
    }).on('failureRequest',(self, el, res, payload) => {
    }).on('afterRequest',(self, el, payload) => {
    });
 });Настройка экспорта 
В системных настройках дополнения в разделе "Экспорт" можно указать:
- В каком формате должен создаваться файл экспорта. По умолчанию 
xlsx. - Добавить ли названия полей в первой строке файла экспорта. По умолчанию 
Да. - Сохранить результат экспорта в файл или сразу начать скачивать. По умолчанию сразу скачивается.
 - Путь, куда следует сохранять файлы экспорта. Используется если включена опция "Сохранить в файл".
 - Классы экспортов. В данной опции можно добавить свой класс экспорта или переопределить имеющийся.
 
Состояние фильтра и какие поля включены для отображения влияет на то, какие данные и из каких полей попадут в файл экспорта. Порядок следования полей и их ширина так же влияет на то, в какой последовательности и какой шириной они будут в файле экспорта.
Создание своего кастомного экспорта 
Для того, что бы создать свой кастомный экспорт необходимо:
- В директории пакета 
core/components/myfavorites/handlers/exportsсоздать свой класс, унаследовав его от класса MyFavoritesExport, в котором вам нужно реализовать функционал. - В системных настройках пакета в опцию "Классы экспортов" (ключ myfavorites_export_handlers) добавить в нужный топик название своего класса экспорта.
 
После того, как все пункты будут выполнены, созданный вами экспорт появиться в меню экспорта.
Системные события 
MyFavoritesOnManagerCustomCssJs - Загрузка скриптов MyFavorites в админке сайта 
Параметры 
| Имя | Описание | 
|---|---|
controller | Экземпляр класса контроллера | 
page | Идентификатор страницы. Доступные значения: home | 
MyFavoritesOnBeforeAdd - Запускается перед добавлением ресурса в избранное 
Параметры 
| Имя | Описание | 
|---|---|
| rid | ID ресурса | 
| userId | ID пользователя | 
| listId | ID листа | 
| list | Идентификатор листа | 
| tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnAdd - Запускается после добавления ресурса в избранное 
Параметры 
| Имя | Описание | 
|---|---|
| rid | ID ресурса | 
| userId | ID пользователя | 
| listId | ID Листа | 
| list | Идентификатор листа | 
| count | Количество ресурсов в избранном | 
| tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeRemove - Запускается перед удалением ресурса из избранного 
Параметры 
| Имя | Описание | 
|---|---|
rid | ID ресурса | 
userId | ID пользователя | 
listId | ID листа | 
list | Идентификатор листа | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnRemove - Запускается после удаления ресурса из избранного 
Параметры 
| Имя | Описание | 
|---|---|
rid | ID ресурса | 
userId | ID пользователя | 
listId | ID листа | 
list | Идентификатор листа | 
count | Количество ресурсов в избранном | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeClear - Запускается перед очисткой листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
userId | ID пользователя | 
listId | ID листа | 
list | Идентификатор листа | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnClear - Запускается после очистки листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
userId | ID пользователя | 
listId | ID листа | 
list | Идентификатор листа | 
count | Количество ресурсов в избранном | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeCreateUser - Запускается перед созданием пользователя MyFavorites 
Параметры 
| Имя | Описание | 
|---|---|
muid | ID пользователя MODX который в этом момент авторизирован | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnCreateUser - Запускается после создания пользователя MyFavorites 
Параметры 
| Имя | Описание | 
|---|---|
user | Ссылка на объект MyFavoriteUsers | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeCreateList - Запускается перед созданием листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
data | Массив данных для создания листа | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnCreateList - Запускается после создания листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
list | Ссылка на объект MyFavoriteLists | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeRenameList - Запускается перед переименованием листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
| newName | Новое название | 
list | Ссылка на объект MyFavoriteLists | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnRenameList - Запускается после переименования листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
list | Ссылка на объект MyFavoriteLists | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeUpdateList - Запускается перед обновлением листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
data | Массив данных объекта MyFavoriteLists | 
object | Ссылка на объект MyFavoriteLists | 
MyFavoritesOnUpdateList - Запускается после обновления листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
data | Массив данных объекта MyFavoriteLists | 
object | Ссылка на объект MyFavoriteLists | 
MyFavoritesOnBeforeRemoveList - Запускается перед удалением листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
object | Ссылка на объект MyFavoriteLists | 
MyFavoritesOnRemoveList - Запускается после удаления листа избранного 
Параметры 
| Имя | Описание | 
|---|---|
object | Ссылка на объект MyFavoriteLists | 
MyFavoritesOnVerifyRequestFailure - Запускается, когда запрос не прошел проверку безопасности 
Параметры 
| Имя | Описание | 
|---|---|
type | Тип ошибки (bad_request;access_anonymous;csrf;captcha;user_banned;request_limit) | 
code | Код ошибки | 
error | Текст ошибки | 
data | Массив данных запроса | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeSendNotification - Запускается перед отправкой уведомления о запросе не прошедшем проверку 
Параметры 
| Имя | Описание | 
|---|---|
email | E-mail получателя | 
subject | Тема сообщения | 
text | Текст сообщения | 
type | Тип ошибки (bad_request;access_anonymous;csrf;captcha;user_banned;request_limit) | 
code | Код ошибки | 
data | Массив данных запроса | 
tools | Ссылка на объект MyFavoritesTools | 
MyFavoritesOnBeforeStartExport - Запускается перед началом экспорта 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnFinishExport - Запускается после окончания экспорта 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnExportPrepareQuery - Запускается после подготовки конфига экспорта 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
config | Массив конфига для pdoFetch | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnExportBeforePrepareRow - Запускается перед подготовкой экспортируемых данных 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
dataType | Тип данных. (fields или record) | 
data | Массив экспортируемых данных | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnExportAfterPrepareRow - Запускается после подготовки экспортируемых данных 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
dataType | Тип данных. (fields или record) | 
data | Массив экспортируемых данных | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnExportBeforeWriteRow - Запускается перед записью данных в файл 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
dataType | Тип данных. (fields или record) | 
data | Массив экспортируемых данных | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 
MyFavoritesOnExportAfterWriteRow - Запускается после записи данных в файл 
Параметры 
| Имя | Описание | 
|---|---|
classKey | Название класса экспортируемого объекта | 
dataType | Тип данных. (fields или record) | 
data | Массив экспортируемых данных | 
settings | Массив настроек | 
tools | Ссылка на объект MyFavoritesTools | 
context | Ссылка на объект класса экспорта (наследник MyFavoritesExport) | 

