# =========================================================================== #
# NG CMS // Плагин "Закладки пользователей" (Bookmarks)                       #
# =========================================================================== #

## Что это такое?

Плагин позволяет авторизованным пользователям сохранять понравившиеся новости
в личные закладки для быстрого доступа к ним в будущем.

## Возможности

✓ Добавление/удаление новостей в закладки через AJAX без перезагрузки страницы
✓ Счетчик закладок - показывает сколько пользователей добавили новость
✓ Блок закладок в сайдбаре с выводом последних добавленных
✓ Отдельная страница со всеми закладками пользователя
✓ Лимит на количество закладок для одного пользователя
✓ Кэширование для повышения производительности
✓ Современные уведомления через notify.js (Toast notifications)
✓ Извлечение и отображение изображений из новостей

## Установка

После активации плагина добавьте переменные в шаблоны:

**В news.short.tpl или news.full.tpl:**
```twig
{{ plugin_bookmarks_news }}
```
Выводит кнопку "Добавить в закладки" / "Удалить из закладок"

**В main.tpl (для сайдбара):**
```twig
{{ plugin_bookmarks }}
```
Выводит блок с последними закладками пользователя

**В usermenu.tpl (для меню пользователя):**
```twig
<a href="{{ p.bookmarks.link }}">
    Мои закладки
    {% if p.bookmarks.count > 0 %}
        ({{ p.bookmarks.count }})
    {% endif %}
</a>
```

## Настройки в админ-панели

**Основные настройки:**
- Лимит закладок на пользователя (по умолчанию: без ограничений)
- Показывать счетчик добавлений (сколько раз новость добавлена в закладки)
- Максимальная длина заголовка в сайдбаре (символов)

**Отображение в сайдбаре:**
- Включить/выключить блок в сайдбаре
- Максимальное количество закладок в сайдбаре
- Скрывать блок если закладок нет

**Кэширование:**
- Включить кэширование (рекомендуется)
- Время жизни кэша (минуты)

**Шаблоны:**
- Источник шаблонов: из темы сайта или из папки плагина

## Используемые шаблоны

### bookmarks.tpl
Оболочка блока закладок для сайдбара

**Переменные:**
- `entries` - массив закладок
  - `link` - ссылка на новость
  - `title` - заголовок новости
  - `image` - URL изображения новости (или пустая строка)
- `bookmarks_page` - ссылка на страницу со всеми закладками
- `count` - количество закладок пользователя
- `tpl_url` - URL текущей темы

**Пример вывода изображения:**
```twig
{% for entry in entries %}
    <img src="{{ entry.image ? entry.image : tpl_url ~ '/img/img-none.png' }}"
         width="50" height="50" alt="{{ entry.title }}"/>
    <a href="{{ entry.link }}">{{ entry.title }}</a>
{% endfor %}
```

### add.remove.links.style.tpl
Кнопка добавления/удаления закладки на странице новости

**Переменные:**
- `news` - ID новости
- `found` - флаг: true если новость уже в закладках, false если нет
- `link` - полная ссылка с GET-параметрами (работает без JavaScript)
- `url` - базовая ссылка для AJAX-запроса
- `action` - текущее действие: 'delete' (удалить) или 'add' (добавить)
- `link_title` - текст для атрибута title ссылки
- `counter` - счетчик добавлений новости всеми пользователями
- `isFullNews` - true для полной новости, false для короткой
- `isShortNews` - противоположность isFullNews

**Важно:**
- Сохраняйте `id="bookmarks_{{ news }}"` у контейнера - используется для AJAX
- Не изменяйте структуру вызова функции `bookmarks()` в onclick
- Функция автоматически обновляет содержимое без перезагрузки страницы

**Пример:**
```twig
<span id="bookmarks_{{ news }}">
    <a href="{{ link }}" onclick="bookmarks('{{ url }}', '{{ news }}', '{{ action }}', {{ isFullNews ? 'true' : 'false' }}); return false;">
        {% if found %}
            Удалить из закладок
        {% else %}
            Добавить в закладки
        {% endif %}
    </a>
    {% if counter %}({{ counter }}){% endif %}
</span>
```

### ajax.add.remove.links.style.tpl
Шаблон для обновления кнопки после AJAX-запроса

**Переменные:**
- `news` - ID новости
- `action` - следующее действие после текущего: 'delete' или 'add'
- `url` - базовая ссылка для AJAX
- `link_title` - текст title
- `counter` - обновленный счетчик
- `isFullNews` / `isShortNews` - флаги типа отображения

