Поиск задач

Заменой устаревшему CTasks::getList считаются:

  1. Верхнуровневый фасад для legacy-замены Bitrix\Tasks\Provider\TaskProvider.
  2. Текущий низкоуровневый провайдер Bitrix\Tasks\Provider\TaskList.
  3. Экспериментальный провайдер возвращающий доменные сущности Bitrix\Tasks\V2\Public\Provider\TaskProvider.

TaskProvider

Класс-провайдера получения результатов с обратной-совместимостью Bitrix\Tasks\Provider\TaskProvider схематично можно представить его так:

namespace Bitrix\Tasks\Provider;

class TaskProvider
{
    /**
     * @throws InvalidGroupByException
     * @throws CTaskAssertException
     * @throws TasksException
     */
    public function getList(
        mixed $arOrder = [],
        mixed $arFilter = [],
        mixed $arSelect = [],
        mixed $arParams = [],
        array $arGroup = []
    ): CDBResult;

    /**
     * @throws InvalidGroupByException
     * @throws CTaskAssertException
     * @throws TasksException
     */
    public function getCount(mixed $arFilter = [], mixed $arParams = [], mixed $arGroup = []): CDBResult;
}

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

Поскольку под капотом TaskProvider::getList и TaskProvider::getCount имеют схожее поведение, давайте заберем ключ arParams и посмотрим на примеры запросов.

В качестве arParams принимаются следующие ключи:

  • nPageTop (int) - ограничение по количеству выбираемых записей. Если не передан - игнорируется.
  • USER_ID (int) - текущий пользователь. По-умолчанию текущий пользователь, если не указан, но указан TARGET_USER_ID будет заполнено из TARGET_USER_ID.
  • TARGET_USER_ID (int) - пользователь, от лица которого выполняется действие. Если не указан будет аналогичен USER_ID
  • NAV_PARAMS (object) - структура описывающая постраничную навигацию: – ЛИБО должно быть заполнено __calculateTotalCount – ЛИБО должно быть заполнено nTopCount – ЛИБО должно быть заполнено nPageSize, iNumPage и не заполнено getTotalCount
  • MAKE_ACCESS_FILTER (bool|null) указывает на необходимость подключения фильтра по правам
  • CHECK_PERMISSIONS (string: Y|N) - нужно ли проверять права
  • FILTER_PARAMS (object), структура описывающая дополнительные настройки для проверки прав. – SEARCH_TASK_ONLY (string: Y|N) - указывает на то что необходимо искать только в поисковом индексе задачи и не искать в комментариях

Примечание при передаче CHECK_PERMISSIONS в arParams и в arFilter будут учитывать оба. Если хотя бы в одном из массивов он будет N то проверки прав не будет.

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

use Bitrix\Main\Loader;
use Bitrix\Tasks\Provider\TaskProvider;
use Throwable;

try {
    Loader::requireModule('tasks');

    $taskProvider = new TaskProvider();

    $filter = [
        '%TITLE' => 'тест'
    ];

    $resCount = $taskProvider->getCount(
        arFilter: $filter,
        arParams: ['CHECK_PERMISSIONS' => 'N']
    );

    if ($arTaskCount = $resCount->fetch()) {
        echo sprintf("Task with 'test' count: %d", $arTaskCount['CNT']);
    }
} catch (Throwable $e) {
    // @todo: log error instead of print error
    var_dump($e);
}

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

use Bitrix\Main\Loader;
use Bitrix\Tasks\Provider\TaskProvider;
use Throwable;

try {
    Loader::requireModule('tasks');

    $taskProvider = new TaskProvider();

    $filter = [
        '%TITLE' => 'тест'
    ];

    $resCount = $taskProvider->getList(
        arSelect: ["ID", "TITLE"],
        arFilter: $filter,
        arParams: ['CHECK_PERMISSIONS' => 'N']
    );

    /**
     * @var array $arTaskItem
     */
    while($arTaskItem = $resCount->fetch()) {
        echo "<pre>";
        var_dump($arTaskItem);
        echo "</pre>";
    }
} catch (Throwable $e) {
    // @todo: log error instead of print error
    var_dump($e);
}

TaskList

Гибкий низкоуровневый поиск по объекту фильтра Bitrix\Tasks\Provider\TaskList:

namespace Bitrix\Tasks\Provider;

use Bitrix\Tasks\Provider\Query\TaskQuery;

class TaskList
{
    /**
     * @param TaskQuery $query
     * @return array
     * @throws TaskListException
     */
    public function getList(TaskQuery $query): array;

    /**
     * @param TaskQuery $query
     * @return int
     * @throws Exception\InvalidSelectException
     * @throws Exception\UnexpectedTableException
     * @throws \Bitrix\Main\ArgumentException
     * @throws \Bitrix\Main\ObjectPropertyException
     * @throws \Bitrix\Main\SystemException
     */
    public function getCount(TaskQuery $query): int;
}    

