=== Inomarker ===
Contributors: inomarker_team
Tags: иностранный агент, экстремист, террорист, маркировка, СМИ
Requires at least: 5.5
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.10.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Автоматически помечает упоминания иностранных агентов, террористов и экстремистов и позволяет настраивать исключения по значениям полей ACF.

== Description ==

Этот плагин является официальным коннектором для сервиса Inomarker.ru. Он предназначен для помощи администраторам веб-сайтов в автоматизации маркировки конкретных лиц и организаций, требуемой законодательством Российской Федерации.

Действующее законодательство требует обязательной маркировки упоминаний лиц и организаций, включенных в реестры иностранных агентов, террористов и экстремистов. Ручная проверка тысяч имен отнимает много времени и может привести к человеческим ошибкам.

Плагин Inomarker упрощает этот процесс.

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

Ключевые функции:

- Автоматическая маркировка: Плагин автоматически обнаруживает и помечает упоминания на вашем сайте на основе загруженной базы данных.
- Маркировка заголовков: обрабатывает заголовки статей и страниц в основном выводе, хлебных крошках, списках, блоках «Последние публикации» и стандартном HTML-теге `<title>`.
- Три реестра в одном: работает со списками иностранных агентов, террористов и экстремистов.
- Исключения по ACF: позволяет выбрать поля и значения ACF, при совпадении которых маркировка материала не выводится.
- Постоянные исключения: выбранные исключения хранятся отдельно от статистики и не удаляются при ее очистке.
- Фоновая проверка статей: отдельный раздел показывает полные и краткие совпадения во всех опубликованных статьях с фильтрами и прогрессом выполнения.
- AI-проверка совпадений: по отдельному явному включению отправляет ограниченный контекст полных и кратких совпадений в Inomarker.ru, чтобы отличать сущность из реестра от однофамильца или одноименной организации.
- Безопасная маркировка: использует DOM-анализатор для изменения только текстового содержимого, не нарушая HTML-макет, ссылки или короткие коды.
- Два режима маркировки:
    1. Заголовок: Иван Иванов (лицо, выполняющее функции иностранного агента).
    2. Сноски (*): Иван Иванов* с автоматически сгенерированным блоком сносок в конце статьи.

Этот плагин является инструментом, предназначенным для оказания помощи администраторам веб-сайтов в соблюдении требований к маркировке. Хотя Inomarker стремится поддерживать базу данных в актуальном состоянии, этот плагин не гарантирует 100% соблюдения законодательства или абсолютной защиты от штрафов.

- Окончательная ответственность за соблюдение всех применимых законов и нормативных актов лежит на владельце/администраторе веб-сайта.
- Плагин действует как средство автоматизации и должен использоваться как часть более широкой стратегии обеспечения соответствия требованиям.

Для этого плагина требуется активная подписка на "Виджет" на веб-сайте https://inomarker.ru .

== External Service ==

Для правильной работы этого плагина требуется сторонний сервис Inomarker.ru. Плагин выступает в качестве соединителя с этим сервисом для получения и обновления базы данных иностранных агентов, террористов и экстремистов.

Подробная информация об услуге:
- Провайдер: Inomarker.ru
- URL сервиса: https://inomarker.ru
- Условия Inomarker.ru: https://inomarker.ru/terms-of-use
- Политика конфиденциальности Inomarker.ru: https://inomarker.ru/privacy-policy

Для опциональной AI-проверки Inomarker.ru использует OpenAI как обработчика ограниченного контекста:
- Провайдер: OpenAI
- URL сервиса: https://openai.com
- Условия использования: https://openai.com/policies/terms-of-use/
- Политика конфиденциальности: https://openai.com/policies/privacy-policy/
- Правила обработки данных API: https://developers.openai.com/api/docs/guides/your-data

Передача данных:
Плагин отправляет HTTP-запросы к Inomarker API в следующих пяти случаях:

