• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/lib/iblocktable.php
  • Класс: BitrixIblockIblockTable
  • Вызов: IblockTable::compileEntity
static function compileEntity($iblockApiCode)
{
	// get iblock
	if ($iblockApiCode instanceof Iblock)
	{
		$iblock = $iblockApiCode;
		$iblock->fillApiCode();
	}
	else
	{
		$iblock = IblockTable::getList([
			'select' => ['ID', 'API_CODE'],
			'filter' => Query::filter()->where('API_CODE', $iblockApiCode)
		])->fetchObject();
	}

	if (!$iblock || empty($iblock->getApiCode()))
	{
		return false;
	}

	// class info
	$iblockNamespace = static::DATA_CLASS_NAMESPACE;
	$iblockDataClassName = $iblock->getEntityDataClassName();

	if ($iblockDataClassName == '')
	{
		return false;
	}

	// check if already compiled
	$iblockDataClass = $iblock->getEntityDataClass();

	if (class_exists($iblockDataClass, false))
	{
		return $iblockDataClass::getEntity();
	}

	// fill some necessary info
	$iblock->fill(['VERSION', 'PROPERTIES']);

	// iblock personal entity
	$parentDataClass = $iblock->getVersion() == 1
		? ElementV1Table::class
		: ElementV2Table::class;

	/** @var ElementEntity $elementEntity */
	$elementEntity = BitrixMainORMEntity::compileEntity(
		$iblockDataClassName,
		[],
		[
			'namespace' => $iblockNamespace,
			'parent' => $parentDataClass,
		]
	);

	// set iblock to the entity
	$elementEntity->setIblock($iblock);

	// set relation with sections
	SectionElementTable::getEntity()->addField(
		(new Reference('REGULAR_ELEMENT_'.$iblock->getId(), $elementEntity,
		Join::on('this.IBLOCK_ELEMENT_ID', 'ref.ID')->whereNull('this.ADDITIONAL_PROPERTY_ID')))
	);

	$elementEntity->addField((new ManyToMany('SECTIONS', SectionTable::class))
		->configureMediatorEntity(SectionElementTable::class)
		->configureLocalReference('REGULAR_ELEMENT_'.$iblock->getId())
		->configureRemoteReference('IBLOCK_SECTION')
	);

	//$baseTypeList = BitrixIblockHelpersAdminProperty::getBaseTypeList(true);
	$userTypeList = CIBlockProperty::GetUserType();

	// get properties
	foreach ($iblock->getProperties() as $property)
	{
		if (empty($property->getCode()))
		{
			continue;
		}

		// build property entity with base fields
		$propertyValueEntity = $property->getValueEntity($elementEntity);

		// add custom fields
		if (!empty($property->getUserType()) && !empty($userTypeList[$property->getUserType()]['GetORMFields']))
		{
			call_user_func($userTypeList[$property->getUserType()]['GetORMFields'], $propertyValueEntity, $property);
		}

		// add relations with property entity
		$niceColumnName = $property->getCode();

		if ($property->getMultiple())
		{
			// classic OneToMany
			$elementRefName = 'SRC_ELEMENT';

			// ref from prop entity to src element
			$propertyValueEntity->addField(
				(new Reference(
					$elementRefName,
					$elementEntity,
					Join::on('this.IBLOCK_ELEMENT_ID', 'ref.ID')
						->where('this.IBLOCK_PROPERTY_ID', $property->getId())
				))
					->configureJoinType(Join::TYPE_INNER)

			);

			// OneToMany from src element to prop entity
			$elementEntity->addField(
				(new PropertyOneToMany($niceColumnName, $propertyValueEntity, $elementRefName))
					->configureJoinType(Join::TYPE_LEFT)
					->configureIblockElementProperty($property)
					->configureCascadeDeletePolicy(
						CascadePolicy::FOLLOW
					)
			);
		}
		else
		{
			// classic ref
			$joinType = Join::TYPE_INNER;
			$joinFilter = Join::on('this.ID', 'ref.IBLOCK_ELEMENT_ID');

			if ($iblock->getVersion() == 1)
			{
				// additional clause for shared value table in v1.0
				$joinType = Join::TYPE_LEFT;
				$joinFilter->where('ref.IBLOCK_PROPERTY_ID', $property->getId());
			}

			// ref from src element to prop entity
			$elementEntity->addField(
				(new PropertyReference($niceColumnName, $propertyValueEntity, $joinFilter))
					->configureJoinType($joinType)
					->configureIblockElementProperty($property)
					->configureCascadeDeletePolicy(
						CascadePolicy::NO_ACTION  // will be removed together in onAfterDelete
					)
			);
		}
	}

	return $elementEntity;
}