Документация для разработчиков
Темная тема

Примеры кастомизации

Несколько примеров кастомизации.

Добавить / заменить фразу

$localization = new class extends Service\Localization {
	public function loadMessages (): array
	{
		$messages = parent:: loadMessages ();
		$messages['CRM_MY_NEW_COMMON_MESSAGE' ] = 'Some Messages' ;
		return $messages;
	}
};
DI\ServiceLocator ::getInstance ()->addInstance (
	'crm.service.localization' ,
	$localization
);

Замена контейнера и фабрики

use Bitrix\Crm\Service;
use Bitrix\Main\DI;
define('SUPER_ENTITY_TYPE_ID', 150);
// our new custom container
$container = new class extends Service\Container {
	public function getFactory(int $entityTypeId): ?Factory
	{
		// it is the same as
		// DI\ServiceLocator::getInstance()->addInstance('Crm.Service.Factory.Dynamic.150',$factory);
		if ($entityTypeId === SUPER_ENTITY_TYPE_ID)
		{
			$type = $this->getTypeByEntityTypeId($entityTypeId);
			// our new custom factory class
			$factory = new class($type) extends Factory\Dynamic {
                
			};
			return $factory;
		}
		return parent::getFactory($entityTypeId);
	}
};
// here we change the container
DI\ServiceLocator::getInstance()->addInstance('crm.service.container', $container);

Сделать поле только для чтения

use Bitrix\Crm\Service\Factory;
$factory = new class($type) extends Factory\Dynamic {
	public function getUserFieldsInfo(): array
	{
		$fields = parent::getUserFieldsInfo();
		$fields['UF_CRM_150_STRING']['ATTRIBUTES'][] = \CCrmFieldInfoAttr::Immutable;
        
		return $fields;
	}
};

Аналогично, с необходимостью скрыть поле или сделать его обязательным. Только используется:

  • \CCrmFieldInfoAttr::NotDisplayed - скрыть поле
  • \CCrmFieldInfoAttr::Required - обязательное поле

Логгирование удаления элементов

use Bitrix\Crm\Item;
use Bitrix\Crm\Service;
use Bitrix\Crm\Service\Context;
use Bitrix\Crm\Service\Factory;
use Bitrix\Crm\Service\Operation;
use Bitrix\Main\Result;
use Bitrix\Main\Web\Json;
$factory = new class($type) extends Factory\Dynamic {
	public function getDeleteOperation(Item $item, Context $context = null): Operation\Delete
	{
		$operation = parent::getDeleteOperation($item, $context);
		return $operation->addAction(
			Operation::ACTION_AFTER_SAVE,
			new class extends Operation\Action {
				public function process(Item $item): Result
				{
					$userId = Service\Container::getInstance()->getContext()->getUserId();
					AddMessage2Log(Json::encode([
						'userId' => $userId,
						'entityTypeId' => $item->getEntityTypeId(),
						'id' => $item->getId(),
					]));
                  
					return new Result();
				}
			}
		);
	}
};

Запретить менять стадию пользователю

use Bitrix\Crm\Item;
use Bitrix\Crm\Service;
use Bitrix\Crm\Service\Context;
use Bitrix\Crm\Service\Factory;
use Bitrix\Crm\Service\Operation;
use Bitrix\Main\Result;
$factory = new class ($type) extends Factory\Dynamic {
	public function getUpdateOperation(Item $item, Context $context = null): Operation\Update
	{
		$operation = parent::getUpdateOperation($item, $context);
		return $operation->addAction(
			Operation::ACTION_BEFORE_SAVE,
			new class extends Operation\Action {
				public function process(Item $item): Result
				{
					$result = new Result();
					$userId = Service\Container::getInstance()->getContext()->getUserId();
                    
					if (
						$userId === 222
						&& $item->isChangedStageId()
						&& $item->getStageId() === 'D150_3:CLIENT'
						&& $item->remindActual(Item::FIELD_NAME_STAGE_ID) === 'D150_3:PREPARATION'
					)
					{
						$result->addError(new Error('Stage updating is prohibited'));
					}
					return $result;
				}
			}
		);
	}
}

Заменить компонент карточки:

use Bitrix\Crm\Service;
use Bitrix\Main\HttpRequest;
use Bitrix\Crm\Service\Router\ParseResult;
define('SUPER_ENTITY_TYPE_ID', 150);
$router = new class extends Service\Router {
	public function parseRequest(HttpRequest $httpRequest = null): ParseResult
	{
		$result = parent::parseRequest($httpRequest);
		if ($result->getComponentName() === 'bitrix:crm.item.details')
		{
			$parameters = $result->getComponentParameters();
			$entityTypeId = $parameters['ENTITY_TYPE_ID'] ?? $parameters['entityTypeId'] ?? null;
			if ((int)$entityTypeId === SUPER_ENTITY_TYPE_ID)
			{
				$result = new ParseResult(
					'dev:crm.item.details',
					$parameters,
					$result->getTemplateName()
				);
			}
		}
      
		return $result;
	}
};
DI\ServiceLocator::getInstance()->addInstance('crm.service.router', $router);

Пользовательские комментарии

Мы будем рады, если разработчики добавят свои комментарии по практическому использованию методов системы.

Для этого нужно всего лишь авторизоваться на сайте

Но помните, что Пользовательские комментарии, несмотря на модерацию, не являются официальной документацией. Ответственность за их использование несет сам пользователь.

Также Пользовательские комментарии не являются местом для обсуждения функционала. По подобным вопросам обращайтесь на форумы.
0
Виталий Семко
Сообщение не промодерировано, возможны ошибки и неточности.
В приведённом выше примере есть комментарий
Код
// it is the same as         
// DI\ServiceLocator::getInstance()->addInstance('Crm.Service.Factory.Dynamic.150',$factory);

Хочу заметить что верным будет код, где индекс будет указан в нижнем регистре 'crm.service.factory.dynamic.150'
Код
DI\ServiceLocator::getInstance()->addInstance('crm.service.factory.dynamic.150',$factory);
3
Юлиана Присяжнюк
Сообщение не промодерировано, возможны ошибки и неточности.
при замене фабрики нужно учитывать, что в операции удаления в событии перед удалением элемент смарт-процесса будет уже без связей с другими смарт-процессами, если включена корзина.
© «Битрикс», 2001-2024, «1С-Битрикс», 2024
Наверх