1. Проверка лицензии:
    - Когда: Каждый раз, когда вы нажимаете "Сохранить изменения" в настройках плагина.
    - Конечная точка: `https://inomarker.ru/api/v1/plugin/validate`
    - Отправленные данные: ваш "Ключ API" (указанный в настройках) и "Доменное имя" вашего веб-сайта.
    - Цель: Убедиться, что ваша подписка активна и соответствует домену, на котором установлен плагин.

2. Синхронизация базы данных:
    - Когда: Автоматически раз в день (через WP-Cron) или после активации плагина.
    - Конечная точка: `https://inomarker.ru/api/v1/plugin/regex-data`
    - Отправленные данные: Ваш `Ключ API`.
    - Цель: Загрузить последний список лиц и организаций (сохраненный локально как "inomarker-data.json"), необходимый для текстовой маркировки.

3. Синхронизация статистики маркировки:
    - Когда: Если включена настройка «Отправка аналитики», в фоне через WP-Cron, не чаще одного раза в час. При первом запуске ранее накопленная статистика отправляется небольшими пачками; затем передаются только новые или изменившиеся URL. Повторные изменения одного URL схлопываются в одну актуальную запись очереди.
    - Конечная точка: `https://inomarker.ru/api/v1/plugin/page-stats`
    - Отправленные данные: API-ключ, домен, нормализованный URL без рекламных GET-параметров, найденные имена и тип совпадения, место маркировки (контент, заголовок, хлебные крошки или `<title>`), дата изменения, версии плагина, WordPress и PHP.
    - Не отправляются: текст статьи, IP-адрес или User-Agent посетителя сайта.
    - Цель: Показать владельцу сервиса агрегированную статистику работы каждого установленного плагина.

4. Суточная аналитика обнаружений:
    - Когда: Если включена настройка «Отправка аналитики», при первом просмотре опубликованной статьи за календарные сутки выполняется независимая проверка, а новые результаты отправляются в фоне через WP-Cron не чаще одного раза в час.
    - Конечная точка: `https://inomarker.ru/api/v1/plugin/daily-analytics`
    - Отправленные данные: API-ключ, домен, нормализованный URL, найденные имена, тип совпадения (полный или краткий), дата первого обнаружения и версии окружения.
    - Не отправляются: текст статьи, IP-адрес или User-Agent посетителя сайта.
    - Цель: Посчитать уникальные страницы с краткими и полными совпадениями за каждые сутки независимо от настройки маркировки «Возможно».

5. AI-проверка совпадений (опционально):
    - Когда: Синхронно при показе страницы с полным или кратким совпадением, только если администратор отдельно включил настройку «AI-проверка совпадений». Локальный кэш AI-решений временно отключен для диагностики.
    - Конечная точка: `https://inomarker.ru/api/v1/plugin/resolve-matches`
    - Отправленные данные: API-ключ, домен, URL и заголовок страницы, найденное вхождение, его тип (`full` или `short`), ограниченный фрагмент текста вокруг него, тип и идентификатор записи реестра, версия плагина.
    - Не отправляются: IP-адрес, cookie, учетная запись или иные данные посетителя сайта.
    - Цель: Определить, относится ли полное или краткое совпадение именно к указанной сущности из актуального реестра. Inomarker может передать этот ограниченный контекст в OpenAI для классификации идентичности.

== Terms and Privacy ==

Используя этот плагин, вы соглашаетесь с условиями предоставления услуг Inomarker.ru .
- Условия предоставления услуг https://inomarker.ru/terms-of-use
- Политика конфиденциальности https://inomarker.ru/privacy-policy

== Installation ==

Для подключения плагина требуется активная подписка на продукт Widget в сервисе. Inomarker.ru .

**1. Установка через админ-панель WordPress:**

1. Перейдите в раздел "Плагины" -> "Добавить новый".
2. Введите "Inomarker" в поле поиска.
3. Нажмите "Установить", а затем "Активировать".

**2. Установка вручную (через ZIP-архив):**

