Передача файлов из форм на сайте в Битрикс 24

18 июля, 2020 11:44
Admin
31 июля, 2020 21:38
bitrix24-files

Поскольку по умолчанию при интеграции форм на сайте с CRM Битрикс 24 нет возможности передачи файлов. В данной статье я предлагаю одно из возможных решений реализации данной возможности без необходимости модификации файлов на стороне портала Битрикс 24. Этот способ может быть особенно актуален для тех, кто использует облачную версию Битрикс 24, так как изменение файлов исходного кода в данном случае запрещено.

Также стоит отметить, что данный вариант работает на основе стандартного модуля «Веб-формы». Если вы не используете на сайте данный модуль для работы с формами, данный вариант вам не подойдет.

Пример исходного кода для вставки на вашем сайте

Вставляем код приведенный ниже в файл init.php на сайт под управлением 1С-Битрикс:

<?php
use Bitrix\Main;
use Bitrix\Main\Context;
Main\EventManager::getInstance()->addEventHandler(
    'form',
    'onAfterResultAdd',
    ["ExtCrmExchange", "handler"]
);

// Класс отвечает за обновление полей результатов форм, которые передаются в CRM
class ExtCrmExchange
{
    /**
     * @var ExtCrmExchange
     */
    private static $instance;

    /**
     * @var CFormResult
     */
    private $cFormResult;

    /**
     * ID веб форм, которые будут обновляться
     *
     * @var array
     */
    protected $formIds = [3 , 4, 5];

    /**
     * Подключаемые модули
     *
     * @var array
     */
    private $modules = ["form"];

    /**
     * Обработчик. Срабатывает после добавления нового результата веб-формы
     *
     * @param integer|string $webFormId
     * @param integer|string $resultId
     *
     * @return void
     */
    public function handler($webFormId, $resultId)
    {
        // Так как при вызове метода не создается объект класса создаем сами
        $exchange = self::getInstance();

        if($exchange->includeModules()) {
            // Создаем объект класса CFormResult
            $exchange->createForm();

            $needleId = intval($webFormId);
            if(in_array($needleId, $exchange->formIds, true)) {
                $fieldsRes = $exchange->cFormResult->GetDataByID($resultId, [], $result, $answer);

                $arrayUpdate = []; // Массив для передачи в метод CFormResult::Update
                $pathToFiles = []; // Путь к файлам для скачивания в CRM
                foreach ($fieldsRes as $fieldKey => $fieldName) {
                    $formKey = "form_". $fieldName[0]["FIELD_TYPE"]. "_" . $fieldName[0]["ANSWER_ID"];

                    switch ($fieldName[0]["FIELD_TYPE"]) {
                        case "text":
                        case "textarea":
                            if(!empty($fieldName[0]["USER_TEXT"])) {
                                $arrayUpdate[$formKey] = $fieldName[0]["USER_TEXT"];
                            }
                            break;

                        case "image":
                        case "file":
                            if(!empty($fieldName[0]["USER_FILE_HASH"])) {
                                // TODO метод GetFileByHash проверяет права на форму.
                                // Необходимо изменять права при использовании метода на более высокие 25 и потом возвращать обратно
                                $fileInfo = $exchange->cFormResult->GetFileByHash($resultId, $fieldName[0]["USER_FILE_HASH"]);
                                $path = CFile::GetPath($fileInfo["FILE_ID"]);
                                array_push($pathToFiles, $path);
                            }
                            break;
                    }
                }

                // Проходим еще раз чтобы добавить ссылку на файл для передачи в CRM.
                $countFile = 0;
                foreach ($fieldsRes as $fieldKey => $fieldName) {
                    $formKey = "form_". $fieldName[0]["FIELD_TYPE"]. "_" . $fieldName[0]["ANSWER_ID"];

                    switch ($fieldName[0]["FIELD_TYPE"]) {
                        case "url":
                            $arrayUpdate[$formKey] = $exchange->getCurrentUrl() . $pathToFiles[$countFile];
                            $countFile++;
                            break;
                    }
                }

                // Удаляем файлы, чтобы корректно передавалась ссылка на файл иначе метод update добавит новый файл
                $exchange->removeFiles();

                $exchange->update($resultId, $arrayUpdate);
            }
        }
    }

    /**
     * Возвращает объект текущего класса если он не создан
     *
     * @return ExtCrmExchange
     */
    protected static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Создает объект CFormResult
     *
     * @return void
     */
    protected function createForm()
    {
        if(empty($this->cFormResult)) {
            $this->cFormResult = new CFormResult();
        }
    }

    /**
     * Подключает необходимые модули
     *
     * @return bool
     */
    private function includeModules()
    {
        foreach ($this->modules as $module) {
            if(!CModule::IncludeModule($module)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Очищает переменную с файлами $_FILES
     */
    private function removeFiles()
    {
        if(!empty($_FILES)) {
            foreach ($_FILES as $key => $file) {
                unset($_FILES[$key]);
            }
        }
    }

    /**
     * Обновляет результаты формы в соответствии с массивом $fields
     *
     * @param integer|string $resultId
     * @param array $fields
     *
     * @return void
     */
    protected function update($resultId, $fields)
    {
        $this->cFormResult->Update($resultId, $fields, "N", "N");
    }

    /**
     * Возвращает текущий урл сайта http://sitename.ru или https://sitename.ru
     *
     * @return string
     */
    protected function getCurrentUrl()
    {
        $server = Context::getCurrent()->getServer();
        $host = $server->get("HTTP_HOST");
        $sheme = (Context::getCurrent()->getRequest()->isHttps()) ? "https" : "http" ;
        $url = $sheme . "://" . $host;

        return $url;
    }
}

Данный код был протестирован на одном проекте, если у вас возникли проблемы, рекомендую разобраться более детально в том, что именно делает этот кусок кода. Я лишь предлагаю один из вариантов решения задачи — это не значит, что данный код может подходить для всех проектов без исключения. Ответственность за ваш проект несете только вы! Со своей стороны буду признателен, если вы сообщите о неточностях или возможных ошибках данного примера. Контактные данные можно найти на странице «О сайте» или в футере сайта.

Суть данного метода заключается в том, что в CRM Битрикс 24 мы передаем поле типа url, который представляет собой ссылку на файл, который располагается на вашем сайте под управлением 1С Битрикс. Тем самым мы не передаем сам файл в CRM и поэтому файл сохраняется только на стороне сайта и передается в виде ссылки в CRM штатными средствами 1С Битрикс (более подробную информацию по интеграции форм можно найти в статье: Интеграция форм на сайте с Битрикс 24).