• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/classes/general/crm_contact.php
  • Класс: \CAllCrmContact
  • Вызов: CAllCrmContact::Add
public function Add(array &$arFields, $bUpdateSearch = true, $options = array())
{
	global $DB;

	if(!is_array($options))
	{
		$options = array();
	}

	if ($this->isUseOperation())
	{
		return $this->getCompatibilityAdapter()->performAdd($arFields, $options);
	}

	$this->LAST_ERROR = '';
	$this->checkExceptions = [];

	$isRestoration = isset($options['IS_RESTORATION']) && $options['IS_RESTORATION'];

	// ALLOW_SET_SYSTEM_FIELDS is deprecated temporary option. It will be removed soon! Do not use it!
	$allowSetSystemFields = $options['ALLOW_SET_SYSTEM_FIELDS'] ?? $isRestoration;

	$userID = isset($options['CURRENT_USER'])
		? (int)$options['CURRENT_USER'] : CCrmSecurityHelper::GetCurrentUserID();

	if($userID <= 0 && $this->bCheckPermission)
	{
		$arFields['RESULT_MESSAGE'] = $this->LAST_ERROR = GetMessage('CRM_PERMISSION_USER_NOT_DEFINED');
		return false;
	}

	unset($arFields['ID']);

	if(!($allowSetSystemFields && isset($arFields['DATE_CREATE'])))
	{
		unset($arFields['DATE_CREATE']);
		$arFields['~DATE_CREATE'] = $DB->CurrentTimeFunction();
	}

	if(!($allowSetSystemFields && isset($arFields['DATE_MODIFY'])))
	{
		unset($arFields['DATE_MODIFY']);
		$arFields['~DATE_MODIFY'] = $DB->CurrentTimeFunction();
	}

	if($userID > 0)
	{
		if(!(isset($arFields['CREATED_BY_ID']) && $arFields['CREATED_BY_ID'] > 0))
		{
			$arFields['CREATED_BY_ID'] = $userID;
		}

		if(!(isset($arFields['MODIFY_BY_ID']) && $arFields['MODIFY_BY_ID'] > 0))
		{
			$arFields['MODIFY_BY_ID'] = $userID;
		}

		if(!(isset($arFields['ASSIGNED_BY_ID']) && $arFields['ASSIGNED_BY_ID'] > 0))
		{
			$arFields['ASSIGNED_BY_ID'] = $userID;
		}
	}

	if((!isset($arFields['LAST_NAME']) || trim($arFields['LAST_NAME']) === '')
		&& (!isset($arFields['NAME']) || trim($arFields['NAME']) === ''))
	{
		$arFields['LAST_NAME'] = self::GetDefaultTitle();
	}

	$fields = self::GetUserFields();
	$this->fillEmptyFieldValues($arFields, $fields);

	$arFields['CATEGORY_ID'] = $arFields['CATEGORY_ID'] ?? 0;

	if (!$this->CheckFields($arFields, false, $options))
	{
		$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
		$result = false;
	}
	else
	{
		if(isset($arFields['BIRTHDATE']))
		{
			if($arFields['BIRTHDATE'] !== '')
			{
				$birthDate = $arFields['BIRTHDATE'];
				$arFields['~BIRTHDATE'] = $DB->CharToDateFunction($birthDate, 'SHORT', false);
				$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting($birthDate);
			}
			else
			{
				$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting('');
			}
			unset($arFields['BIRTHDATE']);
		}
		else
		{
			$arFields['BIRTHDAY_SORT'] = \Bitrix\Crm\BirthdayReminder::prepareSorting('');
		}

		$arAttr = array();
		if (!empty($arFields['OPENED']))
			$arAttr['OPENED'] = $arFields['OPENED'];

		$permissionEntityType = (new PermissionEntityTypeHelper(CCrmOwnerType::Contact))
			->getPermissionEntityTypeForCategory((int)$arFields['CATEGORY_ID'])
		;

		$sPermission = 'ADD';
		if (isset($arFields['PERMISSION']))
		{
			if ($arFields['PERMISSION'] == 'IMPORT')
				$sPermission = 'IMPORT';
			unset($arFields['PERMISSION']);
		}

		if($this->bCheckPermission)
		{
			$arEntityAttr = self::BuildEntityAttr($userID, $arAttr);
			$userPerms =  $userID == CCrmPerms::GetCurrentUserID() ? $this->cPerms : CCrmPerms::GetUserPermissions($userID);
			$sEntityPerm = $userPerms->GetPermType($permissionEntityType, $sPermission, $arEntityAttr);
			if ($sEntityPerm == BX_CRM_PERM_NONE)
			{
				$this->LAST_ERROR = GetMessage('CRM_PERMISSION_DENIED');
				$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
				return false;
			}

			$assignedByID = intval($arFields['ASSIGNED_BY_ID']);
			if ($sEntityPerm == BX_CRM_PERM_SELF && $assignedByID != $userID)
			{
				$arFields['ASSIGNED_BY_ID'] = $userID;
			}
		}

		$assignedByID = intval($arFields['ASSIGNED_BY_ID']);
		$arEntityAttr = self::BuildEntityAttr($assignedByID, $arAttr);
		$userPerms =  $assignedByID == CCrmPerms::GetCurrentUserID() ? $this->cPerms : CCrmPerms::GetUserPermissions($assignedByID);
		$sEntityPerm = $userPerms->GetPermType($permissionEntityType, $sPermission, $arEntityAttr);
		$this->PrepareEntityAttrs($arEntityAttr, $sEntityPerm);

		if(isset($arFields['PHOTO'])
			&& is_array($arFields['PHOTO'])
			&& CFile::CheckImageFile($arFields['PHOTO']) == '')
		{
			$arFields['PHOTO']['MODULE_ID'] = 'crm';
			CFile::SaveForDB($arFields, 'PHOTO', 'crm');
		}
		elseif (!empty($arFields['FACE_ID']) && Main\Loader::includeModule('faceid'))
		{
			// Set photo from FaceId module
			$face = \Bitrix\Faceid\FaceTable::getRowById($arFields['FACE_ID']);
			if (!empty($face))
			{
				$file = \CFile::MakeFileArray($face['FILE_ID']);

				$io = \CBXVirtualIo::GetInstance();
				$filePath = $io->GetPhysicalName($file['tmp_name']);
				$binaryImageContent = $io->GetFile($filePath)->GetContents();

				$arFields['PHOTO'] = array(
					'name' => 'face_'.$arFields['FACE_ID'].'.jpg',
					'type' => 'image/jpeg',
					'content' => $binaryImageContent
				);

				$arFields['PHOTO']['MODULE_ID'] = 'crm';
				CFile::SaveForDB($arFields, 'PHOTO', 'crm');
			}
		}

		$arFields['FULL_NAME'] = self::GetFullName($arFields);

		//region Setup HAS_EMAIL & HAS_PHONE & HAS_IMOL fields
		$arFields['HAS_EMAIL'] = $arFields['HAS_PHONE'] = $arFields['HAS_IMOL'] = 'N';
		if(isset($arFields['FM']) && is_array($arFields['FM']))
		{
			if(CCrmFieldMulti::HasValues($arFields['FM'], CCrmFieldMulti::EMAIL))
			{
				$arFields['HAS_EMAIL'] = 'Y';
			}

			if(CCrmFieldMulti::HasValues($arFields['FM'], CCrmFieldMulti::PHONE))
			{
				$arFields['HAS_PHONE'] = 'Y';
			}

			if(CCrmFieldMulti::HasImolValues($arFields['FM']))
			{
				$arFields['HAS_IMOL'] = 'Y';
			}
		}
		//endregion

		//region Preparation of companies
		$companyBindings = isset($arFields['COMPANY_BINDINGS']) && is_array($arFields['COMPANY_BINDINGS'])
			? $arFields['COMPANY_BINDINGS'] : null;
		$companyIDs = isset($arFields['COMPANY_IDS']) && is_array($arFields['COMPANY_IDS'])
			? $arFields['COMPANY_IDS'] : null;
		unset($arFields['COMPANY_IDS']);
		//For backward compatibility only
		$companyID = isset($arFields['COMPANY_ID']) ? max((int)$arFields['COMPANY_ID'], 0) : null;
		if($companyID !== null && $companyIDs === null)
		{
			$companyIDs = array();
			if($companyID > 0)
			{
				$companyIDs[] = $companyID;
			}
		}
		unset($arFields['COMPANY_ID']);

		if(is_array($companyIDs) && !is_array($companyBindings))
		{
			$companyBindings = EntityBinding::prepareEntityBindings(
				\CCrmOwnerType::Company,
				$companyIDs
			);

			EntityBinding::markFirstAsPrimary($companyBindings);
		}
		/* Please uncomment if required
		elseif(is_array($companyBindings) && !is_array($companyIDs))
		{
			$companyIDs = EntityBinding::prepareEntityIDs(
				CCrmOwnerType::Company,
				$companyBindings
			);
		}
		*/
		//endregion

		self::getLastActivityAdapter()->performAdd($arFields, $options);
		self::getCommentsAdapter()->normalizeFields(null, $arFields);

		//region Rise BeforeAdd event
		$beforeEvents = GetModuleEvents('crm', 'OnBeforeCrmContactAdd');
		while ($arEvent = $beforeEvents->Fetch())
		{
			if(ExecuteModuleEventEx($arEvent, array(&$arFields)) === false)
			{
				if(isset($arFields['RESULT_MESSAGE']))
				{
					$this->LAST_ERROR = $arFields['RESULT_MESSAGE'];
				}
				else
				{
					$this->LAST_ERROR = GetMessage('CRM_CONTACT_CREATION_CANCELED', array('#NAME#' => $arEvent['TO_NAME']));
					$arFields['RESULT_MESSAGE'] = &$this->LAST_ERROR;
				}
				return false;
			}
		}
		//endregion

		unset($arFields['ID']);

		$this->normalizeEntityFields($arFields);
		$ID = (int) $DB->Add(self::TABLE_NAME, $arFields, [], 'FILE: '.__FILE__.'
LINE: '.__LINE__); //Append ID to LAST_NAME if required if($ID > 0 && $arFields['LAST_NAME'] === self::GetDefaultTitle()) { $arFields['LAST_NAME'] = self::GetDefaultTitle($ID); $sUpdate = $DB->PrepareUpdate('b_crm_contact', array('LAST_NAME' => $arFields['LAST_NAME'])); if($sUpdate <> '') { $DB->Query( "UPDATE b_crm_contact SET {$sUpdate} WHERE ID = {$ID}", false, 'FILE: '.__FILE__.'
LINE: '.__LINE__ ); }; } $result = $arFields['ID'] = $ID; if(defined('BX_COMP_MANAGED_CACHE')) { $GLOBALS['CACHE_MANAGER']->CleanDir('b_crm_contact'); } $securityRegisterOptions = (new \Bitrix\Crm\Security\Controller\RegisterOptions()) ->setEntityAttributes($arEntityAttr) ; Crm\Security\Manager::getEntityController(CCrmOwnerType::Contact) ->register($permissionEntityType, $ID, $securityRegisterOptions) ; //Statistics & History --> Bitrix\Crm\Statistics\ContactGrowthStatisticEntry::register($ID, $arFields); //<-- Statistics & History //region Save companies if (is_array($companyBindings)) { \Bitrix\Crm\Binding\ContactCompanyTable::bindCompanies($ID, $companyBindings); } if (isset($GLOBALS['USER']) && $companyID > 0) { CUserOptions::SetOption('crm', 'crm_company_search', array('last_selected' => $companyID)); } //endregion //region Statistics & History if(isset($arFields['LEAD_ID']) && $arFields['LEAD_ID'] > 0) { Bitrix\Crm\Statistics\LeadConversionStatisticsEntry::processBindingsChange($arFields['LEAD_ID']); } //endregion if($isRestoration) { Bitrix\Crm\Timeline\ContactController::getInstance()->onRestore($ID, array('FIELDS' => $arFields)); } else { Bitrix\Crm\Timeline\ContactController::getInstance()->onCreate($ID, array('FIELDS' => $arFields)); } CCrmEntityHelper::registerAdditionalTimelineEvents([ 'entityTypeId' => \CCrmOwnerType::Contact, 'entityId' => $ID, 'fieldsInfo' => static::GetFieldsInfo(), 'previousFields' => [], 'currentFields' => $arFields, 'options' => $options, 'bindings' => [ 'entityTypeId' => \CCrmOwnerType::Company, 'previous' => [], 'current' => $companyBindings, ] ]); EntityAddress::register( CCrmOwnerType::Contact, $ID, EntityAddressType::Primary, array( 'ADDRESS_1' => isset($arFields['ADDRESS']) ? $arFields['ADDRESS'] : null, 'ADDRESS_2' => isset($arFields['ADDRESS_2']) ? $arFields['ADDRESS_2'] : null, 'CITY' => isset($arFields['ADDRESS_CITY']) ? $arFields['ADDRESS_CITY'] : null, 'POSTAL_CODE' => isset($arFields['ADDRESS_POSTAL_CODE']) ? $arFields['ADDRESS_POSTAL_CODE'] : null, 'REGION' => isset($arFields['ADDRESS_REGION']) ? $arFields['ADDRESS_REGION'] : null, 'PROVINCE' => isset($arFields['ADDRESS_PROVINCE']) ? $arFields['ADDRESS_PROVINCE'] : null, 'COUNTRY' => isset($arFields['ADDRESS_COUNTRY']) ? $arFields['ADDRESS_COUNTRY'] : null, 'COUNTRY_CODE' => isset($arFields['ADDRESS_COUNTRY_CODE']) ? $arFields['ADDRESS_COUNTRY_CODE'] : null, 'LOC_ADDR_ID' => isset($arFields['ADDRESS_LOC_ADDR_ID']) ? (int)$arFields['ADDRESS_LOC_ADDR_ID'] : 0, 'LOC_ADDR' => isset($arFields['ADDRESS_LOC_ADDR']) ? $arFields['ADDRESS_LOC_ADDR'] : null ) ); CCrmEntityHelper::NormalizeUserFields($arFields, self::$sUFEntityID, $GLOBALS['USER_FIELD_MANAGER'], array('IS_NEW' => true)); $GLOBALS['USER_FIELD_MANAGER']->Update(self::$sUFEntityID, $ID, $arFields); //region Duplicate communication data if (isset($arFields['FM']) && is_array($arFields['FM'])) { $CCrmFieldMulti = new CCrmFieldMulti(); $CCrmFieldMulti->SetFields('CONTACT', $ID, $arFields['FM']); } //endregion $duplicateCriterionRegistrar = DuplicateManager::getCriterionRegistrar(\CCrmOwnerType::Contact); $data = (new Crm\Integrity\CriterionRegistrar\Data()) ->setEntityTypeId(\CCrmOwnerType::Contact) ->setEntityId($ID) ->setCurrentFields($arFields) ; $duplicateCriterionRegistrar->register($data); \Bitrix\Crm\Counter\Monitor::getInstance()->onEntityAdd(CCrmOwnerType::Contact, $arFields); // tracking of entity Tracking\Entity::onAfterAdd(CCrmOwnerType::Contact, $ID, $arFields); //region save parent relations Crm\Service\Container::getInstance()->getParentFieldManager()->saveParentRelationsForIdentifier( new Crm\ItemIdentifier(\CCrmOwnerType::Contact, $ID), $arFields ); //endregion if($bUpdateSearch) { CCrmSearch::UpdateSearch(array('ID' => $ID, 'CHECK_PERMISSIONS' => 'N'), 'CONTACT', true); } //region Search content index Bitrix\Crm\Search\SearchContentBuilderFactory::create( CCrmOwnerType::Contact )->build($ID, ['checkExist' => true]); //endregion self::getCommentsAdapter()->performAdd($arFields, $options); if(isset($options['REGISTER_SONET_EVENT']) && $options['REGISTER_SONET_EVENT'] === true) { $multiFields = isset($arFields['FM']) ? $arFields['FM'] : null; $phones = CCrmFieldMulti::ExtractValues($multiFields, 'PHONE'); $emails = CCrmFieldMulti::ExtractValues($multiFields, 'EMAIL'); $assignedByID = intval($arFields['ASSIGNED_BY_ID']); $createdByID = intval($arFields['CREATED_BY_ID']); $liveFeedFields = array( 'USER_ID' => $createdByID, 'ENTITY_TYPE_ID' => CCrmOwnerType::Contact, 'ENTITY_ID' => $ID, 'TITLE' => GetMessage('CRM_CONTACT_EVENT_ADD'), 'MESSAGE' => '', 'PARAMS' => array( 'NAME' => isset($arFields['NAME']) ? $arFields['NAME'] : '', 'SECOND_NAME' => isset($arFields['SECOND_NAME']) ? $arFields['SECOND_NAME'] : '', 'LAST_NAME' => isset($arFields['LAST_NAME']) ? $arFields['LAST_NAME'] : '', 'HONORIFIC' => isset($arFields['HONORIFIC']) ? $arFields['HONORIFIC'] : '', 'PHOTO_ID' => isset($arFields['PHOTO']) ? $arFields['PHOTO'] : '', 'COMPANY_ID' => isset($arFields['COMPANY_ID']) ? $arFields['COMPANY_ID'] : '', 'PHONES' => $phones, 'EMAILS' => $emails, 'AUTHOR_ID' => intval($arFields['CREATED_BY_ID']), 'RESPONSIBLE_ID' => $assignedByID ) ); //region Register company relation if(is_array($companyBindings)) { $parents = array(); CCrmLiveFeed::PrepareOwnershipRelations( CCrmOwnerType::Company, EntityBinding::prepareEntityIDs(CCrmOwnerType::Company, $companyBindings), $parents ); if(!empty($parents)) { $liveFeedFields['PARENTS'] = array_values($parents); } } //endregion $isUntypedCategory = (int)$arFields['CATEGORY_ID'] === 0; if ($isUntypedCategory && Crm\Settings\Crm::isLiveFeedRecordsGenerationEnabled()) { CCrmSonetSubscription::RegisterSubscription( CCrmOwnerType::Contact, $ID, CCrmSonetSubscriptionType::Responsibility, $assignedByID ); } $logEventID = $isUntypedCategory ? CCrmLiveFeed::CreateLogEvent($liveFeedFields, CCrmLiveFeedEvent::Add, ['CURRENT_USER' => $userID]) : false; if ( $logEventID !== false && $assignedByID != $createdByID && $isUntypedCategory && CModule::IncludeModule("im") ) { $url = CCrmOwnerType::GetEntityShowPath(CCrmOwnerType::Contact, $ID); $serverName = (CMain::IsHTTPS() ? "https" : "http")."://".((defined("SITE_SERVER_NAME") && SITE_SERVER_NAME <> '') ? SITE_SERVER_NAME : COption::GetOptionString("main", "server_name", "")); $arMessageFields = array( "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, "TO_USER_ID" => $assignedByID, "FROM_USER_ID" => $createdByID, "NOTIFY_TYPE" => IM_NOTIFY_FROM, "NOTIFY_MODULE" => "crm", "LOG_ID" => $logEventID, //"NOTIFY_EVENT" => "contact_add", "NOTIFY_EVENT" => "changeAssignedBy", "NOTIFY_TAG" => "CRM|CONTACT_RESPONSIBLE|".$ID, "NOTIFY_MESSAGE" => GetMessage("CRM_CONTACT_RESPONSIBLE_IM_NOTIFY", Array("#title#" => "".htmlspecialcharsbx($arFields['FULL_NAME'])."")), "NOTIFY_MESSAGE_OUT" => GetMessage("CRM_CONTACT_RESPONSIBLE_IM_NOTIFY", Array("#title#" => htmlspecialcharsbx($arFields['FULL_NAME'])))." (".$serverName.$url.")" ); CIMNotify::Add($arMessageFields); } } //region Rise AfterAdd event $afterEvents = GetModuleEvents('crm', 'OnAfterCrmContactAdd'); while ($arEvent = $afterEvents->Fetch()) { ExecuteModuleEventEx($arEvent, array(&$arFields)); } //endregion if(isset($arFields['ORIGIN_ID']) && $arFields['ORIGIN_ID'] !== '') { $afterEvents = GetModuleEvents('crm', 'OnAfterExternalCrmContactAdd'); while ($arEvent = $afterEvents->Fetch()) { ExecuteModuleEventEx($arEvent, array(&$arFields)); } } } if ($result) { $item = $this->createPullItem($arFields); Crm\Integration\PullManager::getInstance()->sendItemAddedEvent( $item, [ 'TYPE' => self::$TYPE_NAME, 'SKIP_CURRENT_USER' => ($userID !== 0), 'CATEGORY_ID' => ($arFields['CATEGORY_ID'] ?? 0), ] ); } return $result; }