1. Загрузите ZIP-архив плагина со страницы репозитория.
2. Перейдите в раздел "Плагины" -> "Добавить новый" -> "Загрузить плагин".
3. Выберите загруженный ZIP-архив и нажмите "Установить".
4. Активируйте плагин.

**3. После активации (обязательный шаг):**

1. Перейдите в "Настройки" -> "Inomarker" в своей админ-панели.
2. Скопируйте свой API-ключ виджета из личного кабинета на https://inomarker.ru/widgets .
3. Вставьте ключ в поле API-ключ виджета и нажмите Сохранить изменения.
4. Плагин автоматически свяжется с сервером Inomarker и подтвердит ваш ключ и домен.
5. Если вы видите статус "АКТИВЕН", вы можете включить плагин, используя переключатель "Статус плагина".
6. Выберите "Стиль разметки" (по умолчанию рекомендуется "В текстовом виде").
7. При необходимости отключите настройку «Отправка аналитики».
8. При необходимости включите «AI-проверку совпадений», предварительно ознакомившись с описанием передаваемых данных. Полные совпадения проверяются всегда; краткие — только вместе с маркировкой «Возможно».
9. Готово! Плагин запустит фоновую загрузку данных и пометит ваши статьи.

== Frequently Asked Questions ==

= Замедлит ли этот плагин работу моего веб-сайта? =
Нет. Плагин разработан с учетом высокой производительности.
1. ** Загрузка данных:** Выполняется в фоновом режиме (WP-Cron) один раз в день, не влияя на скорость загрузки для пользователей.
2. **Пометка:** Выполняется на стороне сервера (PHP), а не в браузере (JS). Мы используем `DOMDocument` и `preg_replace_callback' для максимально быстрой обработки. Это намного быстрее, чем у JS-виджета.
3. **Полная проверка статей:** Запускается администратором вручную и выполняется через WP-Cron небольшими пакетами с ограничением времени каждого запуска.
4. **AI-проверка:** Показ полного или краткого совпадения может ожидать синхронный ответ API. Локальный кэш AI-решений временно отключен; обычный режим после сетевой ошибки включает короткий предохранитель, а debug-режим обходит его для повторной диагностики.

= Что произойдет, если истечет срок действия моей подписки на Inomarker? =
Плагин автоматически обнаружит это во время ежедневной синхронизации. Оно:
1. **Отключает ** маркировку на сайте (переключает "inomarker_enabled` на `false").
2. ** Покажет вам большое уведомление в админ-панели о том, что срок действия подписки истек и пометка больше не работает.
3. ** Заблокирует ** возможность включения плагина до тех пор, пока вы не продлите подписку.

= Обязательно ли использовать стиль "сносок"? =
Нет. Самый безопасный и рекомендуемый способ - обозначить это "В тексте" (встроенно). Однако, по мнению медиа-юристов (например, из Центра защиты прав СМИ), использование сносок "*" также является приемлемой практикой. Мы предоставляем вам выбор.

= Почему нижний колонтитул для иностранных агентов (*) такой ОГРОМНЫЙ? =
Это не ошибка дизайна. Это ** прямое требование закона**. Согласно приказу Роскомнадзора № 124, шрифт для обозначения иностранного агента должен быть ** в два раза (2x) крупнее ** основного шрифта вашего сайта. Наш плагин автоматически применяет этот стиль, чтобы обеспечить соблюдение вами законодательства и защитить вас от штрафов.

= Будет ли плагин помечать текст в заголовках? =
Да. Плагин обрабатывает заголовки статей и страниц во фронтенд-компонентах, использующих стандартные функции WordPress `the_title` или `get_the_title`: в основном выводе, хлебных крошках, списках и блоках вроде «Последние публикации». Результат `the_title` всегда содержит только текстовую маркировку без HTML-разметки, чтобы темы могли безопасно использовать его и в видимом тексте, и в HTML-атрибутах. Также проверяются HTML-заголовки внутри контента и стандартный тег `<title>`. Административные страницы, REST API, XML-RPC и ленты не изменяются.

= Где хранятся данные? =
Плагин загружает файл `inomarker-data.json` и безопасно сохраняет его в папке `wp-content/uploads/`.
Статистика хранится в таблице `wp_inomarker_stats`, результаты полной проверки статей — в `wp_inomarker_article_matches`, постоянные исключения — независимо в `wp_inomarker_exclusions`, а несинхронизированные изменения — во временной очереди `wp_inomarker_stats_queue`. Суточные обнаружения временно хранятся в `wp_inomarker_daily_analytics`: уже переданные строки прошлых суток удаляются ежедневно, а неотправленные сохраняются до успешной синхронизации. Фоновая синхронизация не выполняет внешний API-запрос во время формирования страницы для посетителя.

1. Страница настроек: Общий вид страницы "Inomarker" в панели администратора WordPress.
2. Статус "Активен": Карточка статуса с активной, подтвержденной подпиской.
3. Статус ошибки: Пример ошибки при вводе неверного ключа или несоответствии домена.
4. Пример пометки "Встроенный" (в тексте): Как выглядит пометка (в круглых скобках) в реальной статье.
5. Пример пометки "Сноски" (*): Как выглядит пометка (звездочками) в статье.
6. Заключительный блок сносок:** Демонстрация юридически корректного блока сносок в конце статьи с разными размерами шрифта.
7. Глобальное уведомление: Как выглядит предупреждение в панели администратора, если срок действия подписки истек.

== Upgrade Notice ==

= 1.10.0 =
AI-проверка расширена на полные совпадения; каждый кандидат передает тип `full` или `short`.

= 1.9.3 =
Локальный кэш AI-решений временно отключен, а debug-консоль статьи показывает отправку запроса и очищенный ответ Laravel API.

= 1.9.2 =
Возвращен отдельный переключатель AI-проверки; передача контекста больше не включается автоматически вместе с краткими совпадениями.

= 1.9.1 =
AI-проверка теперь автоматически работает вместе с режимом кратких совпадений; успешные решения кэшируются на 24 часа.

= 1.9.0 =
Добавлена опциональная AI-проверка кратких совпадений с суточным кэшем и безопасным поведением при сбое API.

= 1.8.2 =
HTML-разметка полностью убрана из результата `the_title`; все заголовки получают безопасную текстовую маркировку.

= 1.8.1 =
Исправлен вывод HTML-тегов маркировки как текста в заголовках архивов и других списков публикаций.

= 1.8.0 =
Добавлен раздел «Статьи» с безопасной фоновой проверкой всех публикаций, прогрессом, фильтрами и пагинацией.

= 1.7.0 =
Добавлена независимая суточная аналитика кратких и полных совпадений с фоновой отправкой и настройкой отключения.

= 1.6.2 =
Добавлена фоновая почасовая синхронизация изменившейся статистики страниц с Inomarker.ru.

= 1.6.1 =
Добавлена маркировка заголовков статей и страниц во фронтенд-компонентах и стандартном теге `<title>`.

= 1.6.0 =
Добавлены исключения маркировки по значениям полей ACF с интерактивным выбором и оптимизированной проверкой через кэш метаданных WordPress.

= 1.5.3 =
Статистика обновляется сразу после добавления или удаления маркируемых сущностей в статье.

= 1.5.2 =
Сохраненные исключения автоматически переносятся в отдельную таблицу и больше не зависят от срока хранения статистики.

== Changelog ==

= 1.10.0 =
* AI-проверка теперь получает все полные совпадения и включенные краткие совпадения.
* Кандидат передает тип `full` или `short`, который учитывается в промпте и ключе кэша Laravel.
* Решение `do_not_mark` отменяет маркировку как краткого, так и полного совпадения.
* При `uncertain` или ошибке API полное совпадение сохраняет прежнюю маркировку, а краткое — пометку «Возможно».
* Плагин использует общий endpoint `/api/v1/plugin/resolve-matches`; прежний адрес сохранен для старых версий.

= 1.9.3 =
* Локальный суточный кэш AI-решений временно отключен для диагностики.
* Debug-консоль статьи показывает, был ли отправлен запрос, HTTP-статус и очищенное тело ответа Laravel API.
* Debug-режим обходит часовой кэш готовой разметки и временный circuit breaker.
* Из диагностического вывода удаляются API-ключи, токены, пароли и данные авторизации.

= 1.9.2 =
* Возвращен отдельный выключенный по умолчанию переключатель AI-проверки кратких совпадений.
* Режим кратких совпадений больше не включает передачу контекста в Laravel API автоматически.
* Успешные валидные решения по-прежнему кэшируются на 24 часа; ошибки API не кэшируются.
* Обновлена схема кэша готовой разметки, чтобы настройка применилась сразу после обновления.

= 1.9.1 =
* AI-проверка автоматически выполняется для новых кратких совпадений, когда включен режим кратких совпадений.
* Удален отдельный дублирующий переключатель AI-проверки.
* Успешные валидные решения кэшируются на 24 часа; ошибки API не кэшируются.
* Обновлена схема кэша готовой разметки, чтобы новая логика применялась сразу после обновления.

= 1.9.0 =
* Добавлена опциональная синхронная проверка кратких совпадений через Inomarker API и OpenAI.
* Успешные решения кэшируются на 24 часа; ошибки не кэшируются, а повторные сетевые сбои временно ограничиваются circuit breaker.
* Подтвержденное совпадение получает обычную маркировку, другое лицо не маркируется, неопределенное совпадение сохраняет пометку «Возможно».

= 1.8.2 =
* Результат стандартного фильтра WordPress `the_title` теперь всегда содержит текст без `<span>` и другой HTML-разметки.
* Исправлены заголовки одиночных статей, хлебные крошки, блоки последних публикаций и HTML-атрибуты, использующие название записи.
* Обновлена схема кэша фрагментов, чтобы разметка от версии 1.8.1 не сохранялась после обновления.

= 1.8.1 =
* Исправлено отображение `<span class="inomarker-highlight">` как текста в заголовках архивов, тегов, поиска и других списков публикаций.
* Заголовки в списках используют текстовую маркировку; HTML-подсветка заголовка текущей статьи сохранена.
* Обновлена схема кэша фрагментов, чтобы ранее сохраненная разметка не появлялась после обновления.

= 1.8.0 =
* Добавлен раздел «Статьи» со ссылками и найденными полными и краткими совпадениями.
* Реализованы фильтры по типу совпадения и пагинация результатов.
* Полная проверка опубликованных статей выполняется WP-Cron небольшими пакетами с ограничением времени обработки.
* Интерфейс показывает прогресс, остаток, количество найденных статей, дату последней успешной проверки и ошибки.
* Результаты переключаются только после успешного завершения, а предыдущие наборы удаляются пакетами.

= 1.7.0 =
* Добавлена отдельная суточная таблица страниц с полными и краткими совпадениями.
* Краткие совпадения учитываются в аналитике независимо от настройки маркировки «Возможно».
* Повторное сканирование одного URL ограничено суточным кэшем; запись уникальна в рамках URL и даты.
* Новые наблюдения отправляются в Laravel почасовым WP-Cron и повторяются после сетевых ошибок без дублирования.
* Добавлена настройка «Отправка аналитики», управляющая фоновой передачей статистики.
* Переданные строки прошлых суток очищаются ежедневно; неотправленные данные сохраняются до успешной синхронизации.

= 1.6.2 =
* Добавлена надежная очередь фоновой синхронизации локальной статистики с Inomarker.ru через WP-Cron.
* Новые и изменившиеся URL отправляются пачками не чаще одного раза в час; повторные изменения одной страницы схлопываются.
* Сетевые ошибки повторяются с увеличивающейся задержкой, а повторная отправка не создает дубликаты.
* В статистике учитывается место маркировки: контент, заголовок, хлебные крошки или стандартный тег `<title>`.
* Текст материалов и данные посетителей сайта в API статистики не передаются.

= 1.6.1 =
* Добавлена маркировка заголовков статей и страниц в основном выводе, стандартных и блочных хлебных крошках, а также в интеграциях Yoast SEO, Rank Math и Breadcrumb NavXT.
* Стандартный тег `<title>` проверяется с текстовой маркировкой без HTML-элементов.
* Кэш заголовков изолирован по записи, URL страницы, контексту и HTML-фрагменту; исключения URL читаются из БД один раз за запрос.
* Найденные в визуальном или HTML-заголовке сущности учитываются в общей статистике страницы.

= 1.6.0 =
* Добавлен раздел исключений по значениям ACF, доступный при установленном плагине ACF.
* Реализован интерактивный поиск полей и выбор нескольких значений для Select, Checkbox, Radio и Button Group.
* Проверка исключений оптимизирована через кэш метаданных WordPress и повторное использование результата в рамках запроса.

= 1.5.3 =
* Исправлена синхронизация статистики после изменения найденных сущностей в статье.
* Суточный браузерный throttle теперь учитывает состояние найденных сущностей, а не только время последней отправки.

= 1.5.2 =
* Исключения вынесены в отдельную таблицу и больше не удаляются при очистке статистики.
* Добавлена одноразовая автоматическая миграция ранее сохранённых исключений.

= 1.5.1 =
* Добавлена поддержка кириллицы в url адресе

= 1.5.0 =
* Добавлена настройка "Маркировать через X дней после публикации" для отложенной маркировки статей.
* Статистика страниц нормализуется по каноническому URL без GET-параметров, а накопленные дубли автоматически схлопываются.
* Синхронизация статистики теперь выполняется даже при отсутствии найденных упоминаний: пустые страницы удаляются из статистики, а для неизменных страниц добавлен суточный state-cache.

= 1.4.2 =
* Исправлена обработка контента с шорткодами: маркировка выполняется после их штатного отрабатывания в WordPress.
* Обновлён ключ кэша маркировки: добавлены schema-метка и hash контента для корректной инвалидации.

= 1.4.1 =
* Актуализирована версия плагина.
* Маркировка теперь применяется в ссылках и заголовках (`h1`, `h2`, `h3`).

= 1.4.0 =
* Добавлена защита API статистики: подписанный токен, валидация URL/хоста и ограничение частоты запросов.
* Сбор статистики переведен на атомарный upsert для снижения нагрузки на базу данных.
* Добавлена ежемесячная очистка статистики старше 31 дня (WP-Cron).
* Добавлены индексы таблицы статистики для ускорения фильтрации и сортировки в админке.
* Исправлена стратегия кэширования маркировки: ключ учитывает hash URL и версию кэша.
* Добавлена настройка включения/отключения маркировки по короткой регулярке ("Возможно").

= 1.3.0 =

* Добавлена поддержка автоматических обновлений

= 1.2.1 =

* Обновлено описание readme для соответствия рекомендациям репозитория.

= 1.2.0 =
* Добавлена страница в панели с выводом всех ссылок, где выполняется автоматическое проставление меток + возможность исключить проставление меток определенного значения на выбранной странице

= 1.0.0 =
* Добавлена страница настроек в главном меню Inomarker.
* Реализована мгновенная проверка API-ключа и домена при сохранении.
* Добавлен фоновый процесс (WP-Cron) для ежедневной синхронизации статуса подписки и загрузки `данных".json".
* Основной механизм присвоения меток реализован на стороне сервера с использованием `DOMDocument` и `preg_replace_callback'.
* Добавлена защита от двойного присвоения меток (проверка на `*` или `(` после сопоставления).
* Добавлены два режима разметки: "В тексте" (inline) и "Сноски" (footnote).
* Плагин автоматически помечает публикации, страницы и выдержки (на главной странице, в архивах).
* Добавлено глобальное уведомление в админ-панели о просроченных подписках.
