Перейти к содержанию

Для внешнего получателя используйте публичную ссылку на документ. В авторизованном интерфейсе получайте документ через PHP API модуля documentgenerator и передавайте подготовленные данные в собственный компонент.

Внимание

Стандартные компоненты модуля — внутренние. Не подключайте их в своих доработках. Для встраивания используйте API и собственный компонент.

Выбрать способ встраивания

Способ зависит от пользователя, задачи и требуемого уровня доступа.

|

|| Задача | Способ | Что проверить || || Показать документ внешнему получателю | Включить публичную ссылку методом Document::enablePublicUrl() и получить ее через Document::getPublicUrl() | Право на публикацию, актуальность документа и возможность отозвать ссылку || || Показать документ авторизованному пользователю | Создать собственный компонент в /local/components/, получить документ через PHP API и передать ссылки в шаблон компонента | Разрешение на просмотр документов и доступ пользователя к данным провайдера || || Добавить действие в интерфейс другого модуля | Разместить кнопку или ссылку в точке расширения этого модуля, а генерацию и проверку прав выполнить на сервере | Правила расширения исходного модуля, защита запроса и обработка Result || |#

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

Открыть документ по публичной ссылке

Публичная ссылка позволяет открыть документ без учетной записи в продукте. Метод Document::getPublicUrl() возвращает готовый URL для передачи внешнему получателю.

Не извлекайте идентификатор и хеш из URL и не собирайте такой адрес самостоятельно. Хеш предоставляет доступ к документу без авторизации. Не записывайте публичную ссылку в журнал и не передавайте ее пользователю, которому документ не предназначен.

Порядок включения, получения и отключения ссылки приведен в статье Файлы, форматы и преобразование.

Проверить публичный просмотр

Проверьте весь жизненный цикл ссылки.

  1. Сформируйте и сохраните документ.

  2. Проверьте право текущего пользователя на исходный объект и операцию публикации.

  3. Включите публичную ссылку и убедитесь, что getPublicUrl() вернул URL.

  4. Откройте URL в браузере без авторизации и проверьте доступность ожидаемого файла.

  5. Отключите ссылку через enablePublicUrl(false) и убедитесь, что прежний URL больше не открывает документ.

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

Встроить документ в авторизованный интерфейс

Для собственного раздела создайте компонент в пространстве имен приложения внутри /local/components/. Компонент должен получать только необходимые идентификаторы, проверять доступ на сервере и передавать в шаблон подготовленные данные.

Подготовить входные параметры

Передавайте идентификатор документа из серверных данных страницы после проверки прав пользователя на исходный объект. Приведите значение к целому числу и отклоните запрос, если идентификатор отсутствует.

Не передавайте из HTTP-запроса класс провайдера, имя модуля, путь к шаблону компонента или готовую ссылку на файл без проверки. Если эти значения зависят от типа исходного объекта, определите их на сервере по разрешенному типу и идентификатору.

Проверить два уровня доступа

До получения файла выполните две независимые проверки:

  • Driver::getInstance()->getUserPermissions($userId)->canViewDocuments() проверяет разрешение пользователя на просмотр документов модуля.

  • Document::hasAccess($userId) проверяет доступ пользователя к исходным данным через провайдер документа.

Если документ связан с объектом другого модуля, примените и модель прав этого модуля. Не считайте наличие идентификатора документа или доступность записи достаточной проверкой.

Подробнее о разделении разрешений читайте в статье Права доступа.

Получить данные для шаблона

Загрузите документ методом Document::loadById(). Для сохраненного документа вызовите getFile(false), чтобы получить текущие ссылки без постановки новой задачи преобразования.

Проверьте Result до чтения данных. Передавайте в шаблон только значения, которые нужны интерфейсу:

  • downloadUrl — ссылка на исходный файл,

  • pdfUrl — ссылка на PDF, если преобразование завершено,

  • imageUrl — ссылка на изображение, если оно создано,

  • printUrl — маршрут представления для печати, если PDF готов,

  • идентификатор и безопасное название документа.

Ссылки на производные форматы могут отсутствовать без ошибки, пока выполняется преобразование. Не запускайте повторное преобразование при каждом открытии страницы. Сценарии ожидания и повторной проверки описаны в статье Файлы, форматы и преобразование.

Реализовать логику компонента

Создайте компонент приложения, например /local/components/mycompany/document.view/class.php. Замените mycompany на пространство имен своего проекта.

Пример. Компонент получает идентификатор документа, проверяет оба уровня доступа и передает текущие ссылки в собственный шаблон.

<?php

use Bitrix\DocumentGenerator\Document;
use Bitrix\DocumentGenerator\Driver;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Main\Loader;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
{
    die();
}

