Как сделать автозамену любого блока действий, переменной, условия, константы в бизнес-процессе коробочного Битрикс 24

Как у меня возникла идея это реализовать?

После очередного обновления коробочного портала Битрикс 24 в марте 2023 г, в бизнес процессах, перестала работать модификация типов при присвоении значения строковым переменным.

Например, при присвоении переменной »Variable1» значения »{{Начальная сумма > double}}|{{Валюта > user}}» в блоке «Изменение переменных» бизнес процесса, модификатор » > double» преобразует нам типо поля «Деньги» (вида 100|RUB) по правилам преобразования строки в «Число» — 100, а из поля «Валюта» модификатор » > user» всегда выдавал код валюты — «RUB». Таким образом это преобразование должно присвоить переменной «Variable1» значение вида »100|RUB». А после обновления выдаёт »100|RUB|Российсий рубль».

Однако после злополучного обновления, и по сей день, кстати, эти модификаторы перестали работать, конкретно при присвоении значения переменной типа «Строка», во всех остальных случаях, включая блок действия «Уведомление» — работает!

bb20d922182dbd259bc4a8d6420b48c3.png

Для того чтобы данное преобразование сработало в бизнес процессе после обновления, требуется «обернуть» модификаторы в другую функцию, так как ещё раз повторюсь, не работает модификация только со строковыми переменными.

Я для этого использовал функцию «trim ()», в итоге получаем следующую запись:

 {{trim({{Начальная сумма > double}}&"|"&{{Валюта > user}})}}

Такой метод реализации модификаторов работает как «до», так и «после» злополучного обновления.

Отсюда у меня и возникла потребность подменить данную запись у одного из клиентов более, чем в четырехстах бизнес процессах! При этом, многие бизнес-процессы, содержат сотни действий, в десятках веток условий. Вероятность пропустить подобную запись, при ручном изнуряющем редактировании, стремится к 100%!

Порядок реализации автозамены чего-либо в одном, либо во всех бизнес процессах

  1. Получаем шаблон (ы) бизнес процесса в виде многомерного массива.

  2. Используем функцию поиска по нужным критериям и модификации действия.

Реализуем п.1 (получаем шаблоны)

В документации Битрикс 24, ни как не описан функционал получения шаблонов бизнес‑процессов в виде массивов данных, есть только описание, что они именно таким образом хранятся. Поэтому помощь пришла из другой полезной статьи на ХАБРе про перенос бизнес-процессов.

Итак к коду.

Получения одного или нескольких шаблонов бизнес процессов:

$resFields = \CBPWorkflowTemplateLoader::GetList(
    [],
    ['ID' => 474], //для получения всех шаблонов, оставляем пустым
   // ['USER_ID' => 34], //для получения всех шаблонов, одного создателя
    false,
    false,
    ['ID', 'NAME', 'TEMPLATE', 'VARIABLES']); //нам нужны только шаблоны, 
//однако для фильтрации нужных значений понадобится типы переменных, 
//а для отладки ID и имена БП

Дальше перебираем полученный результат:

while ($arFields = $resFields->GetNext()) {
    if (!is_array($arFields)) {
        echo "Из базы ничего не пришло!";
        break;
    }
    //ниже 4 строчки которыми я убираю дополнительно пришедшие из БД дубликаты массивов
    unset($arFields['~ID']);
    unset($arFields['~NAME']);
    unset($arFields['~TEMPLATE']);
    unset($arFields['~VARIABLES']);
    //помещаем в отдельные массивы шаблоны и переменные БП
    $arTemplate = $arFields['TEMPLATE']; 
    $arVariables = $arFields['VARIABLES'];
    /*дальше я прохожусь функией по всему массиву, 
    т.к. я не знаю какова страутура многомерного массива, 
    какие названеи переменных и сколько раз им назначаются значения в БП
    callback функцию "changeNeedleStringInArray", приведу ниже */
    array_walk($arTemplate, 'changeNeedleStringInArray'); 
    $arNewFields['TEMPLATE'] = $arTemplate;
    //без поля "MODIFIER_USER" - сохранение не срабатывает, выдаёт ошибку совершенно на этот факт не указывающую
    $arNewFields["MODIFIER_USER"] = new \CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser);
    \CBPWorkflowTemplateLoader::update($arFields['ID'], $arNewFields);
    //чистим память
    unset($arFields);
    unset($arNewFields);
    unset($arTemplate);
    unset($arVariables);
}
//выводим строки для проверки дебага результата
echo "
";
if (!empty($convert)) {
    print_r(count($convert));
    print_r(PHP_EOL);
    print_r($convert);
}

Реализуем п.2 (поиск и модификацию)

