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

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

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

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

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

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

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

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

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

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

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

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

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

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

Итак к коду.

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

$resFields = \CBPWorkflowTemplateLoader::GetList(
    [],
    ['ID' => 474], //для получения всех шаблонов, оставляем пустым
   // ['USER_ID' => 34], //для получения всех шаблонов, одного создателя
    false, //arGroupBy - массив группировать "по"
    false, //arNavStartParams - навигация по получемым массивам параметров
    ['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 "<pre>";
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.

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

Комментарии (0)