Кейс Битрикс24: добавление файлов из задачи, прикрепленной к сделке, в пользовательское поле самой сделки
Сегодня рассмотрим решение реальной задачи, релизованное нашими специалистами и которое может быть полезно разработчикам, занимающимся доработкой и расширением функционала коробочной версии Битрикс24 под конкретные задачи.
Задача следующая: При сохранении привязанной к сделке задачи дублировать в сделку файлы, прикрепленные к этой задаче, в пользовательское поле с множественными значениями типа «Файл». Данная возможность должна быть доступна только пользователям определенного подразделения, назначенным ответственными в этой задаче.
Для решения данной задачи будем использовать события модуля Tasks:
- onTaskAdd – добавление задачи;
- onTaskUpdate – обновление задачи/
На первый взгляд зада несложная, нужно найти где хранятся файлы в задаче и передать их в сделку с помощью комбинации:
- CFile::MakeFileArray($ID_файла) - подготовить файлы;
- Передать файлы в сделку через метод Update.
Но, к сожалению, данный метод здесь бесполезен, так как в задаче файлы хранятся по другому принципу с использованием WebDav (по приниципу почтового сервера) в виде хешей наименований без расширения. Данная система служит для экономии места на ресурсе, так как при таком методе при загрузке нового файла, создается хеш и сравнивается с уже имеющимися хешами в системе и, если такой хеш уже имеется, то загрузки дубликата не происходит, а к задаче привязывается хеш файла. Соответственно при удалении файла из задачи, отвязывается только хеш. В то время как данные в пользовательских полях типа «Файл» хранятся по старой схеме.
Таким образом, нам нужно получить файл с диска и прикрепить его к сделке по классической схеме, предварительно проверив на дубликаты, с сохранением уже прикрепленных к сделке файлов, так как при обновлении поля, предыдущие файлы удаляются.
Для получения данных из WebDav нам приходит на помощь D7 и работа с диском \Bitrix\Disk\Driver и, немного покопавшись в официальной документации и по сети, мы пришли к следующему варианту:
$userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
$userFieldManager->loadBatchAttachedObject($files);
foreach ($files as $attachedId)
{
//...
$attachedObject = $userFieldManager->getAttachedObjectById($attachedId);
//...
}
Здесь:
- $files – массив идентификаторов в системе WebDav пришедший от задачи;
- $attachedObject – возвращает объект с информацией и методами о привязанном файле в системе WebDav. В $attachedObject есть функция getFileId() которая возвращает идентификатор файла в классическом варианте удобоваримом классу CFile. Имея данный идентификатор можно использовать классический метод обработки CFile::MakeFileArray() плюс проверка на наличие уже такого файла в сделке.
Получаем код:
$userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
$userFieldManager->loadBatchAttachedObject($files);
foreach ($files as $attachedId)
{
$key = false;
$attachedObject = $userFieldManager->getAttachedObjectById($attachedId);
if(sizeof($arFields['UF_CRM_1492767878']) > 0)
{
$key = array_search($attachedObject->getName(), array_column($arFileInfo, 'ORIGINAL_NAME'));
}
if ($key === false) {
$arFields['UF_CRM_1492767878'][] = CFile::MakeFileArray($attachedObject->getFileId());
}
}
Теперь полученное поле необходимо записать в сделку:
if(isset($arFields['UF_CRM_1492767878']) && sizeof($arFields['UF_CRM_1492767878']) > 0) {
$crm = new CCrmDeal(false);
$crm->Update($dealId, $arFields, true, true, ['DISABLE_USER_FIELD_CHECK' => true, 'REGISTER_SONET_EVENT' => true]);
}
Нам так же необходимо сохранить уже полученные файлы. Мы сделали это так:
$obDeal = CCrmDeal::GetList([], ['ID' => $dealId], ['*', 'UF_*']);
$deal = $obDeal->GetNext();
$dealFiles = $deal['UF_CRM_1492767878'];
if(sizeof($dealFiles) > 0)
{
foreach ($dealFiles as $f)
{
$arFields['UF_CRM_1492767878'][] = $f;
$arFileInfo[] = CFile::GetByID($f)->GetNext();
}
}
Здесь:
$arFileInfo – содержит массив существующих уже в сделке файлов. Он нам потребуется для проверки по имени файла. Так же еще добавлена проверка по подразделению.
Итоговый вариант всего обработчика:
AddEventHandler("tasks", "OnTaskAdd", ["TaskEvent", "OnTaskAddHandler"]);
AddEventHandler("tasks", "OnTaskUpdate", ["TaskEvent", "OnTaskUpdateHandler"]);
class TaskEvent {
function OnTaskAddHandler($ID)
{
self::syncDealFiles($ID);
}
function OnTaskUpdateHandler($ID)
{
self::syncDealFiles($ID);
}
private static function syncDealFiles($ID)
{
CModule::IncludeModule('tasks');
CModule::IncludeModule('crm');
$obTask = CTasks::GetList([], ['ID' => $ID], ['*', 'UF_*']);
$task = $obTask->GetNext();
list(, $dealId) = explode('_', array_shift($task['UF_CRM_TASK']));
$files = $task['UF_TASK_WEBDAV_FILES']; $arFileInfo = [];
$user = CUser::GetList(($by = 'id'), ($order = 'asc'), ['ID' => $task['RESPONSIBLE_ID'], 'UF_DEPARTMENT' => 28], ['SELECT' => ['*', 'UF_*']])->GetNext();
if (is_numeric($dealId) && sizeof($files) > 0 && isset($user['ID']))
{
$obDeal = CCrmDeal::GetList([], ['ID' => $dealId], ['*', 'UF_*']);
$deal = $obDeal->GetNext();
$dealFiles = $deal['UF_CRM_1492767878'];
if(sizeof($dealFiles) > 0)
{
foreach ($dealFiles as $f)
{
$arFields['UF_CRM_1492767878'][] = $f;
$arFileInfo[] = CFile::GetByID($f)->GetNext();
}
}
$userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
$userFieldManager->loadBatchAttachedObject($files);
foreach ($files as $attachedId)
{
$key = false;
$attachedObject = $userFieldManager->getAttachedObjectById($attachedId);
if(sizeof($arFields['UF_CRM_1492767878']) > 0)
{
$key = array_search($attachedObject->getName(), array_column($arFileInfo, 'ORIGINAL_NAME'));
}
if ($key === false)
{
$arFields['UF_CRM_1492767878'][] = CFile::MakeFileArray($attachedObject->getFileId());
}
}
if(isset($arFields['UF_CRM_1492767878']) && sizeof($arFields['UF_CRM_1492767878']) > 0)
{
$crm = new CCrmDeal(false);
$crm->Update($dealId, $arFields, true, true, ['DISABLE_USER_FIELD_CHECK' => true, 'REGISTER_SONET_EVENT' => true]);
}
}
}
}