Получить элемент по id файла из свойства (тип файл). API Битрикс

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

Право на просмотр файла в проекте хранится в булевом свойстве FOR_VALID_GROUPS_ONLY

$documentHelper = new \Helper\DocumentHelper(
    $this::IBLOCK_ID_DOCUMENTS, // iblockId
    'FOR_VALID_GROUPS_ONLY', // propCode
    'N' // propValidValue
);
// Получаем массив Id файлов, которые нужно удалить из выборки
$checkPermissionResult = $documentHelper->checkPermissionsByProp($documentsIds);

// Ниже вся остальная логика проекта...
<?php

namespace Helper;

use Bitrix\Iblock\ElementPropertyTable;
use Bitrix\Iblock\Iblock;
use Bitrix\Main\SystemException;

class DocumentHelper
{
    private int $iblockId;
    private string $propCode;

    // Проверяемое значение свойства.
    // Например, мы не хотим показывать элементы со свойством "Доступно Только для дистрибьюторов" (Y/N),
    // если пользователь НЕ состоит в группе "Дистрибьюторы" (или любая другая логика), значит нам в конструктор класса
    // нужно передать 'N'.
    private string $propValidValue;

    public function __construct(int $iblockId, string $propCode, string $propValidValue)
    {
        $this->iblockId = $iblockId;
        $this->propCode = $propCode;
        $this->propValidValue = $propValidValue;
    }

    public function checkPermissionsByProp(array $fileIds): array
    {
        if (empty($fileIds)) {
            return [];
        }

        return $this->validate($fileIds);
    }

    public function validate(array $fileIds): array
    {
        try {
            // Шаг 1: Получаем привязки файлов к элементам (сразу из нескольких таблиц).
            $fileToElementsMap = $this->getFileToElementsMap($fileIds);
            if (empty($fileToElementsMap)) {
                return $this->getNotFoundFiles($fileIds);
            }

            // Шаг 2: Получаем значения свойства для элементов.
            $elementIds = array_keys($fileToElementsMap);
            $elementPropValues = $this->getElementPropertyValues($elementIds);

            // Шаг 3: Фильтруем недоступные файлы.
            return $this->filterInvalidFiles($fileIds, $fileToElementsMap, $elementPropValues);
        } catch (\Exception $e) {
            // Логирование ошибки, если нужно.
            \Bitrix\Main\Diag\Debug::writeToFile(
                $e->getMessage(),
                date('d.m.Y H:i:s').' Ошибка validate():',
                'docHelper.log');
            return [];
        }
    }

    private function getFileToElementsMap(array $fileIds): array
    {
        $res = ElementPropertyTable::getList([
            'filter' => [
                'VALUE' => $fileIds,
                'IBLOCK_ELEMENT.IBLOCK_ID' => $this->iblockId
            ],
            'select' => ['VALUE', 'IBLOCK_ELEMENT_ID'],
            'runtime' => [
                'IBLOCK_ELEMENT' => [
                    'data_type' => '\Bitrix\Iblock\ElementTable',
                    'reference' => [
                        '=this.IBLOCK_ELEMENT_ID' => 'ref.ID'
                    ]
                ]
            ]
        ]);

        $map = [];
        while ($row = $res->fetch()) {
            $fileId = (int)$row['VALUE'];
            $elementId = (int)$row['IBLOCK_ELEMENT_ID'];
            $map[$elementId][] = $fileId;
        }

        return $map;
    }

    private function getElementPropertyValues(array $elementIds): array
    {
        $iblock = Iblock::wakeUp($this->iblockId);
        $entity = $iblock->getEntityDataClass();

        $res = $entity::getList([
            'select' => ['ID', $alias = $this->propCode . '_' => $this->propCode],
            'filter' => ['ID' => $elementIds],
            'cache' => ['ttl' => 3600]
        ]);

        $values = [];
        while ($row = $res->fetch()) {
            $values[(int)$row['ID']] = $row[$alias.'VALUE'];
        }

        return $values;
    }

    private function filterInvalidFiles(array $fileIds, array $fileToElementsMap, array $elementPropValues): array
    {
        $invalidFiles = [];

        // Создаем карту доступности файлов.
        $accessMap = array_fill_keys($fileIds, false);

        // Помечаем файлы с доступом.
        foreach ($fileToElementsMap as $elementId => $files) {
            if (isset($elementPropValues[$elementId]) &&
                $elementPropValues[$elementId] === $this->propValidValue) {
                foreach ($files as $file) {
                    if (isset($accessMap[$file])) {
                        $accessMap[$file] = true;
                    }
                }
            }
        }

        // Собираем недоступные файлы.
        foreach ($accessMap as $file => $hasAccess) {
            if (!$hasAccess) {
                $invalidFiles[] = $file;
            }
        }

        return $invalidFiles;
    }

    private function getNotFoundFiles(array $fileIds): array
    {
        // Все файлы не найдены.
        return $fileIds;
    }
}