• О ББК
  • Документация
  • Блог
  • Гитхаб

  • Введение

    Как работать с документацией

    В данном руководстве освещены главные особенности ББК и приведены примеры решения ряда некоторых задач. Но вы не найдёте здесь полного списка методов классов и, уж тем более, их описания. Для этого воспользуйтесь своей любимой средой разработки: все классы и методы ББК задокументированы (описания, параметры, возвращаемые результаты, исключения и т. д.), а их названия соответствуют сущностям, с которыми они взаимодействуют. Методы классов именованы в императивном стиле, а свойства — в декларативном.

    Документация, которую вы сейчас читаете, хранится в открытом доступе на «Гитхабе» в виде маркдаун-файлов. Если вы найдёте неточность или сможете дополнить её, пожалуйста, форкнитесь и сделайте пул-реквест.

    Установка

    ББК поставляются в виде модуля и набора компонентов. Обе составляющие можно установить вместе или по отдельности через «Композер». На «Бэксе» есть статья о работе с «Композером», почитайте её, если ещё не знакомы с этим замечательным менеджером пакетов.

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

    «Я всё знаю, скажите имя пакета!»

    Вот: bitrix-expert/bbc.

    «Подскажите, что делать?»

    1. Если «Композер» на вашем проекте ещё не установлен, самое время сделать это.

    curl -sS https://getcomposer.org/installer | php
    

    2. Пропишем зависимости для проекта: создайте в корне сайта composer.json следующего содержания.

    {
        "name": "mycompany/myproject",
        "description": "My first project with Composer",
        "type": "project",
        "require": {
            "bitrix-expert/bbc": "<=2"
        }
    }
    

    Это минимальное содержание файла. В name указывается имя разработчика и название проекта, в description краткое описание, и, самое интересное, зависимости (пакеты, которые необходимы для работы проекта) в require: здесь мы написали, что для работы проекта нам нужен пакет bitrix-expert/bbc не старше второй версии.

    3. В каталоге, где у вас расположились файлы composer.json и composer.phar, запустите установку пакетов.

    php composer.phar install
    

    Теперь вы можете подключать компоненты из зоны bbc и расширять их с помощью наследования. Или создавать компоненты «с нуля», отнаследовавшись от абстрактных классов, хранящихся в модуле bex.bbc (он тоже установился, т. к. его зависимость прописана в настройках компонентов). После релиза новой версии ББК вы можете обновить их у себя с помощью всего одной команды. Перейдите в каталог, в котором находятся файлы composer.json и composer.phar и выполните

    php composer.phar update
    

    Архитектура

    Базовые битриксовые компоненты построены на использовании исключений. Блок работы с исключениями (try … catch) располагается в методе executeComponent(), что охватывает практически все точки взаимодействия с логикой компонента (кроме метода onPrepareComponentParams()).

    Базовые компоненты предоставляют дочерним классам три основные точки входа, методы, которые можно переопределить для создания индивидуальной логики компонента:

    1. executeProlog() — выполняется в начале работы компонента, после подключения модулей, установки параметров и заголовков. Результаты метода не кешируются.
    2. executeMain() — основная логика компонента, все ключевые операции производятся в этом методе. Если в параметрах компонента передан ключ CACHE_TYPE не равный «N», результаты метода будут закешированы.
    3. executeEpilog() — выполняется после подключения шаблона компонента. Результаты не кешируются.

    Ключевой метод всех компонентов:

    <?php
    
    public function executeComponent()
    {
       try {
           $this->executeBasis();
       }
       catch (\Exception $e)
       {
           $this->catchException($e);
       }
    }
    

    Как видно из примера выше, в начале работы компонента вызывается метод executeBasis() — основа ББК — выполняющий последовательность действий по обеспечению работы компонента.

    Рассмотрим структуру базового компонента в порядке его выполнения.

    Метод Комментарий
    onPrepareComponent() Приведение параметров компонента.
    executeComponent() Основной метод компонента, реализующий инициализацию ББК и перехват исключений.
    includeModules() Подключение модулей, указанных в свойстве needModules класса компонента.
    Автоматическая проверка и приведение параметров, перечисленных в свойстве $checkParams класса компонента.
    checkParams() Предназначен для собственных проверок параметров компонента. Метод-болванка.
    Сброс буфера вывода и установка необходимых заголовков, если к компоненту обращается аякс-запрос.
    Выполнение прологов трейтов.
    executeProlog() Пролог компонента.
    executeMain() Основная логика компонента. Кешируется.
    returnDatas() Подключение шаблона компонента. По-умолчанию шаблон так же кешируется. Для отключения кеширования в классе компонента необходимо присвоить свойству cacheTemplate значенение false.
    Выполнение эпилогов трейтов.
    executeEpilog() Эпилог компонента.
    Остановка выполнения страницы, если к компоненту обращается аякс-запрос.

    Обработка исключений

    Как вы могли заметить из примеров выше, обработку выброшенных исключений осуществляет метод catchException($e): он принимает решение о том, какое сообщение об ошибке показать пользователю и нужно ли отправлять администратору сайта сообщение об этой ошибке.

    Вывод сообщений для обычных пользователей и администраторов различаются. Обычным пользователям выводится простое сообщение о том, что на сервере произошла ошибка (метод showExceptionUser()). Администраторы же получают полное сообщение об ошибке с дебагом выброшенного исключений (метод showExceptionAdmin()).

    Возможности

    Уведомление об ошибках

    ББК построен на использовании исключений, что позволяет контролировать ход выполнения компонента и в случае непредвиденной ситуации корректно её обрабатывать. Если компонент не может продолжать свою работу, нужно выбросить исключение (throw new Exception()), которое будет перехвачено и обработано.

    Перехваченные исключения ББК обрабатывает, выводит соответствующее сообщение пользователю и отправляет (если в этом есть необходимость) уведомление на почту администратора сайта.

    Методы обработки исключений находятся в трейте Common (подключается автоматически во всех компонентах ББК). Перечислим их.

    Метод Описание
    catchException() «Ловит» исключения, останавливает и отменяет кеширование, вызывает соответствующие методы для отображения сообщения об ошибке и отправке уведомления администратору
    showExceptionUser() Выводит сообщение об ошибке простому пользователю
    showExceptionAdmin() Выводит сообщение об ошибке и дебаг исключения, если пользователь является администратором
    sendNotifyException() Отправляет сообщение об ошибке на почту администратора сайта

    По-умолчанию сообщения об ошибках отправляются всегда, кроме случая, когда исключение выброшено по причине отсутствия данных (статус 404). Отключить отправку уведомлений можно двумя способами:

    1. Локально, установив в классе компонента свойство exceptionNotifier в значение false.
    2. Глобально для всех ББК, установив константу BX_EXC_NOTIFY в значение false. Сделать это можно, например, в файле init.php.

    Подключение модулей

    Воспользуйтесь свойством класса $this->needModules, если для работы компонента необходимо подключение модулей. Обратите внимание: если родительским классом не является Basis или BasisRouter, что бы не потерять родительские настройки, свойство необходимо дополнять, а не переназначать.

    Свойство $this->needModules является массивом, значения которого — коды модулей (iblock, seo, catalog и т. д.).

    <?php
    
    class TestChild extends TestParent
    {
        public function onPrepareComponentParams($params)
        {
            // Дополним свойство needModules, что бы не потерять настройки родительского класса
            // Подключаем модули веб-формы и поиск
            $this->needModules = array_unique(array_merge($this->needModules, ['form', 'search']));
    
            return parent::onPrepareComponentParams($params);
        }
    }
    

    Модули подключаются перед вызовом метода executeProlog(). В случае ошибки подключения модуля выбрасывается исключение.

    Параметры компонента

    Проверка и приведение

    ББК значительно упрощает и ускоряет работу с параметрами компонента. Если раньше нужно было вручную производить приведение типов и проверку переданных компоненту параметров, теперь ББК делает это самостоятельно, на основании свойства класса $checkParams.

    <?php
    
    class Test extends Basis
    {
        protected $checkParams = [
            'IBLOCK_TYPE' => ['type' => 'string'],
            'IBLOCK_ID' => ['type' => 'int'],
            'SECTION_ID' => ['type' => 'int', 'error' => false],
            'ELEMENT_ID' => ['type' => 'int', 'error' => '404']
        ];
    }
    

    $checkParams должен содержать массив, ключами которого являются коды параметров компонентов (которые нужно обработать), а значениями — массив с правилами обработки.

    В правилах обработки можно указывать:

    Если родительским классом не является Basis или BasisRouter, важно помнить, что в нём может (уже или в будущем) быть установлено свойство $checkParams. Поэтому, что бы не потерять родительские настройки, свойство необходимо дополнять, а не переназначать.

    <?php
    
    class TestChild extends TestParent
    {
        public function onPrepareComponentParams($params)
        {
            // Дополним свойство checkParams, что бы не потерять настройки родительского класса
            $this->checkParams += [
                'TITLE' => ['type' => 'string', 'error' => false]
            ];
    
            return parent::onPrepareComponentParams($params);
        }
    }
    

    Проверка и приведение параметров производится перед вызовом метода executeProlog().

    Наследование

    Работа с аяксом

    Немного теории. Аякс-запросы можно организовать двумя способами.

    Способ Минусы Плюсы
    Отдельный файл с подключением пролога и необходимого компонента Нужно дважды прописывать параметры компонента Более высокая скорость
    Та же самая страница, на которой размещён компонент при работе в обычном (не аяксовом) режиме При аякс-запросах исполняется вся страница Простота поддержки: параметры компонента настраиваются в одном месте

    В ББК реализована обработка аякс-запросов вторым способом: когда запрос посылается на ту же страницу, где размещён компонент в обычном режиме. Клиент должен послать запрос на страницу, передав идентификатор компонента, сообщающий системе, с каким компонентом нужно работать в данном запросе. Эти параметры доступны в шаблоне в переменной $arResult.

    <?php
    
    // Строка вида compid=p62vhc634vx2ja8 — её необходимо передавать вместе с GET-запросом
    $arResult['AJAX_REQUEST_PARAMS']
    
    // Если аякс-запрос осуществляется методом POST (например, отправка формы), идентификатор можно передать через скрытый инпут
    <input type="hidden" name="<?=$arResult['AJAX_PARAM_NAME']?>" value="<?=$arResult['AJAX_COMPONENT_ID']?>" />
    

    Что происходит при аякс-запросе?

    Когда компонент обнаруживает, что к нему осуществляется аякс-запрос, перед началом вывода (до вызова метода executeProlog()) и после подключения шаблона (после вызова метода executeEpilog()) он очищает буфер вывода. Таким образом, компонент вернёт только то, что будет выведено в его шаблоне (или методах executeProlog(), executeMain() и executeEpilog()).

    Кастомизация

    ББК довольно гибкие: они позволяют задавать свой идентификатор компонента, если в этом есть необходимость. Собственный айди устанавливается в параметре AJAX_COMPONENT_ID. Это может пригодится, когда мы хотим сформировать гиперссылку для аякса за пределами компонента (т. е., мы не имеем доступа к сгенерированному идентификатору).

    <?php
    
    $this->arParams['AJAX_COMPONENT_ID'] = 'my_test_id';
    

    Если вдруг параметр compid (compid=идентификато-компонента) где-то используется у вас на сайте, его название можно так же изменить.

    <?php
    
    $this->arParams['AJAX_PARAM_NAME'] = 'comp_ajax_id';
    

    По-умолчанию компоненты подключают в качестве шаблона файл template.php. Для аякс-запросов можно отдавать другой файл, находящийся в той же директории. Для этого достаточно указать имя файла (без расширения) в параметре AJAX_TEMPLATE_PAGE.

    <?php
    
    // Для аякс-запросов вместо template.php будет отдаваться ajax.php
    $this->arParams['AJAX_TEMPLATE_PAGE'] = 'ajax';
    

    Режимы

    В аяксе поддерживается два варианта ответов: обычный ХТМЛ и джейсон. Режим устанавливается в параметре компонента AJAX_TYPE.

    <?php
    
    $this->arParams['AJAX_TYPE'] = 'JSON';
    

    Перезагрузка заголовков

    В аякс-режиме после сброса буфера, но до вывода результатов исполнения компонента, ББК может перезагружать заголовки страницы (подключать ЯС, ЦСС и т. д.). По-умолчанию перезагрузка отключена. Для включения установите параметр AJAX_HEAD_RELOAD = Y.

    <?php
    
    $this->arParams['AJAX_HEAD_RELOAD'] = 'Y';
    

    Например

    Рассмотрим пример реализации типичного запроса данных по аяксу.

    1. Укажем в настройках компонента (параметр AJAX_TEMPLATE_PAGE), что в аякс-режиме необходимо работать с файлом шаблона ajax.php.

    2. Создадим шаблон для обычного режима (template.php).

    <h1>Я — простой шаблон</h1>
    
    <a href="#" class="js-ajax" data-ajax-params="<?=$arResult['AJAX_REQUEST_PARAMS']?>">Подгрузить данные аяксом</a>
    
    <div id="ajax-block">
    </div>
    

    3. И для аякс-режима (ajax.php).

    А я аякс!
    

    4. А также файл script.js, в котором с помощью «Джейквери» (подразумевается, что на сайте она установлена) будем осуществлять аякс-запрос.

    // script.js
    $(document).on('click', '.js-ajax', function() {
        $.ajax({
            data: $(this).data('ajaxParams'),
            success: function (response) {
                $('#ajax-block').html(response);
            }
        });
    });
    

    Готово. Теперь при клике на ссылку «Подгрузить данные аяксом» текущему компоненту будет отправляться аякс-запрос. Компонент вернёт ответ, используя в качестве шаблона файл ajax.php.

    Кеширование

    Компонент кешируется автоматически, если ему передать соответствующие параметры CACHE_TYPE и CACHE_TIME. Кешируется только метод executeMain() и шаблон. Если кеширование шаблона необходимо отключить, нужно установить свойство класса cacheTemplate в значение false.

    <?php
    
    class Test extends Basis
    {
        // Отключаем кеширование шаблона компонента. 
        // Метод executeMain() по-прежнему будет кешироваься 
        // (если установлены параметры CACHE_TYPE и CACHE_TIME)
        protected $cacheTemplate = false;
    }
    

    В ББК существует метод-хэлпер registerCacheTag($tag), который помечает кеш тегом. Пометив кеш, в будущем мы сможем сбросить его по тегу $tag с помощью \Bitrix\Main\Application::getInstance()->getTaggedCache()->clearByTag($tag).

    ББК может разделять кеш для разных групп пользователей. Для этого установите параметр компонента CACHE_GROUPS = Y. Вы так же можете добавить дополнительный идентификатор кеша с помощью метода addCacheAdditionalId($id).

    <?php
    
    // Пусть кеш реагирует на значение переменной $dependentVar
    $this->addCacheAdditionalId($dependentVar);
    

    Директорию хранения кеша можно задать в свойстве класса компонента $this->cacheDir. По-умолчанию «Битрикс» самостоятельно формирует путь.

    ББК предоставляет сл. методы-хэлперы для работы с кешом.

    Авт. Метод Описание
    + startCache() Подготовка параметров и начало кеширования. Возвращает true, если кеш существует и выполнять вычисления не нужно, в противном случае — false
    + writeCache() Завершает кеширование
    - abortCache() Отмена кеширования

    Поисковая оптимизация

    Мета-теги

    Короткие ссылки

    Хлебные крошки

    Управление контентом

    Постраничная навигация

    Генерация постраничной навигации реализуется трейтом Elements. Параметры компонента, влияющие на генерацию:

    Параметр Описание
    DISPLAY_TOP_PAGER Выводить строку в начале шаблона
    DISPLAY_BOTTOM_PAGER Выводить строку внизу шаблона
    ELEMENTS_COUNT Кол-во элементов на странице
    PAGER_DESC_NUMBERING Постраничная навигация в обратном порядке
    PAGER_SHOW_ALL Разрешить отображение всех записей на одной странице
    PAGER_SAVE_SESSION Записывать в сессию номер текущей страницы (по-умолчанию выкл.)
    PAGER_TITLE Заголовок для строки
    PAGER_TEMPLATE Шаблон строки постраничной навигации
    PAGER_SHOW_ALWAYS Показывать строку всегда (по-умолчанию выкл.)

    Вывод строки постраничной навигации в шаблоне производится через элемент массива arResult:

    <div>
        <?=$arResult['NAV_STRING']?>
    </div>
    

    «Эрмитаж»

    Функционал «Эрмитажа» реализуется трейтом Elements. Просто подключите его.

    Трейты

    Common

    Ручное подключение трейта Common не требуется, т. к. он подключается автоматически по всех компонентах ББК. Common обеспечивает обработку аякс-запросов, исключений, рассылает уведомления, осуществляет кеширование результатов, подключает модули, проверяет и приводит входящие параметры и делает многое другое.

    Наиболее часто используемые методы перечислены в таблице ниже.

    Авт. Метод Комментарий
    + includeModules() Подключает модули, переданные в свойстве needModules класса компонента.
    - startCache() Начинает кеширование результатов работы компонента.
    - writeCache() Завершает кеширование.
    - abortCache() Останавливает и отменяет кеширование.
    - addCacheAdditionalId() Добавление дополнительного идентификатора кеша.
    + returnDatas() Вывод результатов работы компонента. По-умолчанию — подключение шаблона компонента.
    - return404() Установка ХТТП-статуса 404 и константы ERROR_404 в значение Y.
    + catchException() Перехватчик исключения. Вызывается в блоке catch {} метода executeComponent().
    + sendNotifyException() Отправка уведомления на почту администратора о выброшенном исключении.
    + showExceptionUser() Отображении сообщения об ошибке при выброшенном исключении простому пользователю.
    + showExceptionAdmin() Отображении сообщения об ошибке при выброшенном исключении администратору сайта.
    - isAjax() Проверка, является ли текущее обращение к компоненту аякс-запросом.
    - registerCacheTag() Регистрация тега кеша.

    Elements

    Elements предоставляет функционал, наиболее часто используемый в компонентах, работающих с инфоблоками: обработка и подготовка параметров для выборки элементов инфоблока, генерация строки постраничной навигации и интерфейса «Эрмитажа», работа с глобальным фильтром. А так же СЕО-фичи: установка мета-тегов из настроек инфоблока и опен-граф тегов для соцсетей, генерация короткой ссылки и хлебных крошек.

    Для получения функционала трейта Elements нужно только подключить его:

    <?php
    
    namespase Myproject\Components;
    
    use Bex\Bbc\Basis;
    use Bex\Bbc\Traits\Elements;
    
    class Test extends Basis
    {
        use Elements;
    }
    

    Наиболее часто используемые методы перечислены в таблице ниже.

    Авт. Метод Комментарий
    + setNavStartParams() Установка параметров для постраничной навигации.
    - generateNav() Генерация строки постраничной навигации.
    - getShortLink() Возвращает короткую ссылку для страницы.
    - addGlobalFilters() Добавление дополнительных условий в глобальный фильтр.
    - addParamsGrouping() Добавление параметров группировки для гет-листа элементов.
    - addParamsNavStart() Добавление параметров постраничной навигации для гет-листа элементов.
    - addParamsSelected() Добавление выбираемых полей и свойств гет-листом элементов.
    - getParamsSort() Получение параметров сортировки для гет-листа элементов.
    - getParamsFilters() Получение фильтра для гет-листа элементов.
    - getParamsGrouping() Получение параметров группировки для гет-листа элементов.
    - getParamsNavStart() Получение параметров сортировки для гет-листа элементов.
    - getParamsSelected() Получение запрашиваемых полей и свойств для гет-листа элементов.
    - getProcessingMethod() Получение названия метода, с помощью которого будет производиться обработка результатов гет-листа.
    - prepareElementsResult() Метод-перехватчик для обработки результатов гет-листа элементов инфоблока. Вызывается на каждой итерации цикла. Должен вернуть массив, который будет помещён в свойство arResult класса компонента, либо false для пропуска итерации.

    Компоненты

    elements

    Компонент-пример.

    Комплексный компонент, обеспечивающий роутинг страниц.

    elements.list

    Компонент-пример.

    Выводит список элементов инфоблоков, устанавливает 404-й статус, генерирует строку постраничной навигации и предоставляет функционал трейта Elements.

    На каждой итерации обработки результатов выборки элементов инфоблока вызывается метод processingElementsResult(), в котором можно модифицировать записываемый элемент в массив arResult, либо вовсе пропустить итерацию. Для этого необходимо создать дочерний компонент.

    <?php
    
    namespase Myproject\Components;
    
    use Bex\Bbc\Components\ElementsList;
    
    class TestList extends ElementsList
    {
        protected function processingElementsResult($element)
        {
            // Зададим другое значение названию элемента
            $element['NAME'] = 'Тест'; 
    
            return $element;
    
            // Или пропустим итерацию, вернув «ложь»:
            return false;
        }
    }
    

    elements.detail

    Компонент-пример.

    Выводит элемент инфоблока, устанавливает 404-й статус и предоставляет функционал трейта Elements.

    На каждой итерации обработки результатов выборки элементов инфоблока вызывается метод processingElementsResult(), в котором можно модифицировать записываемый элемент в массив arResult. Для этого необходимо создать дочерний компонент.

    <?php
    
    namespase Myproject\Components;
    
    use Bex\Bbc\Components\ElementsDetail;
    
    class TestDetail extends ElementsDetail
    {
        protected function processingElementsResult($element)
        {
            // Зададим другое значение названию элемента
            $element['NAME'] = 'Тест'; 
    
            return $element;
        }
    }
    

    Примеры

    Рассмотрим несколько примеров, демонстрирующих некоторые возможности ББК. В качестве примера будем считать, что ББК размещён в зоне bbc, а наши тестовые — в зоне test.

    «Мой первый компонент»

    Разработаем тестовый компонент, производящий абстрактные операции (какие именно — не суть). Назовём его List.

    Создайте каталог компонента и разместите в нём файл class.php:

    <?php
    
    // Для разграничения и лаконичности имён классов добавим нэйм-спейс своих компонентов,
    // будто бы они располагаются в каталоге /local/components/supersite/
    namespace Myproject\Components;
    
    use Bex\Bbc\Basis;
    
    if(!defined('B_PROLOG_INCLUDED')||B_PROLOG_INCLUDED!==true)die();
    
    // Подключаем модуль, т. к. в нём находится класс для базового компонента
    if (!\Bitrix\Main\Loader::includeModule('bex.bbc')) return false;
    
    class List extends Basis
    {
    
    }
    

    Наш компонент отнаследован от компонента basis. Таким образом, мы получили базовый функционал ББК: кеширование, обработку аякс-запросов, проверку и приведение параметров и многое другое.

    Но сейчас компонент не производит никаких операций. Исправим это. У всех компонентов, отнаследованных от базовых, есть три точки входа (методы, которые можно переназначить для записи своей логики). Научим компонент складывать два числа, передаваемые ему через параметры (в данном примере создание конфигурационного файла .parameters.php не рассматривается).

    Сделаем так, что бы результат работы компонента кешировался, а не исполнялся на каждом хите. Для этого достаточно передать компоненту параметры CACHE_TYPE = A и CACHE_TIME > 0, после чего результаты работы метода executeMain() будут закешированы.

    Т. к. нет необходимости в выполнении этого алгоритма на каждом хите, его можно закешировать. ББК сделает это автоматически.

    <?php
    
    protected function executeMain()
    {
        $this->arResult['SUM'] = $this->arParams['NUM_1'] + $this->arParams['NUM_2'];
    }
    

    Теперь сделаем так, что бы на каждом хите генерировалось случайное число, которое можно будет вывести в шаблоне компонента. В нашем распоряжении есть два метода: executeProlog() и executeEpilog(). Последний выполняется уже после подключения шаблона и, соответственно, отпадает. Переназначим executeProlog() (он выполняется перед методом executeMain() и не кешируется):

    <?php
    
    protected function executeProlog()
    {
        $this->arResult['RANDOM_NUMBER'] = rand();
    }
    
    protected functions executeMain()
    {
        $this->arResult['SUM'] = $this->arParams['NUM_1'] + $this->arParams['NUM_2'];
    }
    

    Расширяем компоненты elements

    Кроме описанных выше способов внедрения в родительский класс, компоненты elements.list и elements.detail предоставляют дополнительный метод, вызываемый на каждой итерации цикла возвращаемых результатов — prepareElementsResult($element).

    Для чего это нужно? Рассмотрим пример с компонентом elements.list. Пусть на сайте выводится список элементов инфоблока, и есть необходимость в модификации результатов выборки из инфоблока.

    1. Добавим к каждому элементу инфоблока дополнительный ключ с абстрактными данными.
    2. Если описание элемента пустое, будем пропускать итерацию (это решается фильтрами в запросе данных, но для примера сойдёт).
    <?php
    
    namespace Myproject\Components;
    
    use Bex\Bbc\Components\ElementsList;
    
    if(!defined('B_PROLOG_INCLUDED')||B_PROLOG_INCLUDED!==true)die();
    
    \CBitrixComponent::includeComponentClass('bbc:elements.list');
    
    class NewsList extends ElementsList
    {
        // $element — это массив конкретного элемента инфоблока, возвращаемый в результате
        // выборки из инфоблока. Метод вызывается непосредственно перед записью жлемента
        // в $this->arResult['ELEMENTS']
        public function prepareElementsResult($element)
        {
            // Добавляем дополнительный ключ с данными в массив конкретного элемента
            $element['TEST_DATA'] = 'Какие-то данные…';
    
            if (!$element['DETAIL_TEXT'])
            {
                // Детального описания нет, пропустим итерацию.
                return false;
            }
    
            return $element;
        }
    }