Модули коробки
Задачи
Рабочая справка по PHP API модуля tasks в коробочном Bitrix24: TaskTable, участники, комментарии через чат задачи, старые форумные комментарии, логи, избранное и затраченное время.
Для чтения задач можно использовать D7-таблицы. Комментарии надо разделять:
в старой карточке задачи они были связаны с форумом, а в новой карточке задачи обсуждение
перенесено в чат. Поэтому основной рабочий вариант для новых задач — получить чат задачи
и работать с сообщениями через модуль im.
Общее понимание
Модуль tasks содержит саму задачу и связанные таблицы: участников,
чек-листы, теги, логи, избранное, таймеры и другие данные.
Подключение модуля
<?php
use Bitrix\Main\Loader;
Loader::includeModule('tasks');
Если нужно работать с новым чатом задачи, дополнительно подключается модуль
im.
<?php
use Bitrix\Main\Loader;
/**
* Подключает модули для задач и чатов.
*/
function requireTaskChatModules(): void
{
$module_ids = [
'tasks',
'im',
];
foreach ($module_ids as $module_id) {
if (!Loader::includeModule($module_id)) {
throw new \RuntimeException('Не удалось подключить модуль: ' . $module_id);
}
}
}
requireTaskChatModules(); TaskTable и связанные таблицы
| Класс | Что хранит |
|---|---|
\Bitrix\Tasks\TaskTable | Основная сущность задачи. |
\Bitrix\Tasks\Internals\Task\MemberTable | Участники задачи. |
\Bitrix\Tasks\Internals\Task\LogTable | Логи изменений задачи. |
\Bitrix\Tasks\Internals\Task\FavoriteTable | Избранные задачи пользователя. |
\Bitrix\Tasks\Internals\Task\ElapsedTimeTable | Затраченное время. |
\Bitrix\Tasks\Internals\Task\RelatedTable | Зависимости задач. |
\Bitrix\Tasks\Internals\Task\ReminderTable | Напоминания по задачам. |
\Bitrix\Tasks\Internals\Task\TagTable | Теги задач. |
\Bitrix\Tasks\Internals\Task\TimerTable | Таймеры задач. |
\Bitrix\Im\Model\ChatTable | Чаты, включая чат новой задачи. |
\Bitrix\Im\Model\MessageTable | Сообщения чата задачи. |
Карта методов
| Метод или класс | Что делает | Когда использовать |
|---|---|---|
TaskTable::getList() | Получает задачи. | Списки, отчёты, проверки по статусу и ответственному. |
MemberTable::getList() | Получает участников задачи. | Когда нужны наблюдатели, соисполнители и роли. |
ChatTable::getList() | Получает чат задачи по ENTITY_TYPE и ENTITY_ID. | Найти CHAT_ID новой задачи из PHP. |
\CIMChat::AddMessage() | Добавляет сообщение в чат. | PHP-комментарий в новую карточку задачи. |
MessageTable::getList() | Получает сообщения чата. | Чтение сообщений новой карточки задачи из коробочного PHP. |
LogTable::getList() | Получает историю изменений задачи. | Диагностика изменения статуса, срока, ответственного. |
FavoriteTable::getList() | Проверяет избранные задачи. | Пользовательские списки и интерфейсные доработки. |
ElapsedTimeTable::getList() | Получает затраченное время. | Отчёты по трудозатратам. |
RelatedTable::getList() | Получает связи и зависимости задач. | Проверка предшествующих и связанных задач. |
ReminderTable::getList() | Получает напоминания. | Диагностика уведомлений по задаче. |
Comment::add() | Добавляет старый форумный комментарий. | Только для старых задач и старого механизма комментариев. |
ORM или старые классы
ORM хорошо подходит для чтения и отчётов. Если нужно создать или изменить задачу так, чтобы сработали права, уведомления и бизнес-логика, лучше отдельно проверить API конкретной версии коробки.
В старом коде часто встречаются CTasks, CTaskItem,
CTaskCommentItem. Для чтения новых задач и связанных данных чаще удобнее
D7-таблицы, а для обсуждения новой задачи — чат.
Задачи
Базовое чтение задач через ORM.
Получить задачу
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\TaskTable;
Loader::includeModule('tasks');
/**
* Получает задачу по ID.
*/
function fetchTaskById(int $task_id): array
{
if ($task_id <= 0) {
return [];
}
$task = TaskTable::getList([
'select' => [
'ID',
'TITLE',
'STATUS',
'RESPONSIBLE_ID',
'CREATED_BY',
'CREATED_DATE',
'DEADLINE',
],
'filter' => [
'=ID' => $task_id,
],
'limit' => 1,
])->fetch();
return is_array($task) ? $task : [];
}
$task = fetchTaskById($task_id);
print_r($task); Получить список задач
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\TaskTable;
Loader::includeModule('tasks');
const TASK_LIMIT = 100;
/**
* Получает задачи ответственного пользователя.
*/
function fetchUserTasks(int $responsible_id): array
{
if ($responsible_id <= 0) {
return [];
}
return TaskTable::getList([
'select' => [
'ID',
'TITLE',
'STATUS',
'RESPONSIBLE_ID',
'CREATED_BY',
'DEADLINE',
],
'filter' => [
'=RESPONSIBLE_ID' => $responsible_id,
],
'order' => [
'ID' => 'DESC',
],
'limit' => TASK_LIMIT,
])->fetchAll();
}
$tasks = fetchUserTasks($responsible_id);
print_r($tasks); Задачи по статусу
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\TaskTable;
Loader::includeModule('tasks');
const TASK_LIMIT = 100;
/**
* Получает задачи пользователя по статусу.
*/
function fetchUserTasksByStatus(int $responsible_id, int $status): array
{
if ($responsible_id <= 0) {
return [];
}
return TaskTable::getList([
'select' => [
'ID',
'TITLE',
'STATUS',
'RESPONSIBLE_ID',
'CREATED_BY',
'DEADLINE',
'CREATED_DATE',
'CHANGED_DATE',
'CLOSED_DATE',
],
'filter' => [
'=RESPONSIBLE_ID' => $responsible_id,
'=STATUS' => $status,
],
'order' => [
'DEADLINE' => 'ASC',
'ID' => 'DESC',
],
'limit' => TASK_LIMIT,
])->fetchAll();
}
$tasks = fetchUserTasksByStatus($responsible_id, $status);
print_r($tasks); Участники задачи
Участники задачи хранятся отдельно. В зависимости от роли это могут быть ответственные, соисполнители, наблюдатели и другие участники.
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\Internals\Task\MemberTable;
Loader::includeModule('tasks');
/**
* Получает участников задачи.
*/
function fetchTaskMembers(int $task_id): array
{
if ($task_id <= 0) {
return [];
}
return MemberTable::getList([
'select' => [
'TASK_ID',
'USER_ID',
'TYPE',
],
'filter' => [
'=TASK_ID' => $task_id,
],
'order' => [
'USER_ID' => 'ASC',
],
])->fetchAll();
}
$members = fetchTaskMembers($task_id);
print_r($members); Участники по ролям
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\Internals\Task\MemberTable;
Loader::includeModule('tasks');
/**
* Получает участников задачи по ролям.
*/
function fetchTaskMembersByType(int $task_id): array
{
if ($task_id <= 0) {
return [];
}
$members_by_type = [];
$member_result = MemberTable::getList([
'select' => [
'TASK_ID',
'USER_ID',
'TYPE',
],
'filter' => [
'=TASK_ID' => $task_id,
],
'order' => [
'TYPE' => 'ASC',
'USER_ID' => 'ASC',
],
]);
while ($member = $member_result->fetch()) {
$type = (string) $member['TYPE'];
if (!isset($members_by_type[$type])) {
$members_by_type[$type] = [];
}
$members_by_type[$type][] = (int) $member['USER_ID'];
}
return $members_by_type;
}
$members_by_type = fetchTaskMembersByType($task_id);
print_r($members_by_type); Значения ролей лучше сверять на конкретной версии и реальных данных задачи.
Комментарии через PHP
В новой карточке задачи комментарий для пользователя — это сообщение в чате задачи.
Рабочий коробочный вариант через модуль im:
Получить CHAT_ID задачи
Для новой карточки задачи чат связан с сущностью TASKS_TASK, а
ENTITY_ID равен ID задачи. В старой карточке может встречаться тип
TASKS.
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\TaskTable;
use Bitrix\Im\Model\ChatTable;
Loader::includeModule('tasks');
Loader::includeModule('im');
const TASK_CHAT_ENTITY_TYPE = 'TASKS_TASK';
const OLD_TASK_CHAT_ENTITY_TYPE = 'TASKS';
/**
* Проверяет наличие поля в TaskTable.
*/
function hasTaskField(string $field_id): bool
{
try {
TaskTable::getEntity()->getField($field_id);
return true;
} catch (\Throwable $exception) {
return false;
}
}
/**
* Получает CHAT_ID задачи из TaskTable, если поле доступно на версии коробки.
*/
function fetchTaskChatIdFromTaskTable(int $task_id): int
{
if ($task_id <= 0 || !hasTaskField('CHAT_ID')) {
return 0;
}
$task = TaskTable::getList([
'select' => [
'ID',
'CHAT_ID',
],
'filter' => [
'=ID' => $task_id,
],
'limit' => 1,
])->fetch();
return is_array($task) ? (int) ($task['CHAT_ID'] ?? 0) : 0;
}
/**
* Получает CHAT_ID задачи через таблицу чатов.
*/
function fetchTaskChatIdFromChatTable(int $task_id, string $entity_type): int
{
if ($task_id <= 0 || $entity_type === '') {
return 0;
}
$chat = ChatTable::getList([
'select' => [
'ID',
'ENTITY_TYPE',
'ENTITY_ID',
],
'filter' => [
'=ENTITY_TYPE' => $entity_type,
'=ENTITY_ID' => (string) $task_id,
],
'order' => [
'ID' => 'DESC',
],
'limit' => 1,
])->fetch();
return is_array($chat) ? (int) ($chat['ID'] ?? 0) : 0;
}
/**
* Получает CHAT_ID задачи несколькими способами.
*/
function fetchTaskChatId(int $task_id): int
{
$chat_id = fetchTaskChatIdFromTaskTable($task_id);
if ($chat_id > 0) {
return $chat_id;
}
$chat_id = fetchTaskChatIdFromChatTable($task_id, TASK_CHAT_ENTITY_TYPE);
if ($chat_id > 0) {
return $chat_id;
}
return fetchTaskChatIdFromChatTable($task_id, OLD_TASK_CHAT_ENTITY_TYPE);
}
$chat_id = fetchTaskChatId($task_id);
echo $chat_id;
Если CHAT_ID не находится, сначала проверь, создан ли чат у задачи и
какие значения лежат в ENTITY_TYPE и ENTITY_ID в таблице
чатов на твоей версии коробки.
Добавить сообщение в чат задачи
Это основной PHP-вариант для «комментария» в новой карточке задачи: найти чат задачи и отправить в него сообщение от нужного пользователя.
<?php
use Bitrix\Main\Loader;
Loader::includeModule('tasks');
Loader::includeModule('im');
/**
* Формирует DIALOG_ID обычного чата.
*/
function buildChatDialogId(int $chat_id): string
{
return 'chat' . $chat_id;
}
/**
* Добавляет сообщение в чат задачи.
*/
function addTaskChatMessage(int $task_id, int $author_id, string $message): array
{
if ($task_id <= 0 || $author_id <= 0 || trim($message) === '') {
return [
'is_success' => false,
'message_id' => 0,
'error_messages' => ['Не заполнены данные сообщения'],
];
}
$chat_id = fetchTaskChatId($task_id);
if ($chat_id <= 0) {
return [
'is_success' => false,
'message_id' => 0,
'error_messages' => ['Чат задачи не найден'],
];
}
$message_id = \CIMChat::AddMessage([
'DIALOG_ID' => buildChatDialogId($chat_id),
'TO_CHAT_ID' => $chat_id,
'FROM_USER_ID' => $author_id,
'MESSAGE' => $message,
'SYSTEM' => 'N',
'URL_PREVIEW' => 'Y',
]);
return [
'is_success' => (int) $message_id > 0,
'message_id' => (int) $message_id,
'chat_id' => $chat_id,
'error_messages' => (int) $message_id > 0 ? [] : ['Сообщение не добавлено'],
];
}
$result = addTaskChatMessage(
$task_id,
$author_id,
'Комментарий в чат задачи из PHP'
);
print_r($result);
Автор сообщения должен иметь доступ к чату. Если сообщение не добавляется, проверь:
CHAT_ID, участие пользователя в чате, права на задачу и наличие модуля
im.
Получить сообщения чата
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\MessageTable;
Loader::includeModule('tasks');
Loader::includeModule('im');
/**
* Получает последние сообщения чата задачи.
*/
function fetchTaskChatMessages(int $task_id, int $limit = 50): array
{
$chat_id = fetchTaskChatId($task_id);
if ($chat_id <= 0) {
return [];
}
$messages = [];
$message_result = MessageTable::getList([
'select' => [
'ID',
'CHAT_ID',
'AUTHOR_ID',
'MESSAGE',
'DATE_CREATE',
'NOTIFY_EVENT',
],
'filter' => [
'=CHAT_ID' => $chat_id,
],
'order' => [
'ID' => 'DESC',
],
'limit' => $limit,
]);
while ($message = $message_result->fetch()) {
$messages[] = $message;
}
return $messages;
}
$messages = fetchTaskChatMessages($task_id, 50);
print_r($messages);
В выборку могут попадать системные сообщения. Их можно дополнительно отфильтровать
по AUTHOR_ID, NOTIFY_EVENT или содержимому, если для задачи
нужны только пользовательские комментарии.
Получить последнее сообщение
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\MessageTable;
Loader::includeModule('tasks');
Loader::includeModule('im');
/**
* Получает последнее сообщение чата задачи.
*/
function fetchLastTaskChatMessage(int $task_id): array
{
$chat_id = fetchTaskChatId($task_id);
if ($chat_id <= 0) {
return [];
}
$message = MessageTable::getList([
'select' => [
'ID',
'CHAT_ID',
'AUTHOR_ID',
'MESSAGE',
'DATE_CREATE',
'NOTIFY_EVENT',
],
'filter' => [
'=CHAT_ID' => $chat_id,
],
'order' => [
'ID' => 'DESC',
],
'limit' => 1,
])->fetch();
return is_array($message) ? $message : [];
}
$message = fetchLastTaskChatMessage($task_id);
print_r($message); Старые комментарии
Этот блок нужен только для старых задач и старого механизма комментариев через форум. Для новой карточки задачи используй чат задачи.
Форумный вариант для старых задач
Старые комментарии задач связаны с форумным модулем. Для добавления такого комментария
в старом механизме встречается
\Bitrix\Tasks\Integration\Forum\Task\Comment::add().
Для новых задач этот вариант не нужно использовать как основной: сообщение может не попасть туда, где пользователь ожидает его увидеть в новой карточке. Для новых задач используй чат.
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\Integration\Forum\Task\Comment;
Loader::includeModule('tasks');
Loader::includeModule('forum');
/**
* Добавляет старый форумный комментарий к задаче.
*/
function addOldTaskForumComment(int $task_id, int $author_id, string $message): array
{
if ($task_id <= 0 || $author_id <= 0 || $message === '') {
return [
'is_success' => false,
'comment_id' => 0,
'error_messages' => ['Не заполнены данные комментария'],
];
}
$result = Comment::add($task_id, [
'AUTHOR_ID' => $author_id,
'POST_MESSAGE' => $message,
]);
if (!$result->isSuccess()) {
return [
'is_success' => false,
'comment_id' => 0,
'error_messages' => $result->getErrorMessages(),
];
}
$data = $result->getData();
return [
'is_success' => true,
'comment_id' => (int) ($data['ID'] ?? 0),
'error_messages' => [],
];
}
$result = addOldTaskForumComment($task_id, $author_id, 'Старый форумный комментарий');
print_r($result); Изменить и удалить старый комментарий
В новом механизме комментарии стали сообщениями чата. Поэтому изменение и удаление старых комментариев через форумный API нужно считать совместимостью со старой карточкой, а не универсальным способом для новых задач.
<?php
use Bitrix\Main\Loader;
use Bitrix\Tasks\Integration\Forum\Task\Comment;
Loader::includeModule('tasks');
Loader::includeModule('forum');
/**
* Изменяет старый форумный комментарий задачи.
*/
function updateOldTaskForumComment(int $task_id, int $comment_id, int $author_id, string $message): array
{
if ($task_id <= 0 || $comment_id <= 0 || $author_id <= 0 || $message === '') {
return [
'is_success' => false,
'error_messages' => ['Не заполнены данные комментария'],
];
}
$result = Comment::update($task_id, $comment_id, [
'AUTHOR_ID' => $author_id,
'POST_MESSAGE' => $message,
]);
return [
'is_success' => $result->isSuccess(),
'error_messages' => $result->getErrorMessages(),
];
}
/**
* Удаляет старый форумный комментарий задачи.
*/
function deleteOldTaskForumComment(int $task_id, int $comment_id, int $author_id): array
{
if ($task_id <= 0 || $comment_id <= 0 || $author_id <= 0) {
return [
'is_success' => false,
'error_messages' => ['Не заполнены данные комментария'],
];
}
$result = Comment::delete($task_id, $comment_id, [
'AUTHOR_ID' => $author_id,
]);
return [
'is_success' => $result->isSuccess(),
'error_messages' => $result->getErrorMessages(),
];
} REST для справки
Основной упор этой статьи — PHP в коробке. REST оставлен как справочная информация, чтобы сопоставлять PHP-подход с публичными методами.
Отправить сообщение REST
Для новой карточки задачи основной REST-метод отправки сообщения —
tasks.task.chat.message.send. Он принимает ID задачи и текст сообщения.
/**
* Готовит payload для REST-метода tasks.task.chat.message.send.
*/
function buildTaskChatMessagePayload(int $task_id, string $text): array
{
if ($task_id <= 0 || $text === '') {
return [];
}
return [
'fields' => [
'taskId' => $task_id,
'text' => $text,
],
];
}
$payload = buildTaskChatMessagePayload(
$task_id,
'Комментарий в новый чат задачи'
);
print_r($payload); Получить чат REST
Для новой карточки задачи используется ENTITY_TYPE = TASKS_TASK. Для
старой карточки в REST-документации указан тип TASKS.
/**
* Готовит payload для REST-метода im.chat.get по новой задаче.
*/
function buildNewTaskChatGetPayload(int $task_id): array
{
if ($task_id <= 0) {
return [];
}
return [
'ENTITY_TYPE' => 'TASKS_TASK',
'ENTITY_ID' => (string) $task_id,
];
}
/**
* Готовит payload для REST-метода im.chat.get по старой задаче.
*/
function buildOldTaskChatGetPayload(int $task_id): array
{
if ($task_id <= 0) {
return [];
}
return [
'ENTITY_TYPE' => 'TASKS',
'ENTITY_ID' => (string) $task_id,
];
}
$payload = buildNewTaskChatGetPayload($task_id);
print_r($payload); Получить сообщения REST
Для чтения сообщений чата в REST используется im.dialog.messages.get.
Для обычного чата DIALOG_ID передаётся в формате chat123,
где 123 — ID чата.
/**
* Формирует DIALOG_ID для обычного чата.
*/
function buildChatDialogIdForRest(int $chat_id): string
{
return 'chat' . $chat_id;
}
/**
* Готовит payload для REST-метода im.dialog.messages.get.
*/
function buildTaskChatMessagesPayload(int $chat_id, int $limit = 50): array
{
if ($chat_id <= 0) {
return [];
}
return [
'DIALOG_ID' => buildChatDialogIdForRest($chat_id),
'LIMIT' => $limit,
];
}
$payload = buildTaskChatMessagesPayload($chat_id, 50);
print_r($payload); Источники
- Официальная документация: модуль tasks
- Официальная документация: TaskTable
- Официальная документация: связанные таблицы задач
- REST: New Task Card — изменения в комментариях
- REST 3.0: tasks.task.chat.message.send
- REST: im.chat.get
- REST: im.dialog.messages.get
- Справочник исходников: CIMChat
- Справочник исходников: TaskService.php
- Старый вариант: Comment::add
- Официальная документация: LogTable
- Официальная документация: ElapsedTimeTable
Старые комментарии и новый чат
В старой карточке задачи комментарии были связаны с форумным модулем. Поэтому в старом коде можно встретить
\Bitrix\Tasks\Integration\Forum\Task\Comment,CTaskCommentItemи форумные таблицы.В новой карточке задачи обсуждение перенесено в чат. Для пользовательского сценария «добавить комментарий к задаче» в коробочном PHP удобнее работать с чатом задачи: найти
CHAT_IDи добавить сообщение через\CIMChat::AddMessage().\Bitrix\Tasks\Integration\Forum\Task\Commentи форумный механизм.ChatTable,MessageTable,\CIMChat::AddMessage().\Bitrix\Im\Model\MessageTableпоCHAT_ID.\CIMChat::AddMessage()сDIALOG_IDилиTO_CHAT_ID.tasks.task.chat.message.send,im.chat.get,im.dialog.messages.get.