Issues (3627)

IntegrationsBundle/Sync/Helper/MappingHelper.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * @copyright   2018 Mautic Contributors. All rights reserved
7
 * @author      Mautic, Inc.
8
 *
9
 * @link        https://mautic.org
10
 *
11
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Mautic\IntegrationsBundle\Sync\Helper;
15
16
use Mautic\IntegrationsBundle\Entity\ObjectMapping;
17
use Mautic\IntegrationsBundle\Entity\ObjectMappingRepository;
18
use Mautic\IntegrationsBundle\Event\InternalObjectFindEvent;
19
use Mautic\IntegrationsBundle\IntegrationEvents;
20
use Mautic\IntegrationsBundle\Sync\DAO\Mapping\MappingManualDAO;
21
use Mautic\IntegrationsBundle\Sync\DAO\Mapping\RemappedObjectDAO;
22
use Mautic\IntegrationsBundle\Sync\DAO\Mapping\UpdatedObjectMappingDAO;
23
use Mautic\IntegrationsBundle\Sync\DAO\Sync\Order\ObjectChangeDAO;
24
use Mautic\IntegrationsBundle\Sync\DAO\Sync\Report\ObjectDAO;
25
use Mautic\IntegrationsBundle\Sync\Exception\FieldNotFoundException;
26
use Mautic\IntegrationsBundle\Sync\Exception\ObjectDeletedException;
27
use Mautic\IntegrationsBundle\Sync\Exception\ObjectNotFoundException;
28
use Mautic\IntegrationsBundle\Sync\Exception\ObjectNotSupportedException;
29
use Mautic\IntegrationsBundle\Sync\SyncDataExchange\Internal\ObjectProvider;
30
use Mautic\IntegrationsBundle\Sync\SyncDataExchange\MauticSyncDataExchange;
31
use Mautic\LeadBundle\Model\FieldModel;
32
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
33
34
class MappingHelper
35
{
36
    /**
37
     * @var FieldModel
38
     */
39
    private $fieldModel;
40
41
    /**
42
     * @var ObjectMappingRepository
43
     */
44
    private $objectMappingRepository;
45
46
    /**
47
     * @var ObjectProvider
48
     */
49
    private $objectProvider;
50
51
    /**
52
     * @var ObjectMappingRepository
53
     */
54
    private $dispatcher;
55
56
    public function __construct(
57
        FieldModel $fieldModel,
58
        ObjectMappingRepository $objectMappingRepository,
59
        ObjectProvider $objectProvider,
60
        EventDispatcherInterface $dispatcher
61
    ) {
62
        $this->fieldModel              = $fieldModel;
63
        $this->objectMappingRepository = $objectMappingRepository;
64
        $this->objectProvider          = $objectProvider;
65
        $this->dispatcher              = $dispatcher;
66
    }
67
68
    /**
69
     * @return ObjectDAO
70
     *
71
     * @throws ObjectDeletedException
72
     * @throws ObjectNotFoundException
73
     * @throws ObjectNotSupportedException
74
     */
75
    public function findMauticObject(MappingManualDAO $mappingManualDAO, string $internalObjectName, ObjectDAO $integrationObjectDAO)
76
    {
77
        // Check if this contact is already tracked
78
        if ($internalObject = $this->objectMappingRepository->getInternalObject(
79
            $mappingManualDAO->getIntegration(),
80
            $integrationObjectDAO->getObject(),
81
            $integrationObjectDAO->getObjectId(),
82
            $internalObjectName
83
        )) {
84
            if ($internalObject['is_deleted']) {
85
                throw new ObjectDeletedException();
86
            }
87
88
            return new ObjectDAO(
89
                $internalObjectName,
90
                $internalObject['internal_object_id'],
91
                new \DateTime($internalObject['last_sync_date'], new \DateTimeZone('UTC'))
92
            );
93
        }
94
95
        // We don't know who this is so search Mautic
96
        $uniqueIdentifierFields = $this->fieldModel->getUniqueIdentifierFields(['object' => $internalObjectName]);
97
        $identifiers            = [];
98
99
        foreach ($uniqueIdentifierFields as $field => $fieldLabel) {
100
            try {
101
                $integrationField = $mappingManualDAO->getIntegrationMappedField($integrationObjectDAO->getObject(), $internalObjectName, $field);
102
                if ($integrationValue = $integrationObjectDAO->getField($integrationField)) {
103
                    $identifiers[$field] = $integrationValue->getValue()->getNormalizedValue();
104
                }
105
            } catch (FieldNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
106
            }
107
        }
108
109
        if (empty($identifiers)) {
110
            // No fields found to search for contact so return null
111
            return new ObjectDAO($internalObjectName, null);
112
        }
113
114
        try {
115
            $event = new InternalObjectFindEvent(
116
                $this->objectProvider->getObjectByName($internalObjectName)
117
            );
118
        } catch (ObjectNotFoundException $e) {
119
            // Throw this exception for BC.
120
            throw new ObjectNotSupportedException(MauticSyncDataExchange::NAME, $internalObjectName);
121
        }
122
123
        $event->setFieldValues($identifiers);
124
125
        $this->dispatcher->dispatch(
126
            IntegrationEvents::INTEGRATION_FIND_INTERNAL_RECORDS,
127
            $event
128
        );
129
130
        $foundObjects = $event->getFoundObjects();
131
132
        if (!$foundObjects) {
133
            // No contacts were found
134
            return new ObjectDAO($internalObjectName, null);
135
        }
136
137
        // Match found!
138
        $objectId = $foundObjects[0]['id'];
139
140
        // Let's store the relationship since we know it
141
        $objectMapping = new ObjectMapping();
142
        $objectMapping->setLastSyncDate($integrationObjectDAO->getChangeDateTime())
143
            ->setIntegration($mappingManualDAO->getIntegration())
144
            ->setIntegrationObjectName($integrationObjectDAO->getObject())
145
            ->setIntegrationObjectId($integrationObjectDAO->getObjectId())
146
            ->setInternalObjectName($internalObjectName)
147
            ->setInternalObjectId($objectId);
148
        $this->saveObjectMapping($objectMapping);
149
150
        return new ObjectDAO($internalObjectName, $objectId);
151
    }
152
153
    /**
154
     * Returns corresponding Mautic entity class name for the given Mautic object.
155
     *
156
     * @throws ObjectNotSupportedException
157
     */
158
    public function getMauticEntityClassName(string $internalObject): string
159
    {
160
        try {
161
            return $this->objectProvider->getObjectByName($internalObject)->getEntityName();
162
        } catch (ObjectNotFoundException $e) {
163
            // Throw this exception instead to keep BC.
164
            throw new ObjectNotSupportedException(MauticSyncDataExchange::NAME, $internalObject);
165
        }
166
    }
167
168
    /**
169
     * @return ObjectDAO
170
     *
171
     * @throws ObjectDeletedException
172
     */
173
    public function findIntegrationObject(string $integration, string $integrationObjectName, ObjectDAO $internalObjectDAO)
174
    {
175
        if ($integrationObject = $this->objectMappingRepository->getIntegrationObject(
176
            $integration,
177
            $internalObjectDAO->getObject(),
178
            $internalObjectDAO->getObjectId(),
179
            $integrationObjectName
180
        )) {
181
            if ($integrationObject['is_deleted']) {
182
                throw new ObjectDeletedException();
183
            }
184
185
            return new ObjectDAO(
186
                $integrationObjectName,
187
                $integrationObject['integration_object_id'],
188
                new \DateTime($integrationObject['last_sync_date'], new \DateTimeZone('UTC'))
189
            );
190
        }
191
192
        return new ObjectDAO($integrationObjectName, null);
193
    }
194
195
    /**
196
     * @param ObjectMapping[] $mappings
197
     */
198
    public function saveObjectMappings(array $mappings): void
199
    {
200
        foreach ($mappings as $mapping) {
201
            $this->saveObjectMapping($mapping);
202
        }
203
    }
204
205
    public function updateObjectMappings(array $mappings): void
206
    {
207
        foreach ($mappings as $mapping) {
208
            try {
209
                $this->updateObjectMapping($mapping);
210
            } catch (ObjectNotFoundException $exception) {
211
                continue;
212
            }
213
        }
214
    }
215
216
    /**
217
     * @param RemappedObjectDAO[] $mappings
218
     */
219
    public function remapIntegrationObjects(array $mappings): void
220
    {
221
        foreach ($mappings as $mapping) {
222
            $this->objectMappingRepository->updateIntegrationObject(
223
                $mapping->getIntegration(),
224
                $mapping->getOldObjectName(),
225
                $mapping->getOldObjectId(),
226
                $mapping->getNewObjectName(),
227
                $mapping->getNewObjectId()
228
            );
229
        }
230
    }
231
232
    /**
233
     * @param ObjectChangeDAO[] $objects
234
     */
235
    public function markAsDeleted(array $objects): void
236
    {
237
        foreach ($objects as $object) {
238
            $this->objectMappingRepository->markAsDeleted($object->getIntegration(), $object->getObject(), $object->getObjectId());
239
        }
240
    }
241
242
    private function saveObjectMapping(ObjectMapping $objectMapping): void
243
    {
244
        $this->objectMappingRepository->saveEntity($objectMapping);
245
        $this->objectMappingRepository->clear();
246
    }
247
248
    /**
249
     * @throws ObjectNotFoundException
250
     */
251
    private function updateObjectMapping(UpdatedObjectMappingDAO $updatedObjectMappingDAO): void
252
    {
253
        /** @var ObjectMapping $objectMapping */
254
        $objectMapping = $this->objectMappingRepository->findOneBy(
255
            [
256
                'integration'           => $updatedObjectMappingDAO->getIntegration(),
257
                'integrationObjectName' => $updatedObjectMappingDAO->getIntegrationObjectName(),
258
                'integrationObjectId'   => $updatedObjectMappingDAO->getIntegrationObjectId(),
259
            ]
260
        );
261
262
        if (!$objectMapping) {
263
            throw new ObjectNotFoundException($updatedObjectMappingDAO->getIntegrationObjectName().':'.$updatedObjectMappingDAO->getIntegrationObjectId());
264
        }
265
266
        $objectMapping->setLastSyncDate($updatedObjectMappingDAO->getObjectModifiedDate());
267
268
        $this->saveObjectMapping($objectMapping);
269
    }
270
}
271