Выполняем преобразования в функции 'changeNeedleStringInArray', у меня будет ниже 3 примера:
1. Исправляем проблему описанную в начале статьи.{{Начальная сумма > double}}|{{Валюта > user}}преобразуем в {{trim({{Начальная сумма > double}}&"|"&{{Валюта > user}})}}

/*

*/
function changeNeedleStringInArray(&$val, $key)
{
    if (is_array($val)) {
        array_walk($val, 'changeNeedleStringInArray'); //заходим этой же функцией во вложенный массив
    } elseif (is_string($val)) {
        if (stripos($val, '|{=Document:CURRENCY_ID > user')  // ищем нужное значение в действии БП
            && !stripos($val, '{{=trim') //проверяем не сделано ли уже нужное нам преобразование
            && (isVarTypeString($key)) //проверяем тип переменной (нам надо менять только в строках)
        ) {
            $val = convertActivityValue($val, $key);
        }
    }
}
function isVarTypeString($key)
{
    global $arVariables;
    if ($arVariables[$key]['Type'] == 'string')
        return true;
    return false;

}

function convertActivityValue($str, $key)
{
    global $convert, $arFields;
    if (!stripos($str, "|")) //проверяем что найденна требуемая нам строка
        return $str;
    $arHelp = explode("|", $str);
    if (stripos($arHelp[0], "=")) {
        $resStr = "{{=trim(" . $arHelp[0] . "&\"|\"&" . $arHelp[1] . ")}}";
    } else {
        $resStr = "{{=trim(\"" . $arHelp[0] . "|\"&" . $arHelp[1] . ")}}";
    }
    $convert[$arFields['NAME']][$arFields['ID']][$key][] = $str;
    $convert[$arFields['NAME']][$arFields['ID'] . "_new"][$key][] = $resStr;
    return $resStr;
}
  1. С каким-то из обновлений некоторые REST запросы стали чувствительны к регистру «ID» объектов в передаваемых параметрах, теперь работает только в нижнем регистре «id». Точно проверено с удалением комментариев в timeline: crm.timeline.comment.delete Так как в некоторых БП я использовал вызовы REST посредствам curl, в качестве асинхронных вызовов, после обновлений пришлось вносить правки и тут. Исправляем '\"ID\"' на '\"id\"' в curl

function changeNeedleStringInArray(&$val, $key)
{
    if (is_array($val)) {
        array_walk($val, 'changeNeedleStringInArray'); //заходим этой же функцией во вложенный массив
    } elseif (is_string($val)) {
        if (stripos($val, 'curl')  // ищем нужное значение в действии БП
            && strpos($val, '\"ID\"') // ищем дополнительное нужное значение в действии БП
            && ($key == 'ExecuteCode') //проверяем тип переменной (нам надо менять только в PHP блоках)
        ) {
            $val = convertActivityValue($val, $key);
        }
    }
}
function convertActivityValue($str, $key)
{
    global $convert, $arFields;
    $resStr = str_replace('\"ID\"', '\"id\"', $str);
    $convert[$arFields['NAME']][$arFields['ID']][$key][] = $str;
    $convert[$arFields['NAME']][$arFields['ID'] . "_new"][$key][] = $resStr;
    return $resStr;
}
  1. В «Уведомлениях» перестал работать BBCode с указанием цветов по их названию, типа
    [color=red]Текст[/color] — в сообщение выводится без форматирования
    но [color=#ff0000]Текст[/color] — вполне себе работает. Подменяем:

function convertActivityValue($str, $key)
{
    global $convert, $arFields;
    $resStr = str_replace('red', '#db0000', $str);
    $convert[$arFields['NAME']][$arFields['ID']][$key][] = $str;
    $convert[$arFields['NAME']][$arFields['ID'] . "_new"][$key][] = $resStr;
    return $resStr;
}

function changeNeedleStringInArray(&$val, $key)
{
    if (is_array($val)) {
        array_walk($val, 'changeNeedleStringInArray'); //заходим этой же функцией во вложенный массив
    } elseif (is_string($val)) {
        if (stripos($val, '[color=red]')  // ищем нужное значение в действии БП
            && ($key == 'MessageSite') //проверяем тип переменной (нам надо менять только в Уведомлениях)
        ) {
            $val = convertActivityValue($val, $key);
        }
    }
}

Итоги

Таким образом мы имеем возможность вносить любые изменения в шаблоны бизнес‑процессов массово. Редактировать шаблоны не только из красивого вэб‑интрефейса, но в виде «хардкода». Так же на базе данного кода можно сделать отладку шаблонов бизнес‑процессов, или динамическое изменения в них.

Уверен, что с подобными изменениями в работы бизнес процессов, сталкиваются многие интеграторы Б24.

Поэтому, думаю, что существенно облегчил нам наш нелёгкий труд, данной статьёй.

© Habrahabr.ru