b24 / devtools
Requires
- php: >=8.1.0
This package is auto-updated.
Last update: 2024-09-07 10:54:56 UTC
README
安装
composer require b24/devtools
连接
使用这些工具需要连接 Composer 的自动加载器。示例连接
local/php_interface/init.php
require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';
智能流程
从头开始创建智能流程
$mapper = \B24\Devtools\Crm\Smart\Mapper::create(title: 'TEST', code: 'TEST', name: 'TEST'|null);
成功创建后将返回 \B24\Devtools\Crm\Smart\Mapper 类的对象
class Mapper { public readonly \B24\Devtools\Crm\Smart\SmartDynamic $smart; public readonly string $entityName; public function __construct( public readonly int $id, public readonly int $entityTypeId, public readonly string $code, ) {} }
删除智能流程
通过字符码,或通过实体的 ENTITY_ID
\B24\Devtools\Crm\Smart\Mapper::deleteByCodeOrEntityId($code|$entityTypeId) // Либо \B24\Devtools\Crm\Smart\Mapper::deleteByCodeOrEntityIdIfExists($code|$entityTypeId)
通过 b_crm_dynamic_type 表的 ID
\B24\Devtools\Crm\Smart\Mapper::deleteById($id); // Либо \B24\Devtools\Crm\Smart\Mapper::deleteByIdIfExists($id)
替换服务容器
使用示例
use Module\Helpers\Crm\Replacement\Container; new Container([ 'TEST' => FactoryTest::class ]);
构造函数的参数是一个数组,其中 CODE 是智能流程的键,值是其工厂的命名空间。这允许在智能流程元素上调用前和后的事件。
示例工厂
use Bitrix\Crm\Item; use Bitrix\Crm\Service; use Bitrix\Crm\Service\Context; use Bitrix\Crm\Service\Operation; class FactoryTest extends Service\Factory\Dynamic { public function getAddOperation(Item $item, Context $context = null): Operation\Add { $operation = parent::getAddOperation($item, $context); $operation->addAction( Operation::ACTION_BEFORE_SAVE, new AddHandler() ); return $operation; } }
处理添加元素的的事件处理器
use Bitrix\Crm\Service\Operation; use Bitrix\Main\Result; use B24\Devtools\Crm\ResultOperationTrait; class AddHandler extends Operation\Action { use ResultOperationTrait; public function process(\Bitrix\Crm\Item $item): Result { return $this ->error('Ошибка 1') ->error('Ошибка 2') ->result(); } }
处理智能流程实体
\B24\Devtools\Crm\Smart\SmartProcess 继承自 \B24\Devtools\Crm\Smart\SmartDynamic
$entityTypeId = \B24\Devtools\Crm\Smart\SmartProcess::getIdByCode('TEST'); $smart = new \B24\Devtools\Crm\Smart\SmartProcess($entityTypeId); // Либо так: $smart = new \B24\Devtools\Crm\Smart\SmartProcess('TEST'); $smart->getFactory(); // Вернёт фабрику смарт-процесса $smart->getFactoryId(); // ID смарт-процесса $smart->getEntityName(); // Название объекта смарт-процесса, CRM_2 (например) $smart->compileClass(); // Отдаст неймспейс класса ORM смарт-процесса $smart->getContainer(); // Отсюда же можно вытащить сервис контейнер $smart->getRelationManager(); // RelationManager
对 b_crm_entity_relation 表执行 CRUD 操作
// Чтение связей // $children = \B24\Devtools\Crm\Relation\Manager::searchChildren(\CCrmOwnerType::Quote, 1) ->getAll(); // Массив из ItemIdentifier всех привязанных детей к Предложению $children = \B24\Devtools\Crm\Relation\Manager::searchChildren(\CCrmOwnerType::Quote, 1) ->withEntityTypeId(152); // Массив ID всех привязанных детей-элементов смартпроцесса с ID 152 $children = \B24\Devtools\Crm\Relation\Manager::searchChildren(\CCrmOwnerType::Quote, 1) ->withOne(function (\Bitrix\Crm\ItemIdentifier $identifier) { return $identifier; // Вернёт массив из ItemIdentifier return $identifier->getEntityId(); // Вернёт массив из ID ItemIdentifier }); // Если заменить метод searchChildren на searchParents, то будут искаться родители //
// Обновление связей // \B24\Devtools\Crm\Relation\Manager::update(\CCrmOwnerType::Quote, 1, 152, 1) ->isParent() // Например если в связи надо отвязать родителя (Предложения) и привязать к другому Предложению ->on(\CCrmOwnerType::Quote, 2) // Привязываем к Предложению с ID = 2 ->replace(); // Замена
// Удаление какой-то одной связи // \B24\Devtools\Crm\Relation\Manager::deleteOne(\CCrmOwnerType::Quote, 1, 152, 1); // У Предложения с ID = 1 удаляем все связи со смарт-процессом, у которого ID = 152 \B24\Devtools\Crm\Relation\Manager::deleteWithType(\CCrmOwnerType::Quote, 1, 152);
// Создание связей // Создаст у Предложения с ID = 1 связь (ребёнка) со смарт-процессом с ID = 152 // \B24\Devtools\Crm\Relation\Manager::create(\CCrmOwnerType::Quote, 1, 152, 1);
处理货币字段
$moneyField = '155|USD'; $rateUsdToRub = 93.22; // либо $money = new \B24\Devtools\Data\MoneyField(155, 'USD'); $money = \B24\Devtools\Data\MoneyField::parse($moneyField) ->math(function (&$price) use ($rateUsdToRub) { $price = $price * $rateUsdToRub; }) ->setCurrency('RUB') ->round(2); echo (string) $money; // 14449.1|RUB
Highload-块
简化了与 Highload 块的工作。现在 Highload 块被描述为模型
use B24\Devtools\HighloadBlock\ActiveRecord; use B24\Devtools\HighloadBlock\Fields\Enumeration; use B24\Devtools\HighloadBlock\Fields\EnumValue; use B24\Devtools\HighloadBlock\Fields\Field; class ElementsCatalogHighload extends ActiveRecord { public function getName(): string { return 'ElementsCatalog'; } public function getTableName(): string { return 'elements_catalog'; } public function ruName(): string { return 'Элементы каталога'; } public function enName(): string { return 'Elements catalog'; } protected function getFields(string $entityId): array { return [ new Field( entityId: $entityId, fieldName: 'ENUMERATION', userTypeId: UserTypeEnum::ENUMERATION, multiple: true, enum: new Enumeration( [ new EnumValue( 'Школа43', 'SCHOOL43' ), ], ) ), ]; } }
方法 getFields - 返回 Highload 块的字段列表。默认情况下,Bitrix 创建一个 ID 列,无需指定。
在类的构造函数中传递 3 个必填参数,其他可以不填
class Field { public function __construct( private string $entityId, private string $fieldName, private string|UserTypeEnum $userTypeId, private bool $multiple = false, private bool $mandatory = true, private array $editFormLabel = [], private array $listColumnLabel = [], private array $listFilterLabel = [], private array $errorMessage = [], private array $helpMessage = [], private ?array $settings = null, private ?Enumeration $enum = null ) {} }
在底层,这个类被转换为数组
[ 'ENTITY_ID' => $entityId, // Название сущности 'FIELD_NAME' => $fieldName, // Название поля. Можно задать без UF_ - он проставится автоматически 'USER_TYPE_ID' => $userTypeId, // Тип пользовательского поля, можно найти в UserTypeEnum описание всех полей для хайлод блока 'MULTIPLE' => $multiple, // Множественное поле 'MANDATORY' => $mandatory, // Обязательность заполнения 'EDIT_FORM_LABEL' => $editFormLabel ?? $fieldName, // массив языковых сообщений вида array("ru"=>"привет", "en"=>"hello") 'LIST_COLUMN_LABEL' => $listColumnLabel ?? $fieldName, 'LIST_FILTER_LABEL' => $listFilterLabel ?? $fieldName, 'ERROR_MESSAGE' => $errorMessage ?? $fieldName, 'SETTINGS' => $settings, // массив с настройками свойства зависимыми от типа свойства. Проходят "очистку" через обработчик типа PrepareSettings. 'ENUM' => $enum, ]
创建和删除 Highload 块
$hl = ElementsCatalogHighload(); $hl->createHL(); // Создание $hl->dropHL(); // Удаление
Highload 块的事件
在 init.php 中
ElementsCatalogHighload::events() ->onAdd(ElementsCatalogEvent::class) ->onAfterAdd(ElementsCatalogEvent::class) ->onBeforeAdd(ElementsCatalogEvent::class) ->onDelete(ElementsCatalogEvent::class) ->onAfterDelete(ElementsCatalogEvent::class) ->onBeforeDelete(ElementsCatalogEvent::class) ->onUpdate(ElementsCatalogEvent::class) ->onAfterUpdate(ElementsCatalogEvent::class) ->onBeforeUpdate(ElementsCatalogEvent::class)
事件处理器
use B24\Devtools\HighloadBlock\Operation\EventTrait; use Bitrix\Main\ORM\Event; class ElementsCatalogEvent { use EventTrait; public static function onBeforeAdd(Event $event) { self::setError($event, 'Ошибка_1'); } }
为了方便记录错误,为事件创建了一个 trait B24\Devtools\HighloadBlock\Operation\EventTrait
如果事件名称为 onBeforeAdd,则方法也将是静态的,并命名为 onBeforeAdd。
迁移 Highload 块的字段
继承自 B24\Devtools\HighloadBlock\ActiveRecord 的类有一个必须的方法 getFields,它描述了 Highload 块的字段,方法 migrate 会跟踪这个列表
$hl = ElementsCatalogHighload(); $hl->migrate();
如果从 getFields() 方法中删除了某个字段,它将被跟踪并从数据库中删除。同样,方法也会跟踪 enum 列表的变化
protected function getFields(string $entityId): array { return [ new Field( entityId: $entityId, fieldName: 'ENUMERATION', userTypeId: UserTypeEnum::ENUMERATION, multiple: true, enum: new Enumeration( [ new EnumValue( value: 'Школа43', xmlId: 'SCHOOL43', def: false, // поле поумолчанию? sort: 500 ), ], ) ), ]; }
如果 enum 中添加了另一个 EnumValue,它也将添加到数据库列表中,唯一性由 xmlId 确定。如果从列表中删除了某个 EnumValue,它也将从数据库中删除。如果 EnumValue 的 value 或 def 发生变化,列表的值将更新
方便地在 highload-块中插入/更新记录
记录
$hl = new ElementsCatalogHighload(); $transfer = $hl->getTransfer(); $result = $transfer ->set('NAME', 'Имя') ->setEnumByXmlId('ENUMERATION', 'SCHOOL43') ->saveExistingFile('FILE', 'log.txt') // Все пути будут складываться от $_SERVER['DOCUMENT_ROOT'] . '/' ->setDateTime('DATE', new \Bitrix\Main\Type\DateTime()) // второй аргумент такой уже поумолчанию ->setBoolean('BOOLEAN', true) ->save();
更新记录
$hl = new ElementsCatalogHighload(); $transfer = $hl->getTransfer(id: 1); $result = $transfer ->set('NAME', 'Имя') ->save();
在所有 set 方法中,在字段名称前不需要指定 UF_ - 如果没有,它将自动填充。同样,没有必要记住多选字段以将字符串替换为字符串数组,Helper 已经可以做到这一点,它会查看 getFields 方法中描述的字段,如果 $multiple = true,则认为该字段是多选的
$hl = new ElementsCatalogHighload(); $transfer = $hl->getTransfer(); $transfer ->setEnumByXmlId('ENUMERATION', 'SCHOOL43') ->setEnumByXmlId('ENUMERATION', 'SCHOOL44')
在底层,UF_ENUMERATION 将记录一个包含两个值的数组。