Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Duplicates #370

Open
wants to merge 1 commit into
base: 371-publish-b24-php-sdk-beta-2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.idea*
/.vscode*
/app
vendor
composer.phar
Expand Down
152 changes: 132 additions & 20 deletions src/Services/CRM/Duplicates/Result/DuplicateResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,157 @@

use Bitrix24\SDK\Core\Exceptions\BaseException;
use Bitrix24\SDK\Core\Result\AbstractResult;
use Bitrix24\SDK\Services\CRM\Duplicates\Service\EntityType;

/**
* Class DuplicateResult
* Handles the results for CRM duplicate checks.
*/
class DuplicateResult extends AbstractResult
{
public function hasDuplicateContacts(): bool
/**
* Private helper method to check for the existence of items of a given type.
* @param EntityType $entityType The type of entity to check.
* @param int $count The number of items to check for.
* @return bool True if the number of items is greater than or equal to the specified count.
*/
private function hasItems(EntityType $entityType, int $count = 1): bool
{
if (!array_key_exists('CONTACT', $this->getCoreResponse()->getResponseData()->getResult())) {
return false;
}
$entityTypeValue = $entityType->value;
$items = $this->getCoreResponse()->getResponseData()->getResult()[$entityTypeValue] ?? [];
return count($items) >= $count;
}

if (count($this->getCoreResponse()->getResponseData()->getResult()['CONTACT']) > 1) {
return true;
}
/**
* Checks if there is exactly one match for a given entity type.
* @param EntityType $entityType The entity type to check.
* @return bool True if there is only one match.
*/
public function hasOne(EntityType $entityType): bool
{
return $this->hasItems($entityType, 1) && count($this->getCoreResponse()->getResponseData()->getResult()[$entityType ->value]) === 1;
}

return false;
/**
* Checks if there is more than one match for a given entity type.
* @param EntityType $entityType The entity type to check.
* @return bool True if 2 or more duplicates.
*/
public function hasDuplicates(EntityType $entityType): bool
{
return $this->hasItems($entityType, 2);
}

public function hasOneContact(): bool
/**
* Checks if there are any matches for a given entity type.
* @param EntityType $entityType The entity type to check
* @return bool True if there are any matches.
*/
public function hasMatches(EntityType $entityType): bool
{
if (!array_key_exists('CONTACT', $this->getCoreResponse()->getResponseData()->getResult())) {
return false;
}
return $this->hasItems($entityType, 1);
}

if (count($this->getCoreResponse()->getResponseData()->getResult()['CONTACT']) === 1) {
return true;
/**
* Checks if there are any matches across all entity types.
* @return bool True if there are matches for any entity type.
*/
public function hasAnyMatches(): bool
{
foreach (EntityType::cases() as $entityType) {
if ($this->hasMatches($entityType)) {
return true;
}
}

return false;
}

// Backward compatible methods
public function hasDuplicateContacts(): bool
{
return $this->hasDuplicates(EntityType::Contact);
}

public function hasOneContact(): bool
{
return $this->hasOne(EntityType::Contact);
}

/**
* @return array<int>
* @throws BaseException
* Retrieves the IDs of a specific entity type.
*
* @param EntityType $entityType The entity type for which to retrieve IDs.
* @return array<int> The array of IDs.
* @throws BaseException If an error occurs during the API call.
*/
public function getContactsId(): array
public function getEntityIds(EntityType $entityType): array
{
if (!array_key_exists('CONTACT', $this->getCoreResponse()->getResponseData()->getResult())) {
$entityTypeValue = $entityType->value;

if (!array_key_exists($entityTypeValue, $this->getCoreResponse()->getResponseData()->getResult())) {
return [];
}

return $this->getCoreResponse()->getResponseData()->getResult()['CONTACT'];
return $this->getCoreResponse()->getResponseData()->getResult()[$entityTypeValue];
}

public function getContactsId(): array //backward-compatibility name
{
return $this->getEntityIds(EntityType::Contact);
}

public function getCompanyIds(): array
{
return $this->getEntityIds(EntityType::Company);
}

public function getLeadIds(): array
{
return $this->getEntityIds(EntityType::Lead);
}


/**
* Returns the ID of a match for a given entity type, with optional sorting to return either the first or last ID.
*
* @param EntityType $entityType The entity type for which to retrieve a match ID.
* @param string $sortOrder Optional sorting order, 'asc' return older entity, 'desc' for the newest. Default is 'desc'.
* @return int|null ID of the match, or null if no matches found.
*/
public function getMatchId(EntityType $entityType, string $sortOrder = 'desc'): ?int
{
$entityIds = $this->getEntityIds($entityType);

if (empty($entityIds)) {
return null;
}

return $sortOrder === 'desc' ? end($entityIds) :reset($entityIds);
}


/**
* Returns the ID and EntityType of the first match found based on the provided priority order.
*
* @param array $entityTypesOrder Array of EntityType objects in the order of priority. (Defaults Lead > Contact > Company)
* @param string $sortOrder Optional sorting order, 'asc' return older entity, 'desc' for the newest. Default is 'desc'.
* @return array|null ID of the first match or null if no matches found.
*/
public function getMatchIdByPriority(array $entityTypesOrder = [EntityType::Lead, EntityType::Contact, EntityType::Company], string $sortOrder = 'desc'): ?array
{
foreach ($entityTypesOrder as $entityType) {
// Используем getMatchId для получения ID с учетом сортировки
$matchId = $this->getMatchId($entityType, $sortOrder);
if ($matchId !== null) {
return [
'id' => $matchId,
'entityType' => $entityType,
'entityTypeValue' => $entityType->value,
];
}
}

return null;
}
}
46 changes: 22 additions & 24 deletions src/Services/CRM/Duplicates/Service/Duplicate.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,35 @@

class Duplicate extends AbstractService
{
/**
* @param array<string> $phones
* @param EntityType|null $entityType
/**
* Generic method to find duplicates by communication type.
*
* @link https://training.bitrix24.com/rest_help/crm/auxiliary/duplicates/crm.duplicate.findbycomm.php
* @param string $type 'PHONE' or 'EMAIL'
* @param array<string> $values Array containing up to 20 phone numbers or emails
* @param EntityType|null $entityType Can be skipped: all three entity types will be returned in this case. If this parameter is used, you can operate only with one of them. If you specify an array or non-existent parameter, all entity types will be returned.
* @return DuplicateResult
* @throws BaseException
* @throws TransportException
*/
public function findByPhone(array $phones, ?EntityType $entityType = null): mixed
private function findByCommType(string $type, array $values, ?EntityType $entityType = null): DuplicateResult
{
return new DuplicateResult($this->core->call('crm.duplicate.findbycomm',
[
'type' => 'PHONE',
'values' => $phones,
'entity_type' => $entityType?->value
]));
$response = $this->core->call('crm.duplicate.findbycomm', [
'type' => $type,
'values' => $values,
'entity_type' => $entityType?->value
]);

return new DuplicateResult($response);
}

/**
* @param array<string> $emails
* @param EntityType|null $entityType
* @return DuplicateResult
* @throws BaseException
* @throws TransportException
*/
public function findByEmail(array $emails, ?EntityType $entityType = null): DuplicateResult
public function findByPhone(array $phones, ?EntityType $entityType): DuplicateResult
{
return $this->findByCommType('PHONE', $phones, $entityType);
}

public function findByEmail(array $emails, ?EntityType $entityType): DuplicateResult
{
return new DuplicateResult($this->core->call('crm.duplicate.findbycomm',
[
'type' => 'EMAIL',
'values' => $emails,
'entity_type' => $entityType?->value
]));
return $this->findByCommType('EMAIL', $emails, $entityType);
}
}