Как сделать работу с Highloadblock bitrix более сносной? Решение есть, описание сущности таблицы в ORM, данный способ позволит нам с легкостью обращаться к полям справочника как к любой другой таблице описанной в ORM, те доступны все методы Add, Update, GetList и т.д.

Только существует один ньюанс при обращении к полю множественного типа оно возращается строкой для которой надо применить unseriallize().

Подключить данный код можно в php_interface/init.php

Рекомендация — для каждой таблицы создавать отдельный файл с описанием сущности справочника

<?php
namespace Gw\Tables;
use Bitrix\Main\Entity\DataManager, Bitrix\Highloadblock as HL,
    Bitrix\Main\Entity\IntegerField,
    Bitrix\Main\Entity\TextField, Bitrix\Main\Entity\FloatField,
    Bitrix\Main\Loader, Bitrix\Highloadblock\HighloadBlockTable;
    Loader::includeModule('highloadblock');
/**
 * Class HlCityTable
 * @package Gw\Tables
 */

class HlStatusTable extends DataManager
{
    private static $id = 1;

    public static function getTableName()
    {
        return 'hl_order_status';
    }
    public static function getMap()
    {
        return array(
            'ID' => new IntegerField('ID', array(
                'primary' => true,
                'title' => "ID"
            )),
            'UF_ID' => new TextField('UF_ID', array(
                'title' => "UF_ID"
            )),
            'UF_COLOR' => new TextField('UF_COLOR', array(
                'title' => "UF_COLOR"
            )),
        );
    }
}

Возникла необходимость использовать местоположения по нескольким странам, которые отсутствуют в редакции «Стандарт», а так же в недостаточном количестве представлены в более продвинутых редакциях битрикса с учетом языковых зависимостей.

Для этого собрал модуль — https://github.com/sm1le404/ds.geolocation, на основе https://github.com/x88/i18nGeoNamesDB этой геобазы.

В настоящий момент таблицы пока пусты, отдельно надо будет сделать прогрузку так как битрикс не успевает за приемлимое время установки все протянуть.

В ближайшее время ждите обновлений.

Возникла задача — необходимо добавить комментарий из письма комментарием к задаче, то есть владелец задачи может оставить комментарий к своей задачи на прямую из почты.

Расписывать каким образом читать почту я не буду, просто приведу листинг того как добавить комментарий и как хотелось бы на D7 , но пока нельзя.

 
$task = \Bitrix\Tasks\Internals\TaskTable::getByPrimary($res['TASK_ID'])->fetch();
$forumID = \CForumTopic::GetByID($task['FORUM_TOPIC_ID']);
$comment = '';
$postFields  = array(
    'TOPIC_ID' => $task['FORUM_TOPIC_ID'], // идентификатор topic'a
    'FORUM_ID' => $forumID['FORUM_ID'], // id форума, приходится делать отдельным запросом
    'SOURCE_ID' => 'WEB',
    'USE_SMILES' => 'Y',
    'NEW_TOPIC' => 'Y',
    'POST_MESSAGE' => $comment,
    'POST_MESSAGE_HTML' => $comment,
    'AUTHOR_ID' => $user['ID'],
    'AUTHOR_NAME' => $user['NAME'].' '.$user['LAST_NAME'], // без этого поля тоже не добавит
    'XML_ID' => 'TASK_'.$task['ID'], // важно соблюдать данный формат
);

$result =  \CForumMessage::Add($postFields);
if (!$result)
{
    GLOBAL $APPLICATION;
    $ex = $APPLICATION->GetException();
    echo $ex->GetString();
}

А вот как хотелось бы на D7, но висит Exception в классе Сообщений (спасибо битрикс)

$result = \Bitrix\Forum\MessageTable::add(array(
    'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
    'FORUM_ID' => $forumID['FORUM_ID'],
    'SOURCE_ID' => 'WEB',
    'USE_SMILES' => 'Y',
    'NEW_TOPIC' => 'Y',
    'POST_MESSAGE' => $comment,
    'POST_MESSAGE_HTML' => $comment,
    'AUTHOR_ID' => $user['ID'],
    'XML_ID' => 'TASK_'.$task['ID']
));
print_r($result->getErrorMessages());

Столкнулся с проблемой следующего характера — при настройке стандартного резервного копирования в облаке Битрикс и установке -> удалять в случае если кол-во копий больше N, если копия не ушла в облако по каким то причинам, она остается на сервере, что в свою очередь захломляет пространство. Чтобы обойти этот момент — написал простой агент, который можно вешать раз в день, он будет в свою очередь удалять лишние копии, выбирает конечно же самые старые.

