• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/integrity/matchhashdedupedatasource.php
  • Класс: Bitrix\Crm\Integrity\MatchHashDedupeDataSource
  • Вызов: MatchHashDedupeDataSource::getListInternal
protected function getListInternal(array $filter, $offset, $limit)
{
	$result = new DedupeDataSourceResult();

	$typeID = $this->typeID;
	$entityTypeID = $this->getEntityTypeID();
	$enablePermissionCheck = $this->isPermissionCheckEnabled();
	$scope = $this->getScope();
	//$userID = $this->getUserID();

	$query = Entity\DuplicateEntityMatchHashTable::query();

	$query->setFilter($filter);

	$query->addSelect('MATCH_HASH');
	$query->addGroup('MATCH_HASH');
	$query->addOrder('MATCH_HASH', 'ASC');

	$query->registerRuntimeField('', new Main\Entity\ExpressionField('QTY', 'COUNT(*)'));
	$query->addSelect('QTY');
	$query->addFilter('>QTY', 1);

	$query->addFilter('=ENTITY_TYPE_ID', $entityTypeID);
	$query->addFilter('=TYPE_ID', $typeID);

	if ($this->params->getIndexDate())
	{
		$query->registerRuntimeField('',
			new Main\Entity\ExpressionField('MAX_HASH_DATE_MODIFY',
				new Main\DB\SqlExpression('MAX(?#.?#)', $query->getInitAlias(), 'DATE_MODIFY')
			)
		);
		$query->addFilter('>=MAX_HASH_DATE_MODIFY', $this->params->getIndexDate()->format("Y-m-d H:i:s"));
	}

	$permissionSql = '';
	if($enablePermissionCheck)
	{
		$permissionSql = $this->preparePermissionSql();
		if($permissionSql === false)
		{
			//Access denied;
			return $result;
		}
		if($permissionSql !== '')
		{
			$query->addFilter('@ENTITY_ID', new Main\DB\SqlExpression($permissionSql));
		}
	}
	// process only dirty items which already existed into automatic index:
	if ($this->params->limitByDirtyIndexItems())
	{
		$query->registerRuntimeField('', new Reference(
			'MATCH_HASH_DIRTY_INDEX',
			AutomaticDuplicateIndexTable::class,
			[
				'=this.MATCH_HASH' => 'ref.MATCH_HASH',
				'=this.ENTITY_TYPE_ID' => 'ref.ENTITY_TYPE_ID',
				'=this.TYPE_ID' => 'ref.TYPE_ID',
				'=ref.USER_ID' => new Main\DB\SqlExpression('?i', $this->getUserID()),
				'=ref.ENTITY_TYPE_ID' => new Main\DB\SqlExpression('?i', $this->getEntityTypeID()),
				'=ref.SCOPE' => new Main\DB\SqlExpression('?s', $this->getScope()),
				'=ref.IS_DIRTY' => new Main\DB\SqlExpression('?s', 'Y'),
			],
			['join_type' => \Bitrix\Main\ORM\Query\Join::TYPE_INNER]
		));
	}

	$query = DedupeDataSource::registerRuntimeFieldsByParams($query, $this->params);

	if ($scope === DuplicateIndexType::DEFAULT_SCOPE)
	{
		$query->addFilter('=SCOPE', DuplicateIndexType::DEFAULT_SCOPE);
	}
	else
	{
		$query->addFilter('@SCOPE', array(DuplicateIndexType::DEFAULT_SCOPE, $scope));
	}

	if(!is_int($offset))
	{
		$offset = (int)$offset;
	}
	if($offset > 0)
	{
		$query->setOffset($offset);
	}

	if(!is_int($limit))
	{
		$limit = (int)$limit;
	}
	if($limit > 0)
	{
		$query->setLimit($limit);
	}

	$dbResult = $query->exec();

	$processedItemCount = 0;
	$lightHashes = array();
	$heavyHashes = array();
	while($fields = $dbResult->fetch())
	{
		$processedItemCount++;

		$quantity = isset($fields['QTY']) ? (int)$fields['QTY'] : 0;
		$matchHash = isset($fields['MATCH_HASH']) ? $fields['MATCH_HASH'] : '';
		if($matchHash === '' || $quantity < 2)
		{
			$result->addInvalidItem($matchHash);
			continue;
		}

		if($quantity <= 100)
		{
			$lightHashes[] = $matchHash;
		}
		else
		{
			$heavyHashes[] = $matchHash;
		}
	}
	$result->setProcessedItemCount($processedItemCount);

	$map = array();
	if(!empty($heavyHashes))
	{
		foreach($heavyHashes as $matchHash)
		{
			$query = new Main\Entity\Query(Entity\DuplicateEntityMatchHashTable::getEntity());
			$query->addSelect('ENTITY_ID');
			$query->addSelect('IS_PRIMARY');

			$query->addFilter('=ENTITY_TYPE_ID', $entityTypeID);
			$query->addFilter('=TYPE_ID', $typeID);
			$query->addFilter('=MATCH_HASH', $matchHash);

			if($enablePermissionCheck && $permissionSql !== '')
			{
				$query->addFilter('@ENTITY_ID', new Main\DB\SqlExpression($permissionSql));
			}

			if ($scope === DuplicateIndexType::DEFAULT_SCOPE)
			{
				$query->addFilter('=SCOPE', DuplicateIndexType::DEFAULT_SCOPE);
			}
			else
			{
				$query->addFilter('@SCOPE', array(DuplicateIndexType::DEFAULT_SCOPE, $scope));
			}

			$query = DedupeDataSource::registerRuntimeFieldsByParams($query, $this->params);

			$query->setOffset(0);
			$query->setLimit(100);

			$dbResult = $query->exec();
			while($fields = $dbResult->fetch())
			{
				$entityID = isset($fields['ENTITY_ID']) ? (int)$fields['ENTITY_ID'] : 0;
				if($entityID <= 0)
				{
					continue;
				}

				if(!isset($map[$matchHash]))
				{
					$map[$matchHash] = array();
				}

				$isPrimary = isset($fields['IS_PRIMARY']) && $fields['IS_PRIMARY'] === 'Y';
				if($isPrimary)
				{
					if(!isset($map[$matchHash]['PRIMARY']))
					{
						$map[$matchHash]['PRIMARY'] = array();
					}
					$map[$matchHash]['PRIMARY'][] = $entityID;
				}
				else
				{
					if(!isset($map[$matchHash]['SECONDARY']))
					{
						$map[$matchHash]['SECONDARY'] = array();
					}
					$map[$matchHash]['SECONDARY'][] = $entityID;
				}
			}
		}
	}
	if(!empty($lightHashes))
	{
		$query = new Main\Entity\Query(Entity\DuplicateEntityMatchHashTable::getEntity());
		$query->addSelect('ENTITY_ID');
		$query->addSelect('MATCH_HASH');
		$query->addSelect('IS_PRIMARY');

		$query->addFilter('=ENTITY_TYPE_ID', $entityTypeID);
		$query->addFilter('=TYPE_ID', $typeID);
		$query->addFilter('@MATCH_HASH', $lightHashes);

		if($enablePermissionCheck && $permissionSql !== '')
		{
			$query->addFilter('@ENTITY_ID', new Main\DB\SqlExpression($permissionSql));
		}

		if ($scope === DuplicateIndexType::DEFAULT_SCOPE)
		{
			$query->addFilter('=SCOPE', DuplicateIndexType::DEFAULT_SCOPE);
		}
		else
		{
			$query->addFilter('@SCOPE', array(DuplicateIndexType::DEFAULT_SCOPE, $scope));
		}

		$query = DedupeDataSource::registerRuntimeFieldsByParams($query, $this->params);

		$dbResult = $query->exec();
		while($fields = $dbResult->fetch())
		{
			$entityID = isset($fields['ENTITY_ID']) ? (int)$fields['ENTITY_ID'] : 0;
			if($entityID <= 0)
			{
				continue;
			}

			$matchHash = isset($fields['MATCH_HASH']) ? $fields['MATCH_HASH'] : '';
			if($matchHash === '')
			{
				continue;
			}

			if(!isset($map[$matchHash]))
			{
				$map[$matchHash] = array();
			}

			$isPrimary = isset($fields['IS_PRIMARY']) && $fields['IS_PRIMARY'] === 'Y';
			if($isPrimary)
			{
				if(!isset($map[$matchHash]['PRIMARY']))
				{
					$map[$matchHash]['PRIMARY'] = array();
				}
				$map[$matchHash]['PRIMARY'][] = $entityID;
			}
			else
			{
				if(!isset($map[$matchHash]['SECONDARY']))
				{
					$map[$matchHash]['SECONDARY'] = array();
				}
				$map[$matchHash]['SECONDARY'][] = $entityID;
			}
		}
	}

	$this->prepareResult($map, $result);

	if ($this->params->limitByAssignedUser())
	{
		foreach ($result->getItems() as $duplicate)
		{
			/** @var $duplicate Duplicate */
			$criterion = $duplicate->getCriterion();
			/** @var $criterion DuplicateCriterion */
			if ($criterion)
			{
				$criterion->setLimitByAssignedUser(true);
			}
			$entities = $duplicate->getEntities();
			foreach ($entities as $entity)
			{
				/** @var $entity DuplicateEntity */
				if ($entity->getCriterion())
				{
					$entity->getCriterion()->setLimitByAssignedUser(true);
				}
			}
		}
	}

	return $result;
}