Рассмотрим аналогичный ранее изученным примерам с использованием TaskList и TaskQuery:

use Bitrix\Main\Loader;
use Bitrix\Tasks\Provider\TaskList;
use Bitrix\Tasks\Provider\Query\TaskQuery;
use Throwable;

try {
    Loader::requireModule('tasks');

    $taskProvider = new TaskList();


    $taskQuery = new TaskQuery(userId: 0);

    $taskQuery->setSelect([
        'ID', 'TITLE'
    ]);

    $taskQuery->setWhere([
        '%TITLE' => 'тест'
    ]);

    $taskQuery->skipAccessCheck();

    $listElements = $taskProvider->getList($taskQuery);

    foreach ($listElements as $element) {
        echo "<pre>";
        var_dump($element);
        echo "</pre>";
    }
} catch (Throwable $e) {
    // @todo: log error instead of print error
    var_dump($e);
}

V2-exp TaskProvider

Экспериментальный провайдер реализует 3 публичных метода getList, getCount и get и схематично его можно представить его как:

namespace Bitrix\Tasks\V2\Public\Provider;

use Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListParams;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskParams;
use Bitrix\Tasks\V2\Internal\Entity\Task;
use Bitrix\Tasks\V2\Internal\Entity\TaskCollection;

class TaskProvider {
    public function getList(TaskListParams $taskListParams): TaskCollection;
    public function getCount(TaskListParams $taskListParams): int;
    public function get(TaskParams $taskParams): ?Task;
}

TaskProvider::get

Это метод отвечающий за получение конкретной задачи, когда вы знаете ее идентификатор. Поскольку модуль содержит значительное количество бизнес-логики, нельзя просто так взять идентификатор задачи и получить то что нужно без лишнего. Чтобы не перегружать метод дополнительными параметрами используется инкапсуляция опций в класс-параметр - Bitrix\Tasks\V2\Public\Provider\Params\TaskParams

Как выглядит сигнатура класса:

namespace Bitrix\Tasks\V2\Public\Provider\Params;

class TaskParams
{
    public function __construct(
        public readonly int $taskId,
        public readonly int $userId,
        public readonly bool $group = true,
        public readonly bool $flow = true,
        public readonly bool $stage = true,
        public readonly bool $members = true,
        public readonly bool $checkLists = true,
        public readonly bool $tags = true,
        public readonly bool $crm = true,
        public readonly bool $email = true,
        public readonly bool $subTasks = true,
        public readonly bool $relatedTasks = true,
        public readonly bool $gantt = true,
        public readonly bool $placements = true,
        public readonly bool $containsCommentFiles = true,
        public readonly bool $favorite = true,
        public readonly bool $options = true,
        public readonly bool $parameters = true,
        public readonly bool $results = true,
        public readonly bool $reminders = true,
        public readonly bool $userFields = true,
        public readonly bool $checkTaskAccess = true,
        public readonly bool $checkGroupAccess = true,
        public readonly bool $checkFlowAccess = true,
        public readonly bool $checkCrmAccess = true,
        public readonly bool $checkParentAccess = true,
        public readonly bool $view = false,
        public readonly bool $scenarios = true,
    ) {}
}

Давайте рассмотрим основные параметры:

  • taskId - идентификатор задачи, которую вы хотите получить
  • userId - идентификатор пользователя, из-под учетной записи которого вы хотите получить (может быть 0 для системных действий)
  • check*Access - учитывать доступ для указанного (в userId) пользователя – checkTaskAccess - к задаче – checkGroupAccess - к проекту/группе – checkFlowAccess - к потоку – checkCrmAccess - к связанной crm сущности – checkParentAccess - к родительской задаче
  • group, flow, stage, members, checkLists, tags, crm, email, subTasks, relatedTasks, gantt, placements, containsCommentFiles, favorite, options, parameters, results, reminders, userFields, view, scenarios - получать ли связанные с задачей сущности.

Если мы хотие получить задачу с ID:1, от лица пользователя ID: 2, при этом нам не нужны дополнительные параметры и пользователь явно никак в задаче не участвует, то код для получения такой задачи выглядит так:

use Bitrix\Tasks\V2\Public\Provider\TaskProvider;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskParams;

$taskProvider = new TaskProvider();

/**
 * @var Bitrix\Tasks\V2\Internal\Entity\Task|null
 */
$entityTask = $taskProvider->get(new TaskParams(
    taskId: 1,
    userId: 2,

    // Ignore permissions
    checkTaskAccess: false,
    checkGroupAccess: false,
    checkFlowAccess: false,
    checkCrmAccess: false,
    checkParentAccess: false,

    // Disable unused data
    group: false,
    flow: false,
    stage: false,
    members: false,
    checkLists: false,
    tags: false,
    crm: false,
    email: false,
    subTasks: false,
    relatedTasks: false,
    gantt: false,
    placements: false,
    containsCommentFiles: false,
    favorite: false,
    options: false,
    parameters: false,
    results: false,
    reminders: false,
    userFields: false,
    scenarios: false,
));

