Current Path : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/modules/landing/lib/internals/ |
Current File : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/modules/landing/lib/internals/site.php |
<?php namespace Bitrix\Landing\Internals; use \Bitrix\Main\Localization\Loc; use \Bitrix\Main\Entity; use \Bitrix\Main\ModuleManager; use \Bitrix\Main\SystemException; use \Bitrix\Landing\Manager; use \Bitrix\Landing\Site; use \Bitrix\Landing\Domain; use \Bitrix\Landing\Rights; use \Bitrix\Landing\Role; use \Bitrix\Landing\Restriction; Loc::loadMessages(__FILE__); /** * Class SiteTable * * DO NOT WRITE ANYTHING BELOW THIS * * <<< ORMENTITYANNOTATION * @method static EO_Site_Query query() * @method static EO_Site_Result getByPrimary($primary, array $parameters = array()) * @method static EO_Site_Result getById($id) * @method static EO_Site_Result getList(array $parameters = array()) * @method static EO_Site_Entity getEntity() * @method static \Bitrix\Landing\Internals\EO_Site createObject($setDefaultValues = true) * @method static \Bitrix\Landing\Internals\EO_Site_Collection createCollection() * @method static \Bitrix\Landing\Internals\EO_Site wakeUpObject($row) * @method static \Bitrix\Landing\Internals\EO_Site_Collection wakeUpCollection($rows) */ class SiteTable extends Entity\DataManager { /** * For save callbacks. */ const ACTION_TYPE_ADD = 'add'; /** * For save callbacks. */ const ACTION_TYPE_UPDATE = 'update'; /** * Stored fields for save separate. * @var array */ protected static $additionalFields = array(); /** * Disable callback. * @var boolean */ protected static $disableCallback = false; /** * In current iteration we change date only. * @var bool */ protected static $touchMode = false; /** * Returns DB table name for entity. * @return string */ public static function getTableName() { return 'b_landing_site'; } /** * Returns entity map definition. * @return array */ public static function getMap() { $types = \Bitrix\Landing\Site::getTypes(); $typesKeys = array_keys($types); return array( 'ID' => new Entity\IntegerField('ID', array( 'primary' => true, 'autocomplete' => true, 'title' => 'ID' )), 'CODE' => new Entity\StringField('CODE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SITE_CODE'), 'required' => true )), 'ACTIVE' => new Entity\StringField('ACTIVE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SITE_ACTIVE'), 'default_value' => 'Y' )), 'DELETED' => new Entity\StringField('DELETED', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_LANDING_DELETED'), 'default_value' => 'N' )), 'TITLE' => new Entity\StringField('TITLE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SITE_TITLE'), 'required' => true )), 'XML_ID' => new Entity\StringField('XML_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_XML_ID') )), 'DESCRIPTION' => new Entity\StringField('DESCRIPTION', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_DESCRIPTION') )), 'TYPE' => new Entity\EnumField('TYPE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_TYPE'), 'values' => $typesKeys, 'default_value' => array_shift($typesKeys) )), 'TPL_ID' => new Entity\IntegerField('TPL_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_TPL_ID'), 'default_value' => 0 )), 'TPL_CODE' => new Entity\StringField('TPL_CODE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_TPL_CODE') )), 'DOMAIN_ID' => new Entity\IntegerField('DOMAIN_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_DOMAIN_ID'), //'required' => true )), 'DOMAIN' => new Entity\ReferenceField( 'DOMAIN', 'Bitrix\Landing\Internals\DomainTable', array('=this.DOMAIN_ID' => 'ref.ID') ), 'SMN_SITE_ID' => new Entity\StringField('SMN_SITE_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SMN_SITE_ID') )), 'LANDING_ID_INDEX' => new Entity\IntegerField('LANDING_ID_INDEX', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_LANDING_ID_INDEX') )), 'LANDING_ID_404' => new Entity\IntegerField('LANDING_ID_404', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_LANDING_ID_404') )), 'LANDING_ID_503' => new Entity\IntegerField('LANDING_ID_503', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_LANDING_ID_503') )), 'LANG' => new Entity\IntegerField('LANG', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_LANG') )), 'SPECIAL' => new Entity\StringField('SPECIAL', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SPECIAL'), 'default_value' => 'N' )), 'VERSION' => new Entity\IntegerField('VERSION', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_SITE_VERSION'), 'default_value' => 2 )), 'CREATED_BY_ID' => new Entity\IntegerField('CREATED_BY_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_CREATED_BY_ID'), 'required' => true )), 'CREATED_BY' => new Entity\ReferenceField( 'CREATED_BY', 'Bitrix\Main\UserTable', array('=this.CREATED_BY_ID' => 'ref.ID') ), 'MODIFIED_BY_ID' => new Entity\IntegerField('MODIFIED_BY_ID', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_MODIFIED_BY_ID'), 'required' => true )), 'MODIFIED_BY' => new Entity\ReferenceField( 'MODIFIED_BY', 'Bitrix\Main\UserTable', array('=this.MODIFIED_BY_ID' => 'ref.ID') ), 'DATE_CREATE' => new Entity\DatetimeField('DATE_CREATE', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_DATE_CREATE'), 'required' => true )), 'DATE_MODIFY' => new Entity\DatetimeField('DATE_MODIFY', array( 'title' => Loc::getMessage('LANDING_TABLE_FIELD_DATE_MODIFY'), 'required' => true )) ); } /** * Return site controller class, or pseudo. * @return string */ protected static function getSiteController() { return Manager::getExternalSiteController(); } /** * Check CODE unique in site group. * @param string $code Site code. * @param int $currentId Current site id. * @param int $domainId Domain id. * @return boolean */ protected static function checkUniqueInDomain($code, $currentId, $domainId) { $res = self::getList(array( 'select' => array( 'ID' ), 'filter' => array( '!ID' => $currentId, 'DOMAIN_ID' => $domainId, '=CODE' => $code, '=DELETED' => ['Y', 'N'], 'CHECK_PERMISSIONS' => 'N' ) )); return $res->fetch() ? false : true; } /** * Is bitrix24.site subdomain? * @param string $domainName Domain name. * @return boolean */ protected static function isB24Domain($domainName) { return Domain::getBitrix24Subdomain($domainName) !== null; } /** * Customize controller message. * @param SystemException $ex Exception from controller. * @return Entity\EntityError */ protected static function customizeControllerError(SystemException $ex) { $code = str_replace(' ', '', $ex->getMessage()); $code = mb_strtoupper($code); $message = Loc::getMessage('LANDING_CONTROLLER_ERROR_' . $code); $message = $message ? $message : $ex->getMessage(); return new Entity\EntityError( $message, 'CONTROLLER_ERROR_' . $code ); } /** * On controller must save only correctly (existing) languages * @param string $lang * @return string */ protected static function prepareLangForController(string $lang): string { $replaces = [ 'in' => 'en', 'hi' => 'en', ]; return in_array($lang, array_keys($replaces)) ? $replaces[$lang] : $lang; } /** * Check 'bitrix'-named domain. * @param string $domainName Domain name. * @return boolean */ public static function checkBitrixUse($domainName) { $isB24Domain = self::isB24Domain($domainName); $disableMask = '/bitrix[^\.]*\.bitrix[^\.]+\.[a-z]+$/'; if ( Manager::isB24() && ( $isB24Domain && preg_match_all($disableMask, $domainName) || !$isB24Domain && mb_strpos($domainName, 'bitrix') !== false ) ) { return true; } return false; } /** * Set additional access filter. * @param mixed $params ORM params. * @return mixed */ public static function setAccessFilter($params) { if ( isset($params['filter']['CHECK_PERMISSIONS']) && $params['filter']['CHECK_PERMISSIONS'] == 'N' ) { return $params; } // build filter $allowedSites = Rights::getAllowedSites(); $buildFilter = Rights::getAccessFilter( $allowedSites ? ['ID' => $allowedSites] : [] ); if (empty($buildFilter)) { return $params; } // create runtime/filter keys if no exists if ( !isset($params['filter']) || !is_array($params['filter']) ) { $params['filter'] = []; } if ( !isset($params['runtime']) || !is_array($params['runtime']) ) { $params['runtime'] = []; } if ( !isset($params['group']) || !is_array($params['group']) ) { $params['group'] = []; } //$tasks = Rights::getAccessTasksReferences(); //$readCode = Rights::ACCESS_TYPES['denied']; $extendedRights = Rights::isExtendedMode(); static $expectedRoles = null; if ($expectedRoles === null) { $expectedRoles = Role::getExpectedRoleIds(); } // create runtime fields $runtimeParams = []; $runtimeParams[] = [ 'LOGIC' => 'OR', '=this.ID' => 'ref.ENTITY_ID', '=ref.ENTITY_ID' => [0] ]; if ($extendedRights) { $runtimeParams['=ref.ROLE_ID'] = [0]; } else { $runtimeParams['=ref.ENTITY_TYPE'] = ['?', Rights::ENTITY_TYPE_SITE]; $runtimeParams['@ref.ROLE_ID'] = [implode(',', $expectedRoles)]; } $params['runtime'][] = new Entity\ReferenceField( 'RIGHTS', 'Bitrix\Landing\Internals\RightsTable', $runtimeParams, ['join_type' => 'INNER'] ); $params['group'][] = 'ID'; // build filter $params['filter'][] = $buildFilter; return $params; } /** * Returns value from row by key code. If key don't exist, get from DB. * @param int $id Site id. * @param array $fields Site row fields. * @param string $code Key code of row. * @return mixed */ private static function getValueByCode($id, array $fields, $code) { static $data = []; if (array_key_exists($id, $data)) { return isset($data[$id][$code]) ? $data[$id][$code] : null; } if (array_key_exists($code, $fields)) { return $fields[$code]; } $res = self::getList([ 'select' => [ '*', 'DOMAIN_NAME' => 'DOMAIN.DOMAIN', 'DOMAIN_PROVIDER' => 'DOMAIN.PROVIDER' ], 'filter' => [ 'ID' => $id, 'CHECK_PERMISSIONS' => 'N', '=DELETED' => ['Y', 'N'] ] ]); if ($row = $res->fetch()) { $data[$id] = $row; } return isset($data[$id][$code]) ? $data[$id][$code] : null; } /** * Prepare change to save. * @param Entity\Event $event Event instance. * @param string $actionType Action type: add / update. * @return Entity\EventResult */ protected static function prepareChange(Entity\Event $event, $actionType) { $result = new Entity\EventResult(); $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 \Bitrix\Landing\Debug::log( $fields['TITLE'] ?? 'Noname', print_r([$fields, \Bitrix\Main\Diag\Helper::getBackTrace(15)], true), 'LANDING_SITE_CREATE' ); } // clear binding cache if ( isset($fields['CODE']) || isset($fields['TITLE']) || isset($fields['DELETED']) ) { if ($primary) { \Bitrix\Landing\Binding\Entity::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 Entity\EntityError( Restriction\Manager::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 Entity\EntityError( 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)\Bitrix\Landing\Site\Type::getFilterType(); if (!in_array($fields['TYPE'], $allowedTypes)) { $result->setErrors(array( new Entity\EntityError( 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'] = \Bitrix\Landing\Site\Type::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 Entity\EntityError( $errMessage, 'ACCESS_DENIED' ) )); return $result; } } } else if (Rights::isOn()) { $hasAccess = Rights::hasAdditionalRight( Rights::ADDITIONAL_RIGHTS['create'] ); if (!$hasAccess) { $result->setErrors(array( new Entity\EntityError( 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 Entity\EntityError( 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 (!Restriction\Manager::isAllowed('limit_free_domen', ['trueOnNotNull' => true])) { $result->unsetFields($unsetFields); $result->setErrors(array( new Entity\EntityError( Restriction\Manager::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 Entity\EntityError( Restriction\Manager::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 Entity\EntityError( 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 Entity\EntityError( 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 Entity\EntityError( 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 Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_EXIST_TRASH'), 'DOMAIN_EXIST_TRASH' ) ) ); return $result; } } elseif (Manager::isB24()) { try { //todo: revert changes after change .by domain if ( !str_ends_with($domainName, '.b24site.online') && !str_ends_with($domainName, '.b24shop.online') ) { $domainExist = $siteController::isDomainExists($domainName); } else { $byDomainName = ''; if (str_ends_with($domainName, '.b24site.online')) { $byDomainName = str_replace('.b24site.online', '.bitrix24site.by', $domainName); } if (str_ends_with($domainName, '.b24shop.online')) { $byDomainName = str_replace('.b24shop.online', '.bitrix24shop.by', $domainName); } if ($byDomainName !== '' && $siteController::isDomainExists($byDomainName)) { $domainExist = true; } else { $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 Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_DOMAIN_BITRIX_DISABLE'), 'DOMAIN_DISABLE' ) ) ); } else { $result->setErrors( array( new Entity\EntityError( 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 = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( 'landing', $actionType == self::ACTION_TYPE_ADD ? '\\' . __NAMESPACE__ . '\\Site::onAfterAdd' : '\\' . __NAMESPACE__ . '\\Site::onAfterUpdate', function(Entity\Event $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; } /** * Switch domains between two sites. Returns true on success. * @param int $siteId1 First site id. * @param int $siteId2 Second site id. * @return bool */ public static function switchDomain(int $siteId1, int $siteId2): bool { $result = false; self::$disableCallback = true; $domains = []; $res = self::getList([ 'select' => [ 'ID', 'TYPE', 'LANG', 'DOMAIN_ID', 'DOMAIN_NAME' => 'DOMAIN.DOMAIN' ], 'filter' => [ 'ID' => [$siteId1, $siteId2] ] ]); while ($row = $res->fetch()) { $domains[] = [ 'ID' => $row['ID'], 'TYPE' => $row['TYPE'], 'LANG' => $row['LANG'], 'DOMAIN_ID' => $row['DOMAIN_ID'], 'DOMAIN_NAME' => $row['DOMAIN_NAME'] ]; } if (count($domains) == 2) { $res1 = self::update($domains[0]['ID'], [ 'DOMAIN_ID' => $domains[1]['DOMAIN_ID'] ]); $res2 = self::update($domains[1]['ID'], [ 'DOMAIN_ID' => $domains[0]['DOMAIN_ID'] ]); $result = $res1->isSuccess() && $res2->isSuccess(); } self::$disableCallback = false; // switch domain for bitrix24 if ($result && Manager::isB24()) { $siteController = self::getSiteController(); try { for ($i = 0; $i <= 1; $i++) { $siteController::deleteDomain($domains[$i]['DOMAIN_NAME']); $siteController::addDomain( $domains[$i]['DOMAIN_NAME'], Manager::getPublicationPath($domains[$i == 0 ? 1 : 0]['ID']), 'Y', ($domains[$i]['TYPE'] == 'STORE') ? 'shop' : $domains[$i]['TYPE'], self::prepareLangForController($domains[$i]['LANG'] ?? Manager::getZone()) ); } } catch (SystemException $ex) {} } return $result; } /** * Sets new random domain to site. * @param int $siteId Site id. * @return bool */ public static function randomizeDomain(int $siteId): bool { $res = self::getList([ 'select' => [ 'ID', 'TYPE', 'DOMAIN_ID', 'DOMAIN_NAME' => 'DOMAIN.DOMAIN' ], 'filter' => [ 'ID' => $siteId ] ]); if ($row = $res->fetch()) { $siteController = self::getSiteController(); $publicUrl = Manager::getPublicationPath($row['ID']); try { $siteController::deleteDomain($row['DOMAIN_NAME']); $domainName = $siteController::addRandomDomain( $publicUrl, ($row['TYPE'] == 'STORE') ? 'shop' : $row['TYPE'], self::prepareLangForController(Manager::getZone()) ); if ($domainName) { $res = Domain::update($row['DOMAIN_ID'], [ 'DOMAIN' => $domainName, 'FAIL_COUNT' => null, 'PROVIDER' => null ]); return $res->isSuccess(); } } catch (SystemException $ex) {} } return false; } /** * Before add handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function OnBeforeAdd(Entity\Event $event) { $result = new Entity\EventResult(); if (self::$disableCallback) { return $result; } $fields = $event->getParameter('fields'); // check site limit if ( !Manager::checkFeature( Manager::FEATURE_CREATE_SITE, array( 'type' => $fields['TYPE'] ) ) ) { $result->unsetFields(array('ADDITIONAL_FIELDS')); $result->setErrors(array( new Entity\EntityError( Restriction\Manager::getSystemErrorMessage('limit_sites_number'), 'SITE_LIMIT_REACHED' ) )); return $result; } return self::prepareChange($event, self::ACTION_TYPE_ADD); } /** * Before update handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function OnBeforeUpdate(Entity\Event $event) { if (self::$disableCallback) { return new Entity\EventResult(); } return self::prepareChange($event, self::ACTION_TYPE_UPDATE); } /** * Save additional fields after add / update. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ protected static function saveAdditionalFields(Entity\Event $event) { $result = new Entity\EventResult(); if (!empty(self::$additionalFields)) { $primary = $event->getParameter('primary'); Site::saveAdditionalFields( $primary['ID'], self::$additionalFields ); } return $result; } /** * Get entity rows. * @param array $params Params array. * @return \Bitrix\Main\ORM\Query\Result */ public static function getList(array $params = array()) { if ( !isset($params['filter']) || !is_array($params['filter']) ) { $params['filter'] = array(); } if ( !isset($params['filter']['DELETED']) && !isset($params['filter']['=DELETED']) ) { $params['filter']['=DELETED'] = 'N'; } if (isset($params['filter']['CHECK_PERMISSIONS'])) { unset($params['filter']['CHECK_PERMISSIONS']); } // strict filter by type $type = null; if (isset($params['filter']['TYPE'])) { $type = $params['filter']['TYPE']; unset($params['filter']['TYPE']); } if (isset($params['filter']['=TYPE'])) { $type = $params['filter']['=TYPE']; unset($params['filter']['=TYPE']); } $allowedTypes = \Bitrix\Landing\Site\Type::getFilterType(); $params['filter']['=TYPE'] = (!is_array($type) && in_array($type, (array)$allowedTypes)) ? $type : $allowedTypes; return parent::getList($params); } /** * After add handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function OnAfterAdd(Entity\Event $event) { if (self::$disableCallback) { return true; } return self::saveAdditionalFields($event); } /** * After update handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function OnAfterUpdate(Entity\Event $event) { if (self::$disableCallback) { return true; } // for B24 we must update domain if (Manager::isB24() && !self::$touchMode) { static $domainUpdated = []; $primary = $event->getParameter('primary'); if (!in_array($primary['ID'], $domainUpdated)) { $domainUpdated[] = $primary['ID']; $siteController = self::getSiteController(); $res = self::getList([ 'select' => [ 'ACTIVE', 'DELETED', 'DOMAIN_NAME' => 'DOMAIN.DOMAIN', 'LANG' ], 'filter' => [ 'ID' => $primary['ID'], '=DELETED' => ['Y', 'N'], 'CHECK_PERMISSIONS' => 'N', '>DOMAIN_ID' => 0 ] ]); if ($row = $res->fetch()) { try { // now external domains always are active $siteController::activateDomain( $row['DOMAIN_NAME'], 'Y', self::prepareLangForController($row['LANG'] ?? Manager::getZone()) ); } catch (\Bitrix\Main\SystemException $ex) {} } } } return self::saveAdditionalFields($event); } /** * Before delete handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function OnBeforeDelete(Entity\Event $event) { if (self::$disableCallback) { return true; } $result = new Entity\EventResult(); $primary = $event->getParameter('primary'); $siteController = self::getSiteController(); if ($primary) { // check delete access $hasAccess = Rights::hasAccessForSite( $primary['ID'], Rights::ACCESS_TYPES['delete'], true ); if (!$hasAccess) { $result->setErrors(array( new Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_ACCESS_DENIED_DELETED'), 'ACCESS_DENIED' ) )); return $result; } // check if site is not empty $res = LandingTable::getList(array( 'select' => array( 'ID' ), 'filter' => array( 'SITE_ID' => $primary['ID'], 'CHECK_PERMISSIONS' => 'N' ) )); if ($res->fetch()) { $result->setErrors(array( new Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_SITE_IS_NOT_EMPTY'), 'SITE_IS_NOT_EMPTY' ) )); return $result; } // check lock status if (\Bitrix\Landing\Lock::isSiteDeleteLocked($primary['ID'])) { $result->setErrors(array( new Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_SITE_IS_LOCK'), 'SITE_IS_LOCK' ) )); return $result; } // delete in b24.site if (Manager::isB24()) { $res = self::getList(array( 'select' => array( 'DOMAIN_ID', 'DOMAIN_NAME' => 'DOMAIN.DOMAIN', 'DOMAIN_PROVIDER' => 'DOMAIN.PROVIDER' ), 'filter' => array( 'ID' => $primary['ID'], 'DELETED' => ['Y', 'N'], 'CHECK_PERMISSIONS' => 'N' ) )); if ($row = $res->fetch()) { if ($row['DOMAIN_PROVIDER'] && ModuleManager::isModuleInstalled('bitrix24')) { $result->setErrors([ new Entity\EntityError( Loc::getMessage('LANDING_TABLE_ERROR_ACCESS_DENIED_DELETED'), 'ACCESS_DENIED_DELETED' ) ]); return $result; } $domainId = $row['DOMAIN_ID']; $domainName = $row['DOMAIN_NAME']; $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( 'landing', '\\' . __NAMESPACE__ . '\\Site::onAfterDelete', function(Entity\Event $event) use ($domainId, $domainName, $result, $siteController) { $res = self::getList(array( 'select' => array( 'ID' ), 'filter' => array( 'DOMAIN_ID' => $domainId, 'DELETED' => ['Y', 'N'] ) )); if (!$res->fetch()) { DomainTable::delete($domainId); try { $siteController::deleteDomain($domainName); } catch (SystemException $ex) { $result->setErrors(array( self::customizeControllerError($ex) )); return $result; } } } ); } } } return $result; } /** * After delete handler. * @param Entity\Event $event Event instance. * @return Entity\EventResult */ public static function onAfterDelete(Entity\Event $event) { $result = new Entity\EventResult(); $primary = $event->getParameter('primary'); if (self::$disableCallback) { return $result; } // delete all inner landings if ($primary) { Rights::setOff(); $res = LandingTable::getList(array( 'select' => array( 'ID' ), 'filter' => array( 'SITE_ID' => $primary['ID'] ) )); while ($row = $res->fetch()) { \Bitrix\Landing\Landing::delete($row['ID'], true); } \Bitrix\Landing\Syspage::deleteForSite($primary['ID']); \Bitrix\Landing\File::deleteFromSite($primary['ID']); \Bitrix\Landing\Hook::deleteForSite($primary['ID']); \Bitrix\Landing\TemplateRef::setForSite($primary['ID'], []); \Bitrix\Landing\UrlRewrite::removeForSite($primary['ID']); \Bitrix\Landing\Rights::setOperationsForSite($primary['ID'], []); \Bitrix\Landing\Folder::deleteForSite($primary['ID']); \Bitrix\Landing\Site\Cookies::removeAgreementsForSite($primary['ID']); BindingTable::siteClear($primary['ID']); if (\Bitrix\Main\Loader::includeModule('ai')) { \Bitrix\AI\Context::clearContext([ "image_site_{$primary['ID']}", "text_site_{$primary['ID']}", ]); } Rights::setOn(); } return $result; } }