• Модуль: sale
  • Путь к файлу: ~/bitrix/modules/sale/lib/location/connector.php
  • Класс: BitrixSaleLocationConnector
  • Вызов: Connector::getConnectedEntitiesQuery
static function getConnectedEntitiesQuery($locationPrimary, $linkType = 'id', $parameters = array()) // // getConnectedEntitiesSql
{
	if($linkType == 'id')
		$locationPrimary = Assert::expectIntegerPositive($locationPrimary, '$locationPrimary');
	else
		$locationPrimary = Assert::expectStringNotNull($locationPrimary, '$locationPrimary');

	$useGroups = 			GroupTable::checkGroupUsage() && static::getUseGroups(); // check if we have groups in project and entity uses groups
	$useCodes = 			static::getUseCodes(); // this entity uses codes
	$groupUseCodes =		GroupLocationTable::getUseCodes(); // group entity uses codes

	$typeFld = 				static::getTypeField();/*LOCATION_TYPE*/
	$linkFld = 				static::getLinkField();/*DELIVERY_ID*/
	$locationLinkFld = 		static::getLocationLinkField();/*LOCATION_ID*/
	$targetPrimaryFld = 	static::getTargetEntityPrimaryField();/*ID*/
	$groupLocationLinkFld = GroupLocationTable::getLocationLinkField();/*LOCATION_ID*/
	$groupLinkFld = 		GroupLocationTable::getLinkField();/*LOCATION_GROUP_ID*/

	$seachById = $linkType == 'id';

	$dbConnection = MainHttpApplication::getConnection();

	if(!is_array($parameters))
		$parameters = array();

	if(is_array($parameters['runtime']))
		Assert::announceNotImplemented('Sorry, runtime clause is not implemented currently.');

	$order = array();
	if(is_array($parameters['order']))
		Assert::announceNotImplemented('Sorry, order-over-union clause is not implemented currently.');

	$filter = array();
	if(is_array($parameters['filter']) && !empty($parameters['filter']))
		$filter = $parameters['filter'];

	$select = array('*');
	if(is_array($parameters['select']) && !empty($parameters['select']))
		$select = $parameters['select'];

	/*
	query example when working with delivery:

	select distinct D.* from b_sale_delivery D
		inner join b_sale_delivery2location DL on D.ID = DL.DELIVERY_ID and DL.LOCATION_TYPE = 'L'
		inner join b_sale_location L1 on L1.CODE = DL.LOCATION_ID
		inner join b_sale_location L2 on L2.ID(there will be CODE, if we search by code) = 65683 and L2.LEFT_MARGIN >= L1.LEFT_MARGIN and L2.RIGHT_MARGIN <= L1.RIGHT_MARGIN;
	*/

	$query = new EntityQuery(static::getTargetEntityName());

	$DLCondition = array(
		'=this.'.$targetPrimaryFld/*ID*/ => 'ref.'.$linkFld/*DELIVERY_ID*/
	);
	if($useGroups)
		$DLCondition['=ref.'.$typeFld/*LOCATION_TYPE*/] = array('?', static::DB_LOCATION_FLAG);

	$query
		->registerRuntimeField(
			'DL',
			array(
				'data_type' => get_called_class(),
				'reference' => $DLCondition,
				'join_type' => 'inner'
			)
		)
		->registerRuntimeField(
			'L1',
			array(
				'data_type' => 'BitrixSaleLocationLocation',
				'reference' => array(
					'=this.DL.'.$locationLinkFld/*LOCATION_ID*/ => 'ref.'.($useCodes ? 'CODE' : 'ID'),
				),
				'join_type' => 'inner'
			)
		)
		->registerRuntimeField(
			'L2',
			array(
				'data_type' => 'BitrixSaleLocationLocation',
				'reference' => array(
					'=ref.'.($seachById ? 'ID' : 'CODE') =>  array('?', $locationPrimary), // among parents we have element with ID or CODE is equal to $locationPrimary
					'>=ref.LEFT_MARGIN' => 'this.L1.LEFT_MARGIN', // and its left_margin
					'<=ref.RIGHT_MARGIN' => 'this.L1.RIGHT_MARGIN' // and right_margin fit our restrictions
				),
				'join_type' => 'inner'
			)
		)
		->setSelect($select)
		->setFilter($filter)
		->setOrder($order);

	if(!$useGroups)
	{
		// emulate "select distinct"
		$query->setGroup($select);

		return $query->getQuery();
	}
	else
	{
		$sqls = array($query->getQuery());

		$query = new EntityQuery(static::getTargetEntityName());

		/*
		query example when working with delivery:

		select D.* from b_sale_delivery D
			inner join b_sale_delivery2location DL on D.ID = DL.DELIVERY_ID and DL.LOCATION_TYPE = 'G'
			inner join b_sale_location_group G on G.CODE = DL.LOCATION_ID (if this entity uses ID, skip this join)
			inner join b_sale_grouplocation GL on GL.LOCATION_GROUP_ID = G.ID (if this entity uses ID, there will be DL.LOCATION_ID)
			inner join b_sale_location L1 on L1.ID (there will be CODE, if grouplocation entity uses CODE) = GL.LOCATION_ID
			inner join b_sale_location L2 on L2.ID (there will be CODE, if we seach by code) = 65683 and L2.LEFT_MARGIN >= L1.LEFT_MARGIN and L2.RIGHT_MARGIN <= L1.RIGHT_MARGIN;
		*/

		$query
			->registerRuntimeField(
				'DL',
				array(
					'data_type' => get_called_class(),
					'reference' => array(
						'=this.'.$targetPrimaryFld/*ID*/ => 'ref.'.$linkFld/*DELIVERY_ID*/,
						'=ref.'.$typeFld/*LOCATION_TYPE*/ => array('?', static::DB_GROUP_FLAG)
					),
					'join_type' => 'inner'
				)
			);

		if($useCodes)
		{
			$query
				->registerRuntimeField(
					'G',
					array(
						'data_type' => 'BitrixSaleLocationGroup',
						'reference' => array(
							'=this.DL.'.$locationLinkFld/*LOCATION_ID*/ => 'ref.CODE', //$useCodes == true here, so always CODE
						),
						'join_type' => 'inner'
					)
				);
		}

		$query
			->registerRuntimeField(
				'GL',
				array(
					'data_type' => 'BitrixSaleLocationGroupLocation',
					'reference' => array(
						($useCodes ? '=this.G.ID' : '=this.DL.'.$locationLinkFld/*LOCATION_ID*/) => 'ref.'.$groupLinkFld/*LOCATION_GROUP_ID*/
					),
					'join_type' => 'inner'
				)
			)
			->registerRuntimeField(
				'L1',
				array(
					'data_type' => 'BitrixSaleLocationLocation',
					'reference' => array(
						'=this.GL.'.$groupLocationLinkFld/*LOCATION_ID*/ => 'ref.'.($groupUseCodes ? 'CODE' : 'ID'),
					),
					'join_type' => 'inner'
				)
			)
			->registerRuntimeField(
				'L2',
				array(
					'data_type' => 'BitrixSaleLocationLocation',
					'reference' => array(
						'=ref.'.($seachById ? 'ID' : 'CODE') =>  array('?', $locationPrimary),
						'>=ref.LEFT_MARGIN' => 'this.L1.LEFT_MARGIN',
						'<=ref.RIGHT_MARGIN' => 'this.L1.RIGHT_MARGIN'
					),
					'join_type' => 'inner'
				)
			)
			->setSelect($select)
			->setFilter($filter)
			->setOrder($order);

		$sqls[] = $query->getQuery();

		return static::unionize($sqls);
	}
}