function removeBackup()
{
    define('DOCUMENT_ROOT', rtrim(str_replace('\\','/',$_SERVER['DOCUMENT_ROOT']),'/'));
    define("BX_ROOT", "/bitrix");
    $arFiles = array();
    $arTmpFiles = array();
    if (is_dir($p = DOCUMENT_ROOT.BX_ROOT.'/backup'))
    {
        if ($dir = opendir($p))
        {
            while(($item = readdir($dir)) !== false)
            {
                $f = $p.'/'.$item;
                if (!is_file($f))
                    continue;
                $arTmpFiles[] = array(
                    'NAME' => $item,
                    'SIZE' => filesize($f),
                    'DATE' => filemtime($f),
                    'BUCKET_ID' => 0,
                    'PLACE' => GetMessage("MAIN_DUMP_LOCAL")
                );
            }
            closedir($dir);
        }
    }
    $arParts = array();
    $arSize = array();
    $arDates = array();$arDates['test'] = 'test';
    $i=0;
    foreach($arTmpFiles as $k=>$ar)
    {
        if (preg_match('#^(.*\.(enc|tar|gz|sql))(\.[0-9]+)?$#',$ar['NAME'],$regs))
        {
            $i++;
            $BUCKET_ID = intval($ar['BUCKET_ID']);
            $arParts[$BUCKET_ID.$regs[1]]++;
            $arSize[$BUCKET_ID.$regs[1]] += $ar['SIZE'];
            if (!$regs[3])
            {
                if ($by == 'size')
                    $key = $arSize[$BUCKET_ID.$regs[1]];
                elseif ($by == 'timestamp')
                    $key = $ar['DATE'];
                elseif ($by == 'location')
                    $key = $ar['PLACE'];
                else // name
                    $key = $regs[1];
                $key .= '_'.$i;
                $arFiles[$key] = $ar;
                $arDates[$key] = $ar['DATE'];
            }
        }
    }

    $state = 2; // количество копий которое должно остаться
    asort($arDates); // Отсортировали по дате в порядке возрастанаия вверху самые старые

    if (count($arFiles) > $state)
    {
        foreach ($arDates as $dumpKey => $date)
        {
            $founded = $arFiles[$dumpKey];
            if (!empty($founded['NAME']))
            {
                foreach ($arParts as $key => $val)
                {
                    if (strstr($key, $founded['NAME']) !== false)
                    {
                        $partsCount = $val;
                        break;
                    }
                }
                $backPath = DOCUMENT_ROOT.BX_ROOT.'/backup/';
                for ($i = 1; $i < $partsCount; $i++)
                {
                    $filePath = $backPath.$founded['NAME'].'.'.$i;
                    if (file_exists($filePath))
                    {
                        unlink($filePath);
                    }
                }
                unlink($backPath.$founded['NAME']);
            }
        }
    }

    return 'removeBackup();';
}

 

Возникла задача сохранения файла из внешнего источника в задаче КП Битрикса, но оказалось все не совсем просто, в связи с тем что использует он модуль disk, а не только стандартный класс CFile, чтобы решить данную проблему пришлось покопать исходники.

$fileInfo = \CFile::GetFileArray(1);
$folder = \Bitrix\Disk\Folder::getById(1);
$data = array(
    'NAME' => $fileID.'_'.$fileInfo['ORIGINAL_NAME'],
    'STORAGE_ID' => 1,
    'FILE_ID' => $fileInfo['ID'],
    'CREATED_BY' => 1,
    'SIZE' => $fileInfo['FILE_SIZE'],
    'PARENT' => $folder,
    'PARENT_ID' => 1
);
$error = new \Bitrix\Disk\Internals\Error\ErrorCollection;
$res = \Bitrix\Disk\File::add($data, $error);
$fileDiskID = $res->getId();

 

Список всех папок на диске для сохранения можно получить так же —

\Bitrix\Disk\Internals\FolderTable::getList();

здесь есть для PARENT_ID и STORAGE_ID

Добавляем файл к задаче

if ($fileID)
{
    $newFiles[] = \Bitrix\Disk\Uf\FileUserType::NEW_FILE_PREFIX.$fileID;
}

if (count($newFiles))
{
    $USER_FIELD_MANAGER->Update("TASKS_TASK", $taskID, array(
        'UF_TASK_WEBDAV_FILES' => $newFiles,
    ));
}

После ввода нового формата GTM который содержит в себе iframe, битриксовый веб-антивирус начал истошно визжать о том что «обнаружен вирус».

Чтобы не наблюдать данную проблему и bitrix не писал подобных сообщений в лог или не пытался просто вырезать данную конструкцию необходимо записать в исключения веб-антивируса содержимое тега src, из <iframe src=’наш код’></iframe>.