Spaces:
No application file
No application file
| declare(strict_types=1); | |
| namespace Mautic\IntegrationsBundle\Sync\Helper; | |
| use Mautic\IntegrationsBundle\Entity\ObjectMapping; | |
| use Mautic\IntegrationsBundle\Entity\ObjectMappingRepository; | |
| use Mautic\IntegrationsBundle\Event\InternalObjectFindEvent; | |
| use Mautic\IntegrationsBundle\IntegrationEvents; | |
| use Mautic\IntegrationsBundle\Sync\DAO\Mapping\MappingManualDAO; | |
| use Mautic\IntegrationsBundle\Sync\DAO\Mapping\RemappedObjectDAO; | |
| use Mautic\IntegrationsBundle\Sync\DAO\Mapping\UpdatedObjectMappingDAO; | |
| use Mautic\IntegrationsBundle\Sync\DAO\Sync\Order\ObjectChangeDAO; | |
| use Mautic\IntegrationsBundle\Sync\DAO\Sync\Report\ObjectDAO; | |
| use Mautic\IntegrationsBundle\Sync\Exception\FieldNotFoundException; | |
| use Mautic\IntegrationsBundle\Sync\Exception\ObjectDeletedException; | |
| use Mautic\IntegrationsBundle\Sync\Exception\ObjectNotFoundException; | |
| use Mautic\IntegrationsBundle\Sync\Exception\ObjectNotSupportedException; | |
| use Mautic\IntegrationsBundle\Sync\SyncDataExchange\Internal\ObjectProvider; | |
| use Mautic\IntegrationsBundle\Sync\SyncDataExchange\MauticSyncDataExchange; | |
| use Mautic\LeadBundle\Model\FieldModel; | |
| use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |
| class MappingHelper | |
| { | |
| public function __construct( | |
| private FieldModel $fieldModel, | |
| private ObjectMappingRepository $objectMappingRepository, | |
| private ObjectProvider $objectProvider, | |
| private EventDispatcherInterface $dispatcher | |
| ) { | |
| } | |
| /** | |
| * @throws ObjectDeletedException | |
| * @throws ObjectNotFoundException | |
| * @throws ObjectNotSupportedException | |
| */ | |
| public function findMauticObject(MappingManualDAO $mappingManualDAO, string $internalObjectName, ObjectDAO $integrationObjectDAO): ObjectDAO | |
| { | |
| // Check if this contact is already tracked | |
| if ($internalObject = $this->objectMappingRepository->getInternalObject( | |
| $mappingManualDAO->getIntegration(), | |
| $integrationObjectDAO->getObject(), | |
| $integrationObjectDAO->getObjectId(), | |
| $internalObjectName | |
| )) { | |
| if ($internalObject['is_deleted']) { | |
| throw new ObjectDeletedException(); | |
| } | |
| return new ObjectDAO( | |
| $internalObjectName, | |
| $internalObject['internal_object_id'], | |
| new \DateTime($internalObject['last_sync_date'], new \DateTimeZone('UTC')) | |
| ); | |
| } | |
| // We don't know who this is so search Mautic | |
| $uniqueIdentifierFields = $this->fieldModel->getUniqueIdentifierFields(['object' => $internalObjectName]); | |
| $identifiers = []; | |
| foreach ($uniqueIdentifierFields as $field => $fieldLabel) { | |
| try { | |
| $integrationField = $mappingManualDAO->getIntegrationMappedField($integrationObjectDAO->getObject(), $internalObjectName, $field); | |
| if ($integrationValue = $integrationObjectDAO->getField($integrationField)) { | |
| $identifiers[$field] = $integrationValue->getValue()->getNormalizedValue(); | |
| } | |
| } catch (FieldNotFoundException) { | |
| } | |
| } | |
| if (empty($identifiers)) { | |
| // No fields found to search for contact so return null | |
| return new ObjectDAO($internalObjectName, null); | |
| } | |
| try { | |
| $event = new InternalObjectFindEvent( | |
| $this->objectProvider->getObjectByName($internalObjectName) | |
| ); | |
| } catch (ObjectNotFoundException) { | |
| // Throw this exception for BC. | |
| throw new ObjectNotSupportedException(MauticSyncDataExchange::NAME, $internalObjectName); | |
| } | |
| $event->setFieldValues($identifiers); | |
| $this->dispatcher->dispatch( | |
| $event, | |
| IntegrationEvents::INTEGRATION_FIND_INTERNAL_RECORDS, | |
| ); | |
| $foundObjects = $event->getFoundObjects(); | |
| if (!$foundObjects) { | |
| // No contacts were found | |
| return new ObjectDAO($internalObjectName, null); | |
| } | |
| // Match found! | |
| $objectId = $foundObjects[0]['id']; | |
| // Let's store the relationship since we know it | |
| $objectMapping = new ObjectMapping(); | |
| $objectMapping->setLastSyncDate($integrationObjectDAO->getChangeDateTime()) | |
| ->setIntegration($mappingManualDAO->getIntegration()) | |
| ->setIntegrationObjectName($integrationObjectDAO->getObject()) | |
| ->setIntegrationObjectId($integrationObjectDAO->getObjectId()) | |
| ->setInternalObjectName($internalObjectName) | |
| ->setInternalObjectId($objectId); | |
| $this->saveObjectMapping($objectMapping); | |
| return new ObjectDAO($internalObjectName, $objectId); | |
| } | |
| /** | |
| * Returns corresponding Mautic entity class name for the given Mautic object. | |
| * | |
| * @throws ObjectNotSupportedException | |
| */ | |
| public function getMauticEntityClassName(string $internalObject): string | |
| { | |
| try { | |
| return $this->objectProvider->getObjectByName($internalObject)->getEntityName(); | |
| } catch (ObjectNotFoundException) { | |
| // Throw this exception instead to keep BC. | |
| throw new ObjectNotSupportedException(MauticSyncDataExchange::NAME, $internalObject); | |
| } | |
| } | |
| /** | |
| * @throws ObjectDeletedException | |
| */ | |
| public function findIntegrationObject(string $integration, string $integrationObjectName, ObjectDAO $internalObjectDAO): ObjectDAO | |
| { | |
| if ($integrationObject = $this->objectMappingRepository->getIntegrationObject( | |
| $integration, | |
| $internalObjectDAO->getObject(), | |
| $internalObjectDAO->getObjectId(), | |
| $integrationObjectName | |
| )) { | |
| if ($integrationObject['is_deleted']) { | |
| throw new ObjectDeletedException(); | |
| } | |
| return new ObjectDAO( | |
| $integrationObjectName, | |
| $integrationObject['integration_object_id'], | |
| new \DateTime($integrationObject['last_sync_date'], new \DateTimeZone('UTC')) | |
| ); | |
| } | |
| return new ObjectDAO($integrationObjectName, null); | |
| } | |
| /** | |
| * @param ObjectMapping[] $mappings | |
| */ | |
| public function saveObjectMappings(array $mappings): void | |
| { | |
| foreach ($mappings as $mapping) { | |
| $this->saveObjectMapping($mapping); | |
| } | |
| } | |
| public function updateObjectMappings(array $mappings): void | |
| { | |
| foreach ($mappings as $mapping) { | |
| try { | |
| $this->updateObjectMapping($mapping); | |
| } catch (ObjectNotFoundException) { | |
| continue; | |
| } | |
| } | |
| } | |
| /** | |
| * @param RemappedObjectDAO[] $mappings | |
| */ | |
| public function remapIntegrationObjects(array $mappings): void | |
| { | |
| foreach ($mappings as $mapping) { | |
| $this->objectMappingRepository->updateIntegrationObject( | |
| $mapping->getIntegration(), | |
| $mapping->getOldObjectName(), | |
| $mapping->getOldObjectId(), | |
| $mapping->getNewObjectName(), | |
| $mapping->getNewObjectId() | |
| ); | |
| } | |
| } | |
| /** | |
| * @param ObjectChangeDAO[] $objects | |
| */ | |
| public function markAsDeleted(array $objects): void | |
| { | |
| foreach ($objects as $object) { | |
| $this->objectMappingRepository->markAsDeleted($object->getIntegration(), $object->getObject(), $object->getObjectId()); | |
| } | |
| } | |
| private function saveObjectMapping(ObjectMapping $objectMapping): void | |
| { | |
| $this->objectMappingRepository->saveEntity($objectMapping); | |
| $this->objectMappingRepository->detachEntity($objectMapping); | |
| } | |
| /** | |
| * @throws ObjectNotFoundException | |
| */ | |
| private function updateObjectMapping(UpdatedObjectMappingDAO $updatedObjectMappingDAO): void | |
| { | |
| /** @var ObjectMapping $objectMapping */ | |
| $objectMapping = $this->objectMappingRepository->findOneBy( | |
| [ | |
| 'integration' => $updatedObjectMappingDAO->getIntegration(), | |
| 'integrationObjectName' => $updatedObjectMappingDAO->getIntegrationObjectName(), | |
| 'integrationObjectId' => $updatedObjectMappingDAO->getIntegrationObjectId(), | |
| ] | |
| ); | |
| if (!$objectMapping) { | |
| throw new ObjectNotFoundException($updatedObjectMappingDAO->getIntegrationObjectName().':'.$updatedObjectMappingDAO->getIntegrationObjectId()); | |
| } | |
| $objectMapping->setLastSyncDate($updatedObjectMappingDAO->getObjectModifiedDate()); | |
| $this->saveObjectMapping($objectMapping); | |
| // Make the ObjectMapping available to the IntegrationEvents::INTEGRATION_BATCH_SYNC_COMPLETED_* events | |
| $updatedObjectMappingDAO->setObjectMapping($objectMapping); | |
| } | |
| } | |