• Модуль: landing
  • Путь к файлу: ~/bitrix/modules/landing/lib/internals/site.php
  • Класс: BitrixLandingInternalsSiteTable
  • Вызов: SiteTable::prepareChange
static function prepareChange(EntityEvent $event, $actionType)
{
	$result = new EntityEventResult();
	$fields = $event->getParameter('fields');
	$primary = $event->getParameter('primary');
	$unsetFields = array();
	$modifyFields = array();
	$siteController = self::getSiteController();
	$deleteMode = false;

	self::$touchMode = isset($fields['TOUCH']) && $fields['TOUCH'] == 'Y';

	if ($actionType == self::ACTION_TYPE_ADD)
	{
		//@tmp log
		BitrixLandingDebug::log(
			$fields['TITLE'] ?? 'Noname',
			print_r([$fields, BitrixMainDiagHelper::getBackTrace(15)],  true),
			'LANDING_SITE_CREATE'
		);
	}

	// clear binding cache
	if (
		isset($fields['CODE']) ||
		isset($fields['TITLE']) ||
		isset($fields['DELETED'])
	)
	{
		if ($primary)
		{
			BitrixLandingBindingEntity::onSiteChange(
				$primary['ID']
			);
		}
	}

	if (
		isset($fields['DOMAIN_ID']) &&
		$fields['DOMAIN_ID'] === ''
	)
	{
		unset($fields['DOMAIN_ID']);
		$unsetFields[] = 'DOMAIN_ID';
	}

	// if delete, set unpublic always
	if (isset($fields['DELETED']))
	{
		$deleteMode = true;
		$modifyFields['ACTIVE'] = 'N';
		$fields['ACTIVE'] = 'N';
		// user try to restore site, check the limits
		if ($primary && $fields['DELETED'] == 'N')
		{
			$fields['TYPE'] = self::getValueByCode(
				$primary['ID'],
				$fields,
				'TYPE'
			);
			$check = Manager::checkFeature(
				Manager::FEATURE_CREATE_SITE,
				[
					'type' => $fields['TYPE'],
					'filter' => ['!ID' => $primary['ID']]
				]
			);
			if (!$check)
			{
				$result->setErrors([
					new EntityEntityError(
						RestrictionManager::getSystemErrorMessage('limit_sites_number'),
						'TOTAL_SITE_REACHED'
					)
				]);
				return $result;
			}
		}
		else if ($primary && $fields['DELETED'] == 'Y')
		{
			$fields['DOMAIN_PROVIDER'] = self::getValueByCode(
				$primary['ID'],
				$fields,
				'DOMAIN_PROVIDER'
			);
			if ($fields['DOMAIN_PROVIDER'] && ModuleManager::isModuleInstalled('bitrix24'))
			{
				$result->setErrors([
					new EntityEntityError(
						Loc::getMessage('LANDING_TABLE_ERROR_ACCESS_DENIED_DELETED'),
						'ACCESS_DENIED_DELETED'
					)
				]);
				return $result;
			}
		}
	}

	// check that TYPE is valid and allowed
	if (!$primary && isset($fields['TYPE']))
	{
		$allowedTypes = (array)BitrixLandingSiteType::getFilterType();
		if (!in_array($fields['TYPE'], $allowedTypes))
		{
			$result->setErrors(array(
				new EntityEntityError(
					Loc::getMessage('LANDING_TABLE_ERROR_ACCESS_DENIED_ADD'),
					'ACCESS_DENIED'
				)
			));
			return $result;
		}
	}

	// if domain id is not specified
	if (!$primary && !array_key_exists('DOMAIN_ID', $fields))
	{
		$fields['DOMAIN_ID'] = BitrixLandingSiteType::getDomainId();
		$modifyFields['DOMAIN_ID'] = $fields['DOMAIN_ID'];
	}

	// check rights
	if (isset($primary['ID']) && Rights::isOn())
	{
		$rights = Rights::getOperationsForSite(
			$primary['ID']
		);
		$freeAccessFields = [
			'CREATED_BY_ID',
			'MODIFIED_BY_ID',
			'DATE_CREATE',
			'DATE_MODIFY',
			'TOUCH'
		];
		if (in_array(Rights::ACCESS_TYPES['sett'], $rights))
		{
			$freeAccessFields = $fields;
			if (isset($freeAccessFields['ACTIVE']))
			{
				unset($freeAccessFields['ACTIVE']);
			}
			if (isset($freeAccessFields['DELETED']))
			{
				unset($freeAccessFields['DELETED']);
			}
			$freeAccessFields = array_keys($freeAccessFields);
		}
		if (in_array(Rights::ACCESS_TYPES['public'], $rights))
		{
			$freeAccessFields[] = 'ACTIVE';
		}
		if (in_array(Rights::ACCESS_TYPES['delete'], $rights))
		{
			$freeAccessFields[] = 'DELETED';
			$freeAccessFields[] = 'DOMAIN_PROVIDER';
			// allow unpublic in delete case
			if ($deleteMode)
			{
				$freeAccessFields[] = 'ACTIVE';
			}
		}
		foreach ($fields as $key => $val)
		{
			if (!in_array($key, $freeAccessFields))
			{
				$errMessage = Loc::getMessage(
					'LANDING_TABLE_ERROR_ACCESS_DENIED_' . $key
				);
				if (!$errMessage)
				{
					$errMessage = Loc::getMessage(
						'LANDING_TABLE_ERROR_ACCESS_DENIED'
					);
				}
				$result->setErrors(array(
					new EntityEntityError(
						$errMessage,
						'ACCESS_DENIED'
					)
				));
				return $result;
			}
		}
	}
	else if (Rights::isOn())
	{
		$hasAccess = Rights::hasAdditionalRight(
			Rights::ADDITIONAL_RIGHTS['create']
		);
		if (!$hasAccess)
		{
			$result->setErrors(array(
				new EntityEntityError(
					Loc::getMessage('LANDING_TABLE_ERROR_ACCESS_DENIED_ADD'),
					'ACCESS_DENIED'
				)
			));
			return $result;
		}
	}

	// additional fields save after
	if (array_key_exists('ADDITIONAL_FIELDS', $fields))
	{
		self::$additionalFields = $fields['ADDITIONAL_FIELDS'];
		$unsetFields[] = 'ADDITIONAL_FIELDS';
	}
	else
	{
		self::$additionalFields = array();
	}

	// check rights for site domain
	if (
		array_key_exists('DOMAIN_ID', $fields) &&
		!Manager::isB24()
	)
	{
		// for check rights call upper level
		$res = Domain::getList(array(
			'select' => array(
				'ID'
			),
			'filter' => array(
				'ID' => $fields['DOMAIN_ID']
			)
		));
		if (!$res->fetch())
		{
			$result->unsetFields($unsetFields);
			$result->setErrors(array(
				new EntityEntityError(
					Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_NOT_EXIST'),
					'DOMAIN_NOT_FOUND'
				)
			));
			return $result;
		}
	}

	// check active first (limit count)
	if (
		isset($fields['ACTIVE']) &&
		$fields['ACTIVE'] == 'Y'
	)
	{
		if ($primary)
		{
			$fields['TYPE'] = self::getValueByCode(
				$primary['ID'],
				$fields,
				'TYPE'
			);
		}
		else
		{
			$fields['TYPE'] = null;
		}
		$special = self::getValueByCode(
			$primary['ID'],
			$fields,
			'SPECIAL'
		);
		if ($special == 'Y')
		{
			$canPublicSite = true;
		}
		else
		{
			$domainProvider = self::getValueByCode(
				$primary['ID'],
				$fields,
				'DOMAIN_PROVIDER'
			);
			if ($domainProvider)
			{
				if (!RestrictionManager::isAllowed('limit_free_domen', ['trueOnNotNull' => true]))
				{
					$result->unsetFields($unsetFields);
					$result->setErrors(array(
						new EntityEntityError(
							RestrictionManager::getSystemErrorMessage('limit_free_domen'),
							'FREE_DOMAIN_IS_NOT_ALLOWED'
						)
					));
					return $result;
				}
			}
			$canPublicSite = Manager::checkFeature(
				Manager::FEATURE_PUBLICATION_SITE,
				$primary
				? array(
					'filter' => array(
						'!ID' => $primary['ID']
					),
					'type' => $fields['TYPE']
				)
				: array(
					'type' => $fields['TYPE']
				)
			);
		}
		if (!$canPublicSite)
		{
			$errCode = Manager::licenseIsFreeSite($fields['TYPE']) && !Manager::isFreePublicAllowed()
				? 'PUBLIC_SITE_REACHED_FREE'
				: 'PUBLIC_SITE_REACHED';
			$msgCode = Manager::licenseIsFreeSite($fields['TYPE']) && !Manager::isFreePublicAllowed()
				? 'limit_sites_number_free'
				: 'limit_sites_number';
			$result->unsetFields($unsetFields);
			$result->setErrors(array(
				new EntityEntityError(
					RestrictionManager::getSystemErrorMessage($msgCode),
					$errCode
				)
			));
			return $result;
		}
	}

	// prepare CODE - base part of URL
	if (array_key_exists('CODE', $fields))
	{
		$fields['CODE'] = trim(trim(trim($fields['CODE']), '/'));
		if (mb_strpos($fields['CODE'], '/') !== false)
		{
			$result->unsetFields($unsetFields);
			$result->setErrors(array(
				new EntityEntityError(
					Loc::getMessage('LANDING_TABLE_ERROR_SITE_SLASH_IS_NOT_ALLOWED'),
					'SLASH_IS_NOT_ALLOWED'
				)
			));
			return $result;
		}
		// generate CODE from TITLE, if CODE is empty (in create)
		if (!$fields['CODE'])
		{
			$fields['CODE'] = CUtil::translit(
				(array_key_exists('TITLE', $fields) && trim($fields['TITLE']))
				? $fields['TITLE'] : 'site',
				LANGUAGE_ID
			);
			if (!$fields['CODE'])
			{
				$fields['CODE'] = randString(12);
			}
		}
		// only digits is disallowed
		if (preg_match('/^[d]+$/', $fields['CODE']))
		{
			$fields['CODE'] = 'site' . $fields['CODE'];
		}
		$fields['CODE'] = mb_substr($fields['CODE'], 0, 253);
		$domainId = null;
		// get domain id if no exists
		if (!array_key_exists('DOMAIN_ID', $fields) && $primary)
		{
			$domainId = self::getValueByCode(
				$primary['ID'],
				$fields,
				'DOMAIN_ID'
			);
		}
		else if (array_key_exists('DOMAIN_ID', $fields))
		{
			$domainId = $fields['DOMAIN_ID'];
		}
		// make CODE unique in one domain
		if ($domainId !== null)
		{
			$checkCount = 1;
			$originalCode = $fields['CODE'];
			do
			{
				$unique = self::checkUniqueInDomain(
					'/' . $fields['CODE'] . '/',
					$primary ? $primary['ID'] : 0,
					$domainId
				);
				if (!$unique)
				{
					$fields['CODE'] = $originalCode . (++$checkCount);
				}
			} while (!$unique);
		}
		$fields['CODE'] = '/' . $fields['CODE'] . '/';
		$modifyFields['CODE'] = $fields['CODE'];
	}

	// create/get domain by name (reg in b24.site if Bitrix24)
	if (
		array_key_exists('DOMAIN_ID', $fields) &&
		$fields['DOMAIN_ID'] !== 0 &&
		(
			preg_replace('/[d]/', '', trim($fields['DOMAIN_ID'])) != '' ||
			Manager::isB24()
		)
	)
	{
		$domainId = 0;
		$domainName = mb_strtolower(trim($fields['DOMAIN_ID']));
		$domainNameOld = '';

		// fix for full name
		if ($domainName != '')
		{
			$puny = new CBXPunycode;
			$domainName = $puny->encode($domainName);
			// check correct name
			if (!preg_match('/^[a-z0-9-.]+.[a-z0-9-]{2,20}$/i', $domainName))
			{
				$result->unsetFields($unsetFields);
				$result->setErrors(array(
					new EntityEntityError(
						Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_IS_INCORRECT2'),
						'DOMAIN_IS_INCORRECT'
					)
				));
				return $result;
			}
		}

		// if add - unset domain_id, else - get current domain of site
		if ($actionType == self::ACTION_TYPE_ADD)
		{
			$modifyFields['DOMAIN_ID'] = 0;
		}
		else
		{
			if ($primary)
			{
				$res = self::getList(array(
					'select' => array(
						'DOMAIN_ID',
						'DOMAIN_NAME' => 'DOMAIN.DOMAIN'
					),
					'filter' => array(
						'ID' => $primary['ID'],
						'CHECK_PERMISSIONS' => 'N'
					)
				));
				if ($row = $res->fetch())
				{
					$domainNameOld = mb_strtolower($row['DOMAIN_NAME']);
					$domainId = $row['DOMAIN_ID'];
				}
			}
			$unsetFields[] = 'DOMAIN_ID';
		}

		// check CODE unique in site group
		if ($domainId && array_key_exists('CODE', $fields))
		{
			$unique = self::checkUniqueInDomain(
				$fields['CODE'],
				$primary ? $primary['ID'] : 0,
				$domainId
			);
			if (!$unique)
			{
				$result->unsetFields($unsetFields);
				$result->setErrors(array(
					new EntityEntityError(
						Loc::getMessage('LANDING_TABLE_ERROR_SITE_CODE_IS_NOT_UNIQUE2'),
						'CODE_IS_NOT_UNIQUE'
					)
				));
				return $result;
			}
		}

		// if domain name now changed
		if (
			$domainName != $domainNameOld ||
			$actionType == self::ACTION_TYPE_ADD
		)
		{
			$domainExist = false;

			// check domain exist
			if ($domainName != '')
			{
				$resDomain = Domain::getList(array(
					'select' => array(
						'ID'
					),
					'filter' => array(
						'=DOMAIN' => $domainName
					)
				));
				if ($rowDomain = $resDomain->fetch())
				{
					$domainExist = true;
					$resSite = Site::getList(array(
						'select' => array(
							'ID'
						),
						'filter' => array(
							'DOMAIN_ID' => $rowDomain['ID'],
							'=DELETED' => 'Y',
							'CHECK_PERMISSIONS' => 'N'
						)
	  				));
					if ($resSite->fetch())
					{
						$result->setErrors(
							array(
								new EntityEntityError(
									Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_EXIST_TRASH'),
									'DOMAIN_EXIST_TRASH'
								)
							)
						);
						return $result;
					}
				}
				elseif (Manager::isB24())
				{
					try
					{
						$domainExist = $siteController::isDomainExists($domainName);
					}
					catch (SystemException $ex)
					{
						$result->unsetFields($unsetFields);
						$result->setErrors(array(
							self::customizeControllerError($ex)
						));
						return $result;
					}
				}
			}
			if ($domainExist)
			{
				$result->unsetFields($unsetFields);
				if (self::checkBitrixUse($domainName))
				{
					$result->setErrors(
						array(
							new EntityEntityError(
								Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_BITRIX_DISABLE'),
								'DOMAIN_DISABLE'
							)
						)
					);
				}
				else
				{
					$result->setErrors(
						array(
							new EntityEntityError(
								Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_EXIST'),
								'DOMAIN_EXIST'
							)
						)
					);
				}

				return $result;
			}

			// check available external service
			try
			{
				$siteController::isDomainExists('repo.bitrix24.site');
			}
			catch (SystemException $ex)
			{
				$result->unsetFields($unsetFields);
				$result->setErrors(array(
					self::customizeControllerError($ex)
				));
				return $result;
			}

			// handler on add / update
			$eventManager = BitrixMainEventManager::getInstance();
			$eventManager->addEventHandler(
				'landing',
				$actionType == self::ACTION_TYPE_ADD
				? '\' . __NAMESPACE__ . '\Site::onAfterAdd'
				: '\' . __NAMESPACE__ . '\Site::onAfterUpdate',
				function(EntityEvent $event) use ($domainId, $domainName, $domainNameOld, $result, $unsetFields, $siteController)
				{
					$primary = $event->getParameter('primary');
					$fields = $event->getParameter('fields');

					if ($primary)
					{
						// create domain
						if (!$domainId)
						{
							// action in b24
							if (Manager::isB24())
							{
								$publicUrl = Manager::getPublicationPath(
									$primary['ID']
								);
								try
								{
									$row = self::getList(array(
										'select' => array(
											'TYPE'
										),
										'filter' => array(
											'ID' => $primary['ID']
										)
								 	))->fetch();
									if ($row['TYPE'] == 'STORE')// fix for controller
									{
										$row['TYPE'] = 'shop';
									}
									if ($domainName)
									{
										$siteController::addDomain(
											$domainName,
											$publicUrl,
											'N',
											$row['TYPE'],
											self::prepareLangForController(Manager::getZone())
										);
									}
									else
									{
										$domainName = $siteController::addRandomDomain(
											$publicUrl,
											$row['TYPE'],
											self::prepareLangForController(Manager::getZone())
										);
									}
								}
								catch (SystemException $ex)
								{
									$result->unsetFields($unsetFields);
									$result->setErrors(array(
										self::customizeControllerError($ex)
									));
									return $result;
								}
							}
							// add new domain
							if ($domainName)
							{
								$resDomain = Domain::add(array(
									'ACTIVE' => 'Y',
									'DOMAIN' => $domainName
								));
								$domainId = $resDomain->getId();
								if ($domainId)
								{
									SiteTable::$disableCallback = true;
									SiteTable::update($primary['ID'], array(
										'DOMAIN_ID' => $domainId
									));
									SiteTable::$disableCallback = false;
								}
							}
						}
						// update domain
						else
						{
							$res = Domain::update($domainId, array(
								'DOMAIN' => $domainName,
								'FAIL_COUNT' => null,
								'PROVIDER' => null
							));
							if ($res->isSuccess())
							{
								if (Manager::isB24())
								{
									try
									{
										$publicUrl = Manager::getPublicationPath(
											$primary['ID']
										);
										$siteController::updateDomain(
											$domainNameOld,
											$domainName,
											$publicUrl
										);
									}
									catch (SystemException $ex)
									{
										$result->unsetFields($unsetFields);
										$result->setErrors(array(
											self::customizeControllerError($ex)
										));
										return $result;
									}
								}
							}
						}
					}
				}
			);
		}
	}

	$result->unsetFields($unsetFields);
	$result->modifyFields($modifyFields);

	return $result;
}