var_dump($entityTask);

На момент написания статьи существует и более короткий синтаксис:

use Bitrix\Tasks\V2\Public\Provider\TaskProvider;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskParams;

$taskProvider = new TaskProvider();

$taskParams = TaskParams::mapFromArray([
    "taskId" => 1,
    "userId" => 2
]);

$taskParams->checkTaskAccess = false;
$taskParams->checkGroupAccess = false;
$taskParams->checkFlowAccess = false;
$taskParams->checkCrmAccess = false;
$taskParams->checkParentAccess = false;

/**
 * @var Bitrix\Tasks\V2\Internal\Entity\Task|null
 */
$entityTask = $taskProvider->get($taskParams);

var_dump($entityTask);

Сам по себе метод TaskParams::mapFromArray достаточно полезный, потому что он позволяет динамически конфигурировать список запрашиваемых параметров.

TaskProvider::getList

Это метод отвечающий за получение неопределеного числа задачи, соответствующий критериям поиска. Подобно TaskProvider::get он так же имеет множество настроек инкапсулированных в Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListParams, однако в своем исполнении он несколько проще поискольку представляет из себя прокси с стандартизированными интерфейсами.

namespace Bitrix\Tasks\V2\Public\Provider\Params\TaskList;

use Bitrix\Main\Provider\Params\FilterInterface;
use Bitrix\Main\Provider\Params\GridParams;
use Bitrix\Main\Provider\Params\PagerInterface;
use Bitrix\Main\Provider\Params\SelectInterface;
use Bitrix\Main\Provider\Params\SortInterface;

class TaskListParams extends GridParams
{
    public function __construct(
        public int $userId,
        PagerInterface $pagination,
        ?FilterInterface $filter = null,
        ?SortInterface $sort = null,
        ?SelectInterface $select = null,
        public bool $skipAccessCheck = false,
    ) {}
}

Рассмотрим параметры метода:

  • userId - идентификатор пользователя, от лица которого осуществляется поиск.
  • pagination - параметры постраничной навигации для управления количеством элементов и сдвигом,
  • filter - параметры фильтрации,
  • sort - параметр сортировки,
  • select - параметр выбираемых полей
  • skipAccessCheck - нужно ли проверять права (все)

Поскольку FilterInterface, PagerInterface, SelectInterface, SortInterface являются лишь контрактами, в системе так же присутствует и реализация по-умолчанию которую можно использовать для наших нужд.

Интерфейс Реализация
Bitrix\Main\Provider\Params\PagerInterface Bitrix\Main\Provider\Params\Pager
Bitrix\Main\Provider\Params\FilterInterface Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListArrayFilter
Bitrix\Main\Provider\Params\SortInterface Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListSort
Bitrix\Main\Provider\Params\SelectInterface Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListSelect

Давайте выполним простую задачу: мы получим все названия задач, которые начинаются со слова “тест” и созданы в период между 10 мая 2026 и 13 мая 2026, отсортированные по дате создания (убывание), без учета прав, в количестве 10 штук.

use Bitrix\Main\Loader;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListParams;
use Bitrix\Main\ORM\Query\Filter\ConditionTree;
use Bitrix\Main\Type\DateTime;
use Bitrix\Main\Provider\Params\Pager;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListArrayFilter;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListSort;
use Bitrix\Tasks\V2\Public\Provider\Params\TaskList\TaskListSelect;
use Bitrix\Tasks\V2\Public\Provider\TaskProvider;
use Throwable;

try {
    Loader::requireModule('tasks');

    // Формируем параметры
    $params = new TaskListParams(
        userId: 1, // От чьего имени выполняем поиск
        pagination: new Pager(limit: 10, offset: 0),
        filter: new TaskListArrayFilter([
            'logic' => 'and',
            ['title', 'like', 'тест%'],
            ['createdDate', '>=', DateTime::createFromTimestamp(strtotime("10.06.2026 00:00:00"))],
            ['createdDate', '<=', DateTime::createFromTimestamp(strtotime("13.06.2026 00:00:00"))],
        ]),
        sort: new TaskListSort([
            'createdDate' => 'desc',
        ]),
        select: new TaskListSelect([
            'id', 'title'
        ]),
        skipAccessCheck: true
    );

    // Выполняем поиск
    $provider = new TaskProvider();
    $tasks = $provider->getList($params);

    foreach ($tasks as $task) {
        /**
         * @var $task \Bitrix\Tasks\V2\Internal\Entity\Task $task
         */
        echo "ID: {$task->getId()}\n";
        echo "Название: {$task->getTitle()}\n";
        echo "---\n";
    }

} catch (Throwable $e) {
    // @todo Use error log instead of var_dump
    var_dump($e);
}

Доступные поля

Доступность полей уточняйте в классе Bitrix\Tasks\V2\Public\Provider\Params\TaskList\FieldsEnum.