class MyCompanyDocumentViewComponent extends CBitrixComponent
{
    public function executeComponent(): void
    {
        // Проверяем, что API модуля доступен
        if (!Loader::includeModule('documentgenerator'))
        {
            ShowError('Модуль documentgenerator не установлен');

            return;
        }

        // Получаем входной идентификатор и текущего пользователя
        $documentId = (int)($this->arParams['DOCUMENT_ID'] ?? 0);
        $userId = (int)CurrentUser::get()->getId();

        if ($documentId <= 0)
        {
            ShowError('Не передан идентификатор документа');

            return;
        }

        // Проверяем разрешение модуля до загрузки документа
        $permissions = Driver::getInstance()->getUserPermissions($userId);

        if (!$permissions->canViewDocuments())
        {
            ShowError('Нет разрешения на просмотр документов');

            return;
        }

        // Не различаем отсутствующий документ и отказ провайдера в тексте ошибки
        $document = Document::loadById($documentId);

        if ($document === null || !$document->hasAccess($userId))
        {
            ShowError('Документ не найден или недоступен');

            return;
        }

        // Получаем только готовые ссылки без запуска преобразования
        $result = $document->getFile(false);

        if (!$result->isSuccess())
        {
            ShowError(implode('; ', $result->getErrorMessages()));

            return;
        }

        $data = $result->getData();

        // Передаем в шаблон минимальный набор данных
        $this->arResult = [
            'ID' => (int)$document->ID,
            'TITLE' => $document->getTitle(),
            'DOWNLOAD_URL' => (string)($data['downloadUrl'] ?? ''),
            'PDF_URL' => (string)($data['pdfUrl'] ?? ''),
            'IMAGE_URL' => (string)($data['imageUrl'] ?? ''),
            'PRINT_URL' => (string)($data['printUrl'] ?? ''),
        ];

        $this->includeComponentTemplate();
    }
}

Код объединяет отсутствующий документ и отказ в доступе в одно сообщение. Такой ответ не раскрывает пользователю наличие чужого документа. Если исходный модуль требует дополнительной проверки объекта, выполните ее до Document::loadById().

Компонент не использует общий кеш. Ссылки и результат проверки прав зависят от пользователя и текущего состояния документа. Если интерфейсу нужен кеш, не сохраняйте в общем кеше результат hasAccess() и URL файлов. Повторно проверяйте права и получайте ссылки для каждого запроса.

Подготовить шаблон компонента

Шаблон пользовательского компонента должен работать только с подготовленным $arResult. Экранируйте название документа и другой текст перед выводом. Для URL используйте значения, которые вернул API модуля, и не собирайте пути из FILE_ID, идентификатора документа или имени файла.

Показывайте действие только при наличии соответствующей ссылки. Например, не выводите кнопку PDF, если ключ pdfUrl отсутствует. Ошибки загрузки, доступа и чтения файла показывайте раздельно, чтобы пользователь понимал следующий шаг.

Собственный шаблон должен опираться только на контракт пользовательского компонента.

Проверить авторизованный интерфейс

Проверьте компонент в нескольких состояниях:

  1. Документ существует, пользователь может просматривать документы и имеет доступ к исходным данным.

  2. Документ не найден или идентификатор некорректен.

  3. У пользователя нет разрешения canViewDocuments().

  4. Провайдер отклоняет доступ к исходному объекту.

  5. Исходный файл доступен, но PDF и изображение еще не созданы.

  6. Хранилище вернуло ошибку чтения файла.

  7. Документ обновлен, а интерфейс получил актуальные ссылки при новом запросе.

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

Добавить действие в интерфейс другого модуля

Кнопку создания, скачивания или просмотра документа размещайте через точки расширения модуля, который владеет исходным объектом. Этот модуль определяет доступность действия, проверяет права на объект и передает серверному обработчику его идентификатор.

Обработчик должен:

  1. Проверить сессию или другой механизм защиты запроса.

  2. Проверить право пользователя на исходный объект и операцию с документом.

  3. Загрузить шаблон или документ через PHP API.

  4. Выполнить операцию и проверить Result.

  5. Вернуть интерфейсу только нужные данные или безопасный URL.

Типичные ошибки

|

|| Ошибка | Признак | Решение || || Проверка только одного уровня прав | Код проверяет только разрешение модуля или только доступ провайдера | До получения файла или включения публичной ссылки проверьте разрешение модуля, доступ провайдера и права исходного модуля || || Формирование ссылок вручную | Код собирает адрес из идентификатора документа или имени файла | Получайте ссылки из данных успешного Result или через Document::getPublicUrl() || |#

Связанные материалы