**Важно:** Должен совпадать по структуре с add.remove.links.style.tpl,
чтобы при AJAX-обновлении интерфейс не "ломался".

### not.logged.links.tpl
Отображение для неавторизованных пользователей (только счетчик)

**Переменные:**
- `counter` - количество добавлений новости в закладки
- `isFullNews` / `isShortNews` - флаги типа отображения

### bookmarks.page.tpl
Страница со всеми закладками пользователя

**Переменные:**
- `count` - общее количество закладок
- `all_bookmarks` - HTML со списком новостей (генерируется через news_showlist)
- `tpl_url` - URL текущей темы

## Система уведомлений

Плагин использует стандартную систему уведомлений NGCMS через `showToast()`.

**Типы уведомлений:**
- **success** (зеленый) - успешное добавление/удаление закладки
- **error** (красный) - ошибка (не авторизован, ошибка добавления)
- **warning** (оранжевый) - превышен лимит закладок

**Автоматическое закрытие:**
- Успешные операции закрываются через 3 секунды
- Ошибки требуют ручного закрытия

**Требования:**
В шаблоне main.tpl должны быть подключены:
```twig
<link rel="stylesheet" href="{{ scriptLibrary }}/notify.css">
<script type="text/javascript" src="{{ scriptLibrary }}/notify.js"></script>
{{ notify|raw }}
```

## AJAX-работа плагина

При клике на кнопку закладки:
1. JavaScript вызывает функцию `bookmarks(url, news, action, isFullNews)`
2. Отправляется AJAX-запрос на сервер
3. Сервер проверяет права, лимиты, выполняет операцию
4. Возвращает обновленный HTML кнопки с комментарием `<!-- add -->` или `<!-- delete -->`
5. JavaScript обновляет кнопку на странице и показывает уведомление

**Если JavaScript отключен:**
Кнопка работает как обычная ссылка с перезагрузкой страницы.

## Интеграция с ng-helpers

Плагин использует функции из ng-helpers v0.2.0:
- `cache_get()` / `cache_put()` - кэширование данных
- `logger()` - логирование действий пользователей
- `sanitize()` - очистка входных данных
- `get_ip()` - получение IP-адреса
- `str_limit()` - ограничение длины строк

## Извлечение изображений

Плагин автоматически извлекает первое изображение из содержимого новости
(BBCode тег `[img]`) для отображения в закладках.

**Алгоритм:**
1. Ищет первый `[img=URL]` или `[img]URL[/img]` в контенте новости
2. Если путь относительный - добавляет базовый URL сайта
3. Если изображения нет - возвращает пустую строку

**В шаблоне:**
```twig
<img src="{{ entry.image ? entry.image : tpl_url ~ '/img/img-none.png' }}"
     alt="{{ entry.title }}"/>
```

## Структура базы данных

**Таблица:** `{prefix}_bookmarks`

| Поле      | Тип       | Описание                  |
|-----------|-----------|---------------------------|
| user_id   | INT       | ID пользователя           |
| news_id   | INT       | ID новости                |

**Индексы:**
- `user_id` - для быстрой выборки закладок пользователя
- `news_id` - для подсчета количества добавлений новости

## Логирование

При включенном логировании ng-helpers записываются события:
- Добавление закладки: `userID, newsID, IP`
- Удаление закладки: `userID, newsID, IP`
- Просмотр страницы закладок: `userID, count, IP`
- Просмотр блока в сайдбаре: `userID, count, IP`

## Производительность

**Рекомендации:**
1. Включите кэширование в настройках (время жизни 5-15 минут)
2. Ограничьте количество закладок в сайдбаре (5-10 штук)
3. Используйте ng-helpers для оптимизации запросов

**Кэш инвалидируется:**
- При добавлении новой закладки
- При удалении закладки
- По истечении времени жизни кэша

## Совместимость

- **NG CMS:** 0.9.2+
- **ng-helpers:** 0.2.0+ (опционально, но рекомендуется)
- **Twig:** Все шаблоны на Twig
- **jQuery:** Не требуется (используется vanilla JS)
- **Browsers:** IE9+, все современные браузеры

## История версий

**v2.7 [2026-01-16]** - Переход на notify.js, исправление двойных уведомлений
**v2.6 [2025-08-13]** - Добавлено извлечение изображений
**v2.5 [2025-05-07]** - Счетчик в usermenu.tpl
**v2.4 [2014-07-26]** - Переход на Twig
**v2.3 [2011-01-01]** - Красивые всплывающие уведомления
**v2.0 [2010-12-13]** - AJAX, страница закладок, счетчик
