Когда загружаются файлы (к задаче или комментарию задачи) производится работа с модулем диска. Сразу после загрузки файлы попадают в раздел «Загруженные файлы» на диске:
При таком подходе при большом количестве пользователей и задач портал стремительно разрастается, что приводит к необходимости постоянно расширять доступное место.
В целом, каждый пользователь может зайти на свой диск, посмотреть каждый файл, используется ли он где, и если нет, то удалить его.


Но когда файлов очень много, это практически невыполнимая задача.
На текущий момент (версия 17.0.9):
При удалении комментария к задаче файлы стали удалятся
При удалении самой задачи – не удаляются ни файлы комментариев, ни файлы самой задачи.
Почему так происходит и как это исправить описано ниже.
Структура в базе
Для начала немного о том, какие сущности создаются в базе при прикреплении файла:
- Создается запись о самом файле в таблице b_file
- Создается запись о файле, как об объекте диска в таблице b_disk_object. Содержит ID файла из b_file, тип, хранилище (у какого пользователя расположен, в какой директории) и прочие поля.
- Создается запись в таблице b_disk_attached_object, в который хранится информация о том, к каким сущностям прикреплен объект диска. Например, если объект был прикреплен к 26 задаче, то основные поля записи будут выглядеть так:
- В задаче заполняется пользовательское поле UF_TASK_WEBDAV_FILES, которое содержит ID записей из таблицы b_disk_attached_object
Аналогичная ситуация происходит с прикреплением файлов к комментарию задачи. Таблица с пользовательскими полями - b_uts_forum_message
Удаление комментария к задаче.
Комментарии к задаче основаны на модуле форума. При удалении комментария:
- Внутри вызывается метод CAllForumMessage::Delete, который приводит к вызову удаления значений пользовательских полей для задачи $USER_FIELD_MANAGER->Delete("FORUM_MESSAGE", $ID);
- Наше пользовательское поле с файлами имеет класс Bitrix\Disk\Uf\FileUserType. Для этого класса вызывается метод ondelete
- Тот в свою очередь удаляет привязку объекта диска к комментарию (запись в b_disk_attached_object), а также если больше привязок не осталось, то удаляется и сам файл (в версии 16.0.13 удаления самого файла ещё нет)
Удаление задачи по факту осуществляется методом CTasks::Delete (после вызова CTaskItem::delete). Внутри есть вызов метода удаления темы форума (комментариев к задаче)

которая по сути является оберткой для: \CForumTopic::Delete($id);
Если посмотреть код этого метода, то будет видно, что события в нем никакие не вызываются, записи удаляются напрямую из базы.
$DB->Query("DELETE FR OM b_forum_message WH ERE TOPIC_ID = ".$ID."");
В результате чего и сами привязки в b_disk_attached_object и файлы остаются на месте (как для задачи, так и для комментариев).
Запись TODO внушает надежды, но неизвестно, когда это произойдет
Решение
В версии 17 достаточно выполнить следующие действия:
Для удаления файлов в комментариях к задаче:
- Регистрируем обработчик onBeforeTopicDelete, который вызывается до удаления темы форума. В нем выбираем все сообщения и сохраняем в статическую переменную
- Регистрируем обработчик onAfterTopicDelete, который вызывается после удаления темы форума, для каждого сообщения вызываем: $USER_FIELD_MANAGER->Delete("FORUM_MESSAGE", $messageId);
- Таким образом $USER_FIELD_MANAGER сам произведет все необходимые действия
Сами задачи из системы не удаляются. Удаляются различные привязки, но для самих задач ставится флаг ZOMBIE в таблице. Если не используется CRM или какие-то собственные значащие пользовательские поля, то для задачи так же повесить обработчик OnTaskDelete и внутри вызвать $USER_FIELD_MANAGER->Delete("TASKS_TASK", $id);
До 17 версии дела обстоят немного хуже. Поскольку при отсутствии привязок к сущностям удаление файла не производится (код для этого действия в метод \Bitrix\Disk\AttachedObject::delete был добавлен примерно в версиях 16.5 – 17)
Необходимо принудительно собирать список файлов, привязанных к сущности и после её удаления, удалять их.
Примерный код классов для версий 17 и ниже находится во вложении (local.rar)