Your IP : 18.191.135.39


Current Path : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/main/lib/
Upload File :
Current File : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/main/lib/userfield.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2014 Bitrix
 */

namespace Bitrix\Main;

use Bitrix\Main\Entity;
use Bitrix\Main\Type;

/**
 * Entity representation of UserFields.
 * @package bitrix
 * @subpackage main
 */
class UserFieldTable extends Entity\DataManager
{
	// to use in uts serialized fields
	const MULTIPLE_DATE_FORMAT = 'Y-m-d';
	const MULTIPLE_DATETIME_FORMAT = 'Y-m-d H:i:s';

	public static function getMap()
	{
		return array(
			'ID' => array(
				'data_type' => 'integer',
				'primary' => true,
				'autocomplete' => true,
			),
			'ENTITY_ID' => array(
				'data_type' => 'string'
			),
			'FIELD_NAME' => array(
				'data_type' => 'string'
			),
			'USER_TYPE_ID' => array(
				'data_type' => 'string'
			),
			'XML_ID' => array(
				'data_type' => 'string'
			),
			'SORT' => array(
				'data_type' => 'integer'
			),
			'MULTIPLE' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'MANDATORY' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'SHOW_FILTER' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'SHOW_IN_LIST' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'EDIT_IN_LIST' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'IS_SEARCHABLE' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y')
			),
			'SETTINGS' => array(
				'data_type' => 'text',
				'serialized' => true
			)
		);
	}

	/**
	 * @param array $data
	 *
	 * @return Entity\AddResult|void
	 * @throws NotImplementedException
	 */
	public static function add(array $data)
	{
		throw new NotImplementedException('Use \CUserTypeEntity API instead.');
	}

	/**
	 * @param mixed $primary
	 * @param array $data
	 *
	 * @return Entity\UpdateResult|void
	 * @throws NotImplementedException
	 */
	public static function update($primary, array $data)
	{
		throw new NotImplementedException('Use \CUserTypeEntity API instead.');
	}

	/**
	 * @param mixed $primary
	 *
	 * @return Entity\DeleteResult|void
	 * @throws NotImplementedException
	 */
	public static function delete($primary)
	{
		throw new NotImplementedException('Use \CUserTypeEntity API instead.');
	}

	/**
	 * @param Entity\Base $entity
	 * @param             $ufId
	 *
	 * @throws ArgumentException
	 */
	public static function attachFields(Entity\Base $entity, $ufId)
	{
		global $USER_FIELD_MANAGER;

		$utsFields = array();
		$utsFieldNames = array();

		$utmFields = array();
		$utmFieldNames = array();

		$fields = $USER_FIELD_MANAGER->getUserFields($ufId);

		foreach ($fields as $field)
		{
			if ($field['MULTIPLE'] === 'Y')
			{
				$utmFields[] = $field;
				$utmFieldNames[$field['FIELD_NAME']] = true;
			}
			else
			{
				$utsFields[] = $field;
				$utsFieldNames[$field['FIELD_NAME']] = true;
			}
		}

		if (!empty($utsFields) || !empty($utmFields))
		{
			// create uts entity & put fields into it
			$utsEntity = static::createUtsEntity($entity, $utsFields, $utmFields);

			// create reference to uts entity
			$utsReference = new Entity\ReferenceField('UTS_OBJECT', $utsEntity->getDataClass(), array(
				'=this.ID' => 'ref.VALUE_ID'
			));

			$entity->addField($utsReference);

			// add UF_* aliases
			foreach ($fields as $userfield)
			{
				$utsFieldName = $userfield['FIELD_NAME'];

				/** @var Entity\ScalarField $utsField */
				$utsField = $utsEntity->getField($utsFieldName);

				$aliasField = new Entity\ExpressionField(
					$utsFieldName,
					'%s',
					'UTS_OBJECT.'.$utsFieldName,
					array('data_type' => get_class($utsField))
				);

				if ($userfield['MULTIPLE'] == 'Y')
				{
					static::setMultipleFieldSerialization($aliasField, $userfield);
				}

				$entity->addField($aliasField);
			}


			if (!empty($utsFields))
			{
				foreach ($utsFields as $utsField)
				{
					/** @var Entity\ScalarField $utsEntityField */
					$utsEntityField = $utsEntity->getField($utsField['FIELD_NAME']);

					foreach ($USER_FIELD_MANAGER->getEntityReferences($utsField, $utsEntityField) as $reference)
					{
						// rewrite reference from this.field to this.uts_object.field
						$referenceDesc = static::rewriteUtsReference($reference->getReference());

						$aliasReference = new Entity\ReferenceField(
							$reference->getName(),
							$reference->getRefEntityName(),
							$referenceDesc
						);

						$entity->addField($aliasReference);
					}
				}
			}

			if (!empty($utmFields))
			{
				// create utm entity & put base fields into it
				$utmEntity = static::createUtmEntity($entity, $utmFields);

				// add UF_* aliases
				foreach ($utmFieldNames as $utmFieldName => $true)
				{
					/** @var Entity\ScalarField $utmField */
					$utmField = $utmEntity->getField($utmFieldName);

					$aliasField = new Entity\ExpressionField(
						$utmFieldName.'_SINGLE',
						'%s',
						$utmEntity->getFullName().':PARENT_'.$utmFieldName.'.'.$utmField->getColumnName(),
						array('data_type' => get_class($utmField))
					);

					$entity->addField($aliasField);
				}
			}
		}
	}

	/**
	 * @param Entity\Base $srcEntity
	 * @param array       $utsFields
	 * @param array       $utmFields
	 *
	 * @return Entity\Base
	 * @throws ArgumentException
	 */
	protected static function createUtsEntity(Entity\Base $srcEntity, array $utsFields, array $utmFields)
	{
		global $USER_FIELD_MANAGER;

		// get namespace & class
		/** @var Entity\DataManager $utsClassFull */
		$utsClassFull = static::getUtsEntityClassNameBySrcEntity($srcEntity);
		$utsClassPath = explode('\\', ltrim($utsClassFull, '\\'));

		$utsNamespace = join('\\', array_slice($utsClassPath, 0, -1));
		$utsClass = end($utsClassPath);

		// get table name
		$utsTable = static::getUtsEntityTableNameBySrcEntity($srcEntity);

		// base fields
		$fieldsMap = array(
			'VALUE_ID' => array(
				'data_type' => 'integer',
				'primary' => true
			),
			'PARENT' => array(
				'data_type' => $srcEntity->getDataClass(),
				'reference' => array(
					'=this.VALUE_ID' => 'ref.ID'
				)
			)
		);

		// initialize entity
		if (class_exists($utsNamespace."\\".$utsClass))
		{
			Entity\Base::destroy($utsNamespace."\\".$utsClass);
			$entity = Entity\Base::getInstance($utsNamespace."\\".$utsClass);

			foreach ($fieldsMap as $fieldName => $field)
			{
				$entity->addField($field, $fieldName);
			}
		}
		else
		{
			$entity = Entity\Base::compileEntity($utsClass, $fieldsMap, array(
				'namespace' => $utsNamespace, 'table_name' => $utsTable
			));
		}

		foreach ($utsFields as $utsField)
		{
			$field = $USER_FIELD_MANAGER->getEntityField($utsField);
			$entity->addField($field);

			foreach ($USER_FIELD_MANAGER->getEntityReferences($utsField, $field) as $reference)
			{
				$entity->addField($reference);
			}
		}

		foreach ($utmFields as $utmField)
		{
			// add serialized utm cache-fields
			$cacheField = new Entity\TextField($utmField['FIELD_NAME']);
			static::setMultipleFieldSerialization($cacheField, $utmField);
			$entity->addField($cacheField);
		}

		return $entity;
	}

	/**
	 * @param Entity\Field       $entityField
	 * @param Entity\Field|array $fieldAsType
	 *
	 * @throws ArgumentException
	 */
	public static function setMultipleFieldSerialization(Entity\Field $entityField, $fieldAsType)
	{
		global $USER_FIELD_MANAGER;

		if (!($fieldAsType instanceof Entity\Field))
		{
			$fieldAsType = $USER_FIELD_MANAGER->getEntityField($fieldAsType);
		}

		if ($fieldAsType instanceof Entity\DatetimeField)
		{
			$entityField->addSaveDataModifier(array(__CLASS__, 'serializeMultipleDatetime'));
			$entityField->addFetchDataModifier(array(__CLASS__, 'unserializeMultipleDatetime'));
		}
		elseif ($fieldAsType instanceof Entity\DateField)
		{
			$entityField->addSaveDataModifier(array(__CLASS__, 'serializeMultipleDate'));
			$entityField->addFetchDataModifier(array(__CLASS__, 'unserializeMultipleDate'));
		}
		else
		{
			$entityField->setSerialized();
		}
	}

	public static function rewriteUtsReference($referenceDesc)
	{
		$new = array();

		foreach ($referenceDesc as $k => $v)
		{
			if (is_array($v))
			{
				$new[$k] = static::rewriteUtsReference($v);
			}
			else
			{
				$k = str_replace('this.', 'this.UTS_OBJECT.', $k);
				$new[$k] = $v;
			}
		}

		return $new;
	}

	protected static function getUtsEntityClassNameBySrcEntity(Entity\Base $srcEntity)
	{
		return $srcEntity->getFullName().'UtsTable';
	}

	protected static function getUtsEntityTableNameBySrcEntity(Entity\Base $srcEntity)
	{
		return 'b_uts_'.strtolower($srcEntity->getUfId());
	}

	/**
	 * @param Entity\Base $srcEntity
	 * @param array       $utmFields
	 *
	 * @return Entity\Base
	 * @throws ArgumentException
	 */
	protected static function createUtmEntity(Entity\Base $srcEntity, array $utmFields)
	{
		global $USER_FIELD_MANAGER;

		/** @var Entity\DataManager $utmClassFull */
		$utmClassFull = static::getUtmEntityClassNameBySrcEntity($srcEntity);
		$utmClassPath = explode('\\', ltrim($utmClassFull, '\\'));

		$utmNamespace = join('\\', array_slice($utmClassPath, 0, -1));
		$utmClass = end($utmClassPath);

		// get table name
		$utmTable = static::getUtmEntityTableNameBySrcEntity($srcEntity);

		// collect fields
		$fieldsMap = array(
			'ID' => array(
				'data_type' => 'integer',
				'primary' => true,
				'autocomplete' => true
			),
			'VALUE_ID' => array(
				'data_type' => 'integer',
				'primary' => true
			),
			'PARENT' => array(
				'data_type' => $srcEntity->getDataClass(),
				'reference' => array(
					'=this.VALUE_ID' => 'ref.ID'
				)
			),
			'FIELD_ID' => array(
				'data_type' => 'integer'
			),

			// base values fields
			'VALUE' => array(
				'data_type' => 'text'
			),
			'VALUE_INT' => array(
				'data_type' => 'integer'
			),
			'VALUE_DOUBLE' => array(
				'data_type' => 'float'
			),
			'VALUE_DATE' => array(
				'data_type' => 'datetime'
			)
		);

		// initialize entity
		if (class_exists($utmNamespace."\\".$utmClass))
		{
			Entity\Base::destroy($utmNamespace."\\".$utmClass);
			$entity = Entity\Base::getInstance($utmNamespace."\\".$utmClass);

			foreach ($fieldsMap as $fieldName => $field)
			{
				$entity->addField($field, $fieldName);
			}
		}
		else
		{
			$entity = Entity\Base::compileEntity($utmClass, $fieldsMap, array(
				'namespace' => $utmNamespace, 'table_name' => $utmTable
			));
		}

		// add utm fields being mapped on real column name
		foreach ($utmFields as $utmField)
		{
			$field = $USER_FIELD_MANAGER->getEntityField($utmField);

			if ($field instanceof Entity\IntegerField)
			{
				$columnName = 'VALUE_INT';
			}
			elseif ($field instanceof Entity\FloatField)
			{
				$columnName = 'VALUE_DOUBLE';
			}
			elseif ($field instanceof Entity\DateField || $field instanceof Entity\DatetimeField)
			{
				$columnName = 'VALUE_DATE';
			}
			else
			{
				$columnName = 'VALUE';
			}

			$field->setColumnName($columnName);

			$entity->addField($field);

			foreach ($USER_FIELD_MANAGER->getEntityReferences($utmField, $field) as $reference)
			{
				$entity->addField($reference);
			}

			// add back-reference
			$refField = new Entity\ReferenceField(
				'PARENT_'.$utmField['FIELD_NAME'],
				$srcEntity->getDataClass(),
				array('=this.VALUE_ID' => 'ref.ID', '=this.FIELD_ID' => array('?i', $utmField['ID']))
			);

			$entity->addField($refField);
		}

		return $entity;
	}

	protected static function getUtmEntityClassNameBySrcEntity(Entity\Base $srcEntity)
	{
		return $srcEntity->getFullName().'UtmTable';
	}

	protected static function getUtmEntityTableNameBySrcEntity(Entity\Base $srcEntity)
	{
		return 'b_utm_'.strtolower($srcEntity->getUfId());
	}

	/**
	 * @param Type\DateTime[] $value
	 *
	 * @return string
	 */
	public static function serializeMultipleDatetime($value)
	{
		if (is_array($value) || $value instanceof \Traversable)
		{
			$tmpValue = array();

			foreach ($value as $k => $singleValue)
			{
				/** @var Type\DateTime $singleValue */
				$tmpValue[$k] = $singleValue->format(static::MULTIPLE_DATETIME_FORMAT);
			}

			return serialize($tmpValue);
		}

		return $value;
	}

	/**
	 * @param string $value
	 *
	 * @return array
	 * @throws ObjectException
	 */
	public static function unserializeMultipleDatetime($value)
	{
		if (strlen($value))
		{
			$value = unserialize($value);

			foreach ($value as &$singleValue)
			{
				try
				{
					//try new independent datetime format
					$singleValue = new Type\DateTime($singleValue, static::MULTIPLE_DATETIME_FORMAT);
				}
				catch (ObjectException $e)
				{
					//try site format
					$singleValue = new Type\DateTime($singleValue);
				}
			}
		}

		return $value;
	}

	/**
	 * @param Type\Date[] $value
	 *
	 * @return string
	 */
	public static function serializeMultipleDate($value)
	{
		if (is_array($value) || $value instanceof \Traversable)
		{
			$tmpValue = array();

			foreach ($value as $k => $singleValue)
			{
				/** @var Type\Date $singleValue */
				$tmpValue[$k] = $singleValue->format(static::MULTIPLE_DATE_FORMAT);
			}

			return serialize($tmpValue);
		}

		return $value;
	}

	/**
	 * @param string $value
	 *
	 * @return array
	 * @throws ObjectException
	 */
	public static function unserializeMultipleDate($value)
	{
		if (strlen($value))
		{
			$value = unserialize($value);

			foreach ($value as &$singleValue)
			{
				try
				{
					//try new independent datetime format
					$singleValue = new Type\Date($singleValue, static::MULTIPLE_DATE_FORMAT);
				}
				catch (ObjectException $e)
				{
					//try site format
					$singleValue = new Type\Date($singleValue);
				}
			}
		}

		return $value;
	}
}