Spaces:
No application file
No application file
mautic
/
app
/bundles
/IntegrationsBundle
/Sync
/SyncDataExchange
/Internal
/ObjectHelper
/CompanyObjectHelper.php
declare(strict_types=1); | |
namespace Mautic\IntegrationsBundle\Sync\SyncDataExchange\Internal\ObjectHelper; | |
use Doctrine\DBAL\ArrayParameterType; | |
use Doctrine\DBAL\Connection; | |
use Mautic\IntegrationsBundle\Entity\ObjectMapping; | |
use Mautic\IntegrationsBundle\Sync\DAO\Mapping\UpdatedObjectMappingDAO; | |
use Mautic\IntegrationsBundle\Sync\DAO\Sync\Order\FieldDAO; | |
use Mautic\IntegrationsBundle\Sync\DAO\Sync\Order\ObjectChangeDAO; | |
use Mautic\IntegrationsBundle\Sync\Logger\DebugLogger; | |
use Mautic\IntegrationsBundle\Sync\SyncDataExchange\MauticSyncDataExchange; | |
use Mautic\LeadBundle\Entity\Company; | |
use Mautic\LeadBundle\Entity\CompanyRepository; | |
use Mautic\LeadBundle\Field\FieldsWithUniqueIdentifier; | |
use Mautic\LeadBundle\Model\CompanyModel; | |
class CompanyObjectHelper implements ObjectHelperInterface | |
{ | |
/** | |
* @var string[]|null | |
*/ | |
private ?array $uniqueIdentifierFields = null; | |
/** | |
* @var array<string,Company> | |
*/ | |
private array $companiesCreated = []; | |
public function __construct( | |
private CompanyModel $model, | |
private CompanyRepository $repository, | |
private Connection $connection, | |
private FieldsWithUniqueIdentifier $fieldsWithUniqueIdentifier | |
) { | |
} | |
/** | |
* @param ObjectChangeDAO[] $objects | |
* | |
* @return ObjectMapping[] | |
*/ | |
public function create(array $objects): array | |
{ | |
$objectMappings = []; | |
foreach ($objects as $object) { | |
$fields = $object->getFields(); | |
$company = $this->getCompanyEntity($fields); | |
foreach ($fields as $field) { | |
$company->addUpdatedField($field->getName(), $field->getValue()->getNormalizedValue()); | |
} | |
$this->model->saveEntity($company); | |
DebugLogger::log( | |
MauticSyncDataExchange::NAME, | |
sprintf( | |
'Created company ID %d', | |
$company->getId() | |
), | |
self::class.':'.__FUNCTION__ | |
); | |
$objectMapping = new ObjectMapping(); | |
$objectMapping->setLastSyncDate($object->getChangeDateTime()) | |
->setIntegration($object->getIntegration()) | |
->setIntegrationObjectName($object->getMappedObject()) | |
->setIntegrationObjectId($object->getMappedObjectId()) | |
->setInternalObjectName(MauticSyncDataExchange::OBJECT_COMPANY) | |
->setInternalObjectId($company->getId()); | |
$objectMappings[] = $objectMapping; | |
} | |
// Detach to free RAM after all companies are processed in case there are duplicates in the same batch | |
foreach ($this->companiesCreated as $company) { | |
$this->repository->detachEntity($company); | |
} | |
// Reset companies created for the next batch | |
$this->companiesCreated = []; | |
return $objectMappings; | |
} | |
/** | |
* @param ObjectChangeDAO[] $objects | |
* | |
* @return UpdatedObjectMappingDAO[] | |
*/ | |
public function update(array $ids, array $objects): array | |
{ | |
$updatedMappedObjects = []; | |
if (!$ids) { | |
return $updatedMappedObjects; | |
} | |
/** @var Company[] $companies */ | |
$companies = $this->model->getEntities(['ids' => $ids]); | |
DebugLogger::log( | |
MauticSyncDataExchange::NAME, | |
sprintf( | |
'Found %d companies to update with ids %s', | |
count($companies), | |
implode(', ', $ids) | |
), | |
self::class.':'.__FUNCTION__ | |
); | |
foreach ($companies as $company) { | |
/** @var ObjectChangeDAO $changedObject */ | |
$changedObject = $objects[$company->getId()]; | |
$fields = $changedObject->getFields(); | |
foreach ($fields as $field) { | |
$company->addUpdatedField($field->getName(), $field->getValue()->getNormalizedValue()); | |
} | |
$this->model->saveEntity($company); | |
$this->repository->detachEntity($company); | |
DebugLogger::log( | |
MauticSyncDataExchange::NAME, | |
sprintf( | |
'Updated company ID %d', | |
$company->getId() | |
), | |
self::class.':'.__FUNCTION__ | |
); | |
// Integration name and ID are stored in the change's mappedObject/mappedObjectId | |
$updatedMappedObjects[] = new UpdatedObjectMappingDAO( | |
$changedObject->getIntegration(), | |
$changedObject->getMappedObject(), | |
$changedObject->getMappedObjectId(), | |
$changedObject->getChangeDateTime() | |
); | |
} | |
return $updatedMappedObjects; | |
} | |
/** | |
* Unfortunately the CompanyRepository doesn't give us what we need so we have to write our own queries. | |
* | |
* @param int $start | |
* @param int $limit | |
*/ | |
public function findObjectsBetweenDates(\DateTimeInterface $from, \DateTimeInterface $to, $start, $limit): array | |
{ | |
$qb = $this->connection->createQueryBuilder(); | |
$qb->select('*') | |
->from(MAUTIC_TABLE_PREFIX.'companies', 'c') | |
->where( | |
$qb->expr()->or( | |
$qb->expr()->and( | |
$qb->expr()->isNotNull('c.date_modified'), | |
$qb->expr()->comparison('c.date_modified', 'BETWEEN', ':dateFrom and :dateTo') | |
), | |
$qb->expr()->and( | |
$qb->expr()->isNull('c.date_modified'), | |
$qb->expr()->comparison('c.date_added', 'BETWEEN', ':dateFrom and :dateTo') | |
) | |
) | |
) | |
->setParameter('dateFrom', $from->format('Y-m-d H:i:s')) | |
->setParameter('dateTo', $to->format('Y-m-d H:i:s')) | |
->setFirstResult($start) | |
->setMaxResults($limit); | |
return $qb->executeQuery()->fetchAllAssociative(); | |
} | |
public function findObjectsByIds(array $ids): array | |
{ | |
if (!count($ids)) { | |
return []; | |
} | |
$qb = $this->connection->createQueryBuilder(); | |
$qb->select('*') | |
->from(MAUTIC_TABLE_PREFIX.'companies', 'c') | |
->where( | |
$qb->expr()->in('id', $ids) | |
); | |
return $qb->executeQuery()->fetchAllAssociative(); | |
} | |
public function findObjectsByFieldValues(array $fields): array | |
{ | |
$q = $this->connection->createQueryBuilder() | |
->select('c.id') | |
->from(MAUTIC_TABLE_PREFIX.'companies', 'c'); | |
foreach ($fields as $col => $val) { | |
// Use andWhere because Mautic treats conflicting unique identifiers as different objects | |
$q->{$this->repository->getUniqueIdentifiersWherePart()}("c.$col = :".$col) | |
->setParameter($col, $val); | |
} | |
return $q->executeQuery()->fetchAllAssociative(); | |
} | |
public function findOwnerIds(array $objectIds): array | |
{ | |
if (empty($objectIds)) { | |
return []; | |
} | |
$qb = $this->connection->createQueryBuilder(); | |
$qb->select('c.owner_id, c.id'); | |
$qb->from(MAUTIC_TABLE_PREFIX.'companies', 'c'); | |
$qb->where('c.owner_id IS NOT NULL'); | |
$qb->andWhere('c.id IN (:objectIds)'); | |
$qb->setParameter('objectIds', $objectIds, ArrayParameterType::INTEGER); | |
return $qb->executeQuery()->fetchAllAssociative(); | |
} | |
public function findObjectById(int $id): ?Company | |
{ | |
return $this->repository->getEntity($id); | |
} | |
public function setFieldValues(Company $company): void | |
{ | |
$this->model->setFieldValues($company, []); | |
} | |
/** | |
* @return string[] | |
*/ | |
private function getUniqueIdentifierFields(): array | |
{ | |
if (null === $this->uniqueIdentifierFields) { | |
$uniqueIdentifierFields = $this->fieldsWithUniqueIdentifier->getFieldsWithUniqueIdentifier(['object' => MauticSyncDataExchange::OBJECT_COMPANY]); | |
$this->uniqueIdentifierFields = array_keys($uniqueIdentifierFields); | |
} | |
return $this->uniqueIdentifierFields; | |
} | |
/** | |
* @param FieldDAO[] $fields | |
*/ | |
private function getCompanyEntity(array $fields): Company | |
{ | |
$uniqueIdentifierFields = $this->getUniqueIdentifierFields(); | |
// Create a key based on the concatenation of unique identifier values | |
$companyKey = ''; | |
foreach ($uniqueIdentifierFields as $uniqueIdentifierField) { | |
if (isset($fields[$uniqueIdentifierField])) { | |
$companyKey .= strtolower($fields[$uniqueIdentifierField]->getValue()->getNormalizedValue()); | |
} | |
} | |
// Check if a company with matching values was created in the same batch as another | |
if (!empty($companyKey) && isset($this->companiesCreated[$companyKey])) { | |
return $this->companiesCreated[$companyKey]; | |
} | |
// Create a new company but ensure a unique key | |
$companyKey = $companyKey ?: uniqid(); | |
return $this->companiesCreated[$companyKey] = new Company(); | |
} | |
} | |