1 | <?php |
||||
2 | |||||
3 | /* |
||||
4 | * @copyright 2014 Mautic Contributors. All rights reserved |
||||
5 | * @author Mautic |
||||
6 | * |
||||
7 | * @link http://mautic.org |
||||
8 | * |
||||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||||
10 | */ |
||||
11 | |||||
12 | namespace MauticPlugin\MauticCrmBundle\Integration; |
||||
13 | |||||
14 | use Doctrine\ORM\EntityManager; |
||||
15 | use Mautic\CoreBundle\Form\Type\ButtonGroupType; |
||||
16 | use Mautic\CoreBundle\Helper\CacheStorageHelper; |
||||
17 | use Mautic\CoreBundle\Helper\EncryptionHelper; |
||||
18 | use Mautic\CoreBundle\Helper\PathsHelper; |
||||
19 | use Mautic\CoreBundle\Model\NotificationModel; |
||||
20 | use Mautic\LeadBundle\Entity\Company; |
||||
21 | use Mautic\LeadBundle\Entity\Lead; |
||||
22 | use Mautic\LeadBundle\Model\CompanyModel; |
||||
23 | use Mautic\LeadBundle\Model\DoNotContact; |
||||
24 | use Mautic\LeadBundle\Model\FieldModel; |
||||
25 | use Mautic\LeadBundle\Model\LeadModel; |
||||
26 | use Mautic\PluginBundle\Entity\IntegrationEntity; |
||||
27 | use Mautic\PluginBundle\Entity\IntegrationEntityRepository; |
||||
28 | use Mautic\PluginBundle\Exception\ApiErrorException; |
||||
29 | use Mautic\PluginBundle\Model\IntegrationEntityModel; |
||||
30 | use Mautic\UserBundle\Model\UserModel; |
||||
31 | use Monolog\Logger; |
||||
32 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||||
33 | use Symfony\Component\Form\Extension\Core\Type\ChoiceType; |
||||
34 | use Symfony\Component\Form\FormBuilder; |
||||
35 | use Symfony\Component\HttpFoundation\RequestStack; |
||||
36 | use Symfony\Component\HttpFoundation\Session\Session; |
||||
37 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||||
38 | use Symfony\Component\Routing\Router; |
||||
39 | use Symfony\Component\Translation\TranslatorInterface; |
||||
40 | use Symfony\Component\Validator\Constraints\NotBlank; |
||||
41 | |||||
42 | class SugarcrmIntegration extends CrmAbstractIntegration |
||||
43 | { |
||||
44 | private $objects = [ |
||||
45 | 'Leads', |
||||
46 | 'Contacts', |
||||
47 | 'Accounts', |
||||
48 | ]; |
||||
49 | |||||
50 | private $sugarDncKeys = ['email_opt_out', 'invalid_email']; |
||||
51 | private $authorizationError; |
||||
52 | private $userModel; |
||||
53 | |||||
54 | /** |
||||
55 | * @var DoNotContact |
||||
56 | */ |
||||
57 | protected $doNotContactModel; |
||||
58 | |||||
59 | public function __construct( |
||||
60 | EventDispatcherInterface $eventDispatcher, |
||||
61 | CacheStorageHelper $cacheStorageHelper, |
||||
62 | EntityManager $entityManager, |
||||
63 | Session $session, |
||||
64 | RequestStack $requestStack, |
||||
65 | Router $router, |
||||
66 | TranslatorInterface $translator, |
||||
67 | Logger $logger, |
||||
68 | EncryptionHelper $encryptionHelper, |
||||
69 | LeadModel $leadModel, |
||||
70 | CompanyModel $companyModel, |
||||
71 | PathsHelper $pathsHelper, |
||||
72 | NotificationModel $notificationModel, |
||||
73 | FieldModel $fieldModel, |
||||
74 | IntegrationEntityModel $integrationEntityModel, |
||||
75 | DoNotContact $doNotContactModel, |
||||
76 | UserModel $userModel |
||||
77 | ) { |
||||
78 | $this->doNotContactModel = $doNotContactModel; |
||||
79 | $this->userModel = $userModel; |
||||
80 | |||||
81 | parent::__construct( |
||||
82 | $eventDispatcher, |
||||
83 | $cacheStorageHelper, |
||||
84 | $entityManager, |
||||
85 | $session, |
||||
86 | $requestStack, |
||||
87 | $router, |
||||
88 | $translator, |
||||
89 | $logger, |
||||
90 | $encryptionHelper, |
||||
91 | $leadModel, |
||||
92 | $companyModel, |
||||
93 | $pathsHelper, |
||||
94 | $notificationModel, |
||||
95 | $fieldModel, |
||||
96 | $integrationEntityModel, |
||||
97 | $doNotContactModel |
||||
98 | ); |
||||
99 | } |
||||
100 | |||||
101 | /** |
||||
102 | * Returns the name of the social integration that must match the name of the file. |
||||
103 | * |
||||
104 | * @return string |
||||
105 | */ |
||||
106 | public function getName() |
||||
107 | { |
||||
108 | return 'Sugarcrm'; |
||||
109 | } |
||||
110 | |||||
111 | /** |
||||
112 | * @return array |
||||
113 | */ |
||||
114 | public function getSupportedFeatures() |
||||
115 | { |
||||
116 | //Version 6.x supports all features |
||||
117 | if (isset($this->keys['version']) && '6' == $this->keys['version']) { |
||||
118 | return ['push_lead', 'get_leads', 'push_leads']; |
||||
119 | } |
||||
120 | //Only push_lead is currently supported for version 7 |
||||
121 | return ['push_lead', 'get_leads', 'push_leads']; |
||||
122 | } |
||||
123 | |||||
124 | /** |
||||
125 | * Get the array key for clientId. |
||||
126 | * |
||||
127 | * @return string |
||||
128 | */ |
||||
129 | public function getClientIdKey() |
||||
130 | { |
||||
131 | return 'client_id'; |
||||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * Get the array key for client secret. |
||||
136 | * |
||||
137 | * @return string |
||||
138 | */ |
||||
139 | public function getClientSecretKey() |
||||
140 | { |
||||
141 | return 'client_secret'; |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * {@inheritdoc} |
||||
146 | * |
||||
147 | * @return array |
||||
148 | */ |
||||
149 | public function getSecretKeys() |
||||
150 | { |
||||
151 | return [ |
||||
152 | 'client_secret', |
||||
153 | 'password', |
||||
154 | ]; |
||||
155 | } |
||||
156 | |||||
157 | /** |
||||
158 | * Get the array key for the auth token. |
||||
159 | * |
||||
160 | * @return string |
||||
161 | */ |
||||
162 | public function getAuthTokenKey() |
||||
163 | { |
||||
164 | return (isset($this->keys['version']) && '6' == $this->keys['version']) ? 'id' : 'access_token'; |
||||
165 | } |
||||
166 | |||||
167 | /** |
||||
168 | * SugarCRM 7 refresh tokens. |
||||
169 | */ |
||||
170 | public function getRefreshTokenKeys() |
||||
171 | { |
||||
172 | return [ |
||||
173 | 'refresh_token', |
||||
174 | 'expires', |
||||
175 | ]; |
||||
176 | } |
||||
177 | |||||
178 | /** |
||||
179 | * {@inheritdoc} |
||||
180 | * |
||||
181 | * @return string |
||||
182 | */ |
||||
183 | public function getAccessTokenUrl() |
||||
184 | { |
||||
185 | $apiUrl = ('6' == $this->keys['version']) ? 'service/v4_1/rest.php' : 'rest/v10/oauth2/token'; |
||||
186 | |||||
187 | return sprintf('%s/%s', $this->keys['sugarcrm_url'], $apiUrl); |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * {@inheritdoc} |
||||
192 | * |
||||
193 | * @return string |
||||
194 | */ |
||||
195 | public function getAuthLoginUrl() |
||||
196 | { |
||||
197 | return $this->router->generate('mautic_integration_auth_callback', ['integration' => $this->getName()]); |
||||
198 | } |
||||
199 | |||||
200 | /** |
||||
201 | * Retrieves and stores tokens returned from oAuthLogin. |
||||
202 | * |
||||
203 | * @param array $settings |
||||
204 | * @param array $parameters |
||||
205 | * |
||||
206 | * @return array |
||||
207 | */ |
||||
208 | public function authCallback($settings = [], $parameters = []) |
||||
209 | { |
||||
210 | if (isset($this->keys['version']) && '6' == $this->keys['version']) { |
||||
211 | $success = $this->isAuthorized(); |
||||
212 | if (!$success) { |
||||
213 | return $this->authorizationError; |
||||
214 | } else { |
||||
215 | return false; |
||||
216 | } |
||||
217 | } else { |
||||
218 | $settings = [ |
||||
219 | 'grant_type' => 'password', |
||||
220 | 'ignore_redirecturi' => true, |
||||
221 | ]; |
||||
222 | $parameters = [ |
||||
223 | 'username' => $this->keys['username'], |
||||
224 | 'password' => $this->keys['password'], |
||||
225 | 'platform' => 'base', |
||||
226 | ]; |
||||
227 | |||||
228 | return parent::authCallback($settings, $parameters); |
||||
229 | } |
||||
230 | } |
||||
231 | |||||
232 | /** |
||||
233 | * {@inheritdoc} |
||||
234 | * |
||||
235 | * @return array |
||||
236 | */ |
||||
237 | public function getRequiredKeyFields() |
||||
238 | { |
||||
239 | return [ |
||||
240 | 'sugarcrm_url' => 'mautic.sugarcrm.form.url', |
||||
241 | 'client_id' => 'mautic.sugarcrm.form.clientkey', |
||||
242 | 'client_secret' => 'mautic.sugarcrm.form.clientsecret', |
||||
243 | 'username' => 'mautic.sugarcrm.form.username', |
||||
244 | 'password' => 'mautic.sugarcrm.form.password', |
||||
245 | ]; |
||||
246 | } |
||||
247 | |||||
248 | /** |
||||
249 | * Get available company fields for choices in the config UI. |
||||
250 | * |
||||
251 | * @param array $settings |
||||
252 | * |
||||
253 | * @return array |
||||
254 | */ |
||||
255 | public function getFormCompanyFields($settings = []) |
||||
256 | { |
||||
257 | return $this->getFormFieldsByObject('company', $settings); |
||||
258 | } |
||||
259 | |||||
260 | /** |
||||
261 | * Get available fields for choices in the config UI. |
||||
262 | * |
||||
263 | * @param array $settings |
||||
264 | * |
||||
265 | * @return array |
||||
266 | */ |
||||
267 | public function getFormLeadFields($settings = []) |
||||
268 | { |
||||
269 | if (!$this->isAuthorized()) { |
||||
270 | return []; |
||||
271 | } |
||||
272 | |||||
273 | if (isset($settings['feature_settings']['objects'])) { |
||||
274 | // combine keys with values |
||||
275 | $settings['feature_settings']['objects'] = array_combine( |
||||
276 | array_values($settings['feature_settings']['objects']), |
||||
277 | $settings['feature_settings']['objects'] |
||||
278 | ); |
||||
279 | } |
||||
280 | |||||
281 | // unset company object |
||||
282 | if (isset($settings['feature_settings']['objects']['company'])) { |
||||
283 | unset($settings['feature_settings']['objects']['company']); |
||||
284 | } |
||||
285 | |||||
286 | if (empty($settings['feature_settings']['objects'])) { |
||||
287 | // BC force add Leads and Contacts from Integration |
||||
288 | $settings['feature_settings']['objects']['Leads'] = 'Leads'; |
||||
289 | $settings['feature_settings']['objects']['Contacts'] = 'Contacts'; |
||||
290 | } |
||||
291 | |||||
292 | $fields = []; |
||||
293 | // merge all arrays from level 1 |
||||
294 | $fieldsromObjects = $this->getAvailableLeadFields($settings); |
||||
295 | foreach ($fieldsromObjects as $fieldsFromObject) { |
||||
296 | $fields = array_merge($fields, $fieldsFromObject); |
||||
297 | } |
||||
298 | |||||
299 | return $fields; |
||||
300 | } |
||||
301 | |||||
302 | /** |
||||
303 | * @param array $settings |
||||
304 | * |
||||
305 | * @return array |
||||
306 | * |
||||
307 | * @throws \Exception |
||||
308 | */ |
||||
309 | public function getAvailableLeadFields($settings = []) |
||||
310 | { |
||||
311 | $sugarFields = []; |
||||
312 | $silenceExceptions = (isset($settings['silence_exceptions'])) ? $settings['silence_exceptions'] : true; |
||||
313 | $sugarObjects = []; |
||||
314 | |||||
315 | if (!empty($settings['feature_settings']['objects'])) { |
||||
316 | $sugarObjects = $settings['feature_settings']['objects']; |
||||
317 | } else { |
||||
318 | $sugarObjects['Leads'] = 'Leads'; |
||||
319 | $sugarObjects['Contacts'] = 'Contacts'; |
||||
320 | $settings['feature_settings']['objects'] = $sugarObjects; |
||||
321 | } |
||||
322 | |||||
323 | $isRequired = function (array $field, $object) { |
||||
324 | switch (true) { |
||||
325 | case 'Leads' === $object && ('webtolead_email1' === $field['name'] || 'email1' === $field['name']): |
||||
326 | case 'Contacts' === $object && 'email1' === $field['name']: |
||||
327 | case 'id' !== $field['name'] && !empty($field['required']): |
||||
328 | return true; |
||||
329 | default: |
||||
330 | return false; |
||||
331 | } |
||||
332 | }; |
||||
333 | |||||
334 | try { |
||||
335 | if (!empty($sugarObjects) and is_array($sugarObjects)) { |
||||
336 | foreach ($sugarObjects as $sObject) { |
||||
337 | if ('Accounts' === $sObject) { |
||||
338 | // Match Sugar object to Mautic's |
||||
339 | $sObject = 'company'; |
||||
340 | } |
||||
341 | $sObject = trim($sObject); |
||||
342 | if ($this->isAuthorized()) { |
||||
343 | // Check the cache first |
||||
344 | $settings['cache_suffix'] = $cacheSuffix = '.'.$sObject; |
||||
345 | if ($fields = parent::getAvailableLeadFields($settings)) { |
||||
346 | if (('company' === $sObject && isset($fields['id'])) || isset($fields['id__'.$sObject])) { |
||||
347 | $sugarFields[$sObject] = $fields; |
||||
348 | continue; |
||||
349 | } |
||||
350 | } |
||||
351 | if (!isset($sugarFields[$sObject])) { |
||||
352 | $fields = $this->getApiHelper()->getLeadFields($sObject); |
||||
353 | |||||
354 | if (null != $fields && !empty($fields)) { |
||||
355 | if (isset($fields['module_fields']) && !empty($fields['module_fields'])) { |
||||
356 | //6.x/community |
||||
357 | |||||
358 | foreach ($fields['module_fields'] as $fieldInfo) { |
||||
359 | if (isset($fieldInfo['name']) && (!in_array($fieldInfo['type'], ['id', 'assigned_user_name', 'link', 'relate']) || ('id' == $fieldInfo['type'] && 'id' == $fieldInfo['name']) |
||||
360 | ) |
||||
361 | ) { |
||||
362 | $type = 'string'; |
||||
363 | $fieldName = (false === strpos($fieldInfo['name'], |
||||
364 | 'webtolead_email')) ? $fieldInfo['name'] : str_replace('webtolead_', |
||||
365 | '', $fieldInfo['name']); |
||||
366 | // make these congruent as some come in with colons and some do not |
||||
367 | $label = str_replace(':', '', $fieldInfo['label']); |
||||
368 | if ('company' !== $sObject) { |
||||
369 | $sugarFields[$sObject][$fieldName.'__'.$sObject] = [ |
||||
370 | 'type' => $type, |
||||
371 | 'label' => $sObject.'-'.$label, |
||||
372 | 'required' => $isRequired($fieldInfo, $sObject), |
||||
373 | 'group' => $sObject, |
||||
374 | 'optionLabel' => $fieldInfo['label'], |
||||
375 | ]; |
||||
376 | } else { |
||||
377 | $sugarFields[$sObject][$fieldName] = [ |
||||
378 | 'type' => $type, |
||||
379 | 'label' => $label, |
||||
380 | 'required' => $isRequired($fieldInfo, $sObject), |
||||
381 | ]; |
||||
382 | } |
||||
383 | } |
||||
384 | } |
||||
385 | } elseif (isset($fields['fields']) && !empty($fields['fields'])) { |
||||
386 | //7.x |
||||
387 | foreach ($fields['fields'] as $fieldInfo) { |
||||
388 | if (isset($fieldInfo['name']) && empty($fieldInfo['readonly']) |
||||
389 | && (!in_array( |
||||
390 | $fieldInfo['type'], |
||||
391 | ['id', 'team_list', 'link', 'relate'] |
||||
392 | ) |
||||
393 | || |
||||
394 | ('id' == $fieldInfo['type'] && 'id' == $fieldInfo['name']) |
||||
395 | ) |
||||
396 | ) { |
||||
397 | if (!empty($fieldInfo['comment'])) { |
||||
398 | $label = $fieldInfo['comment']; |
||||
399 | } elseif (!empty($fieldInfo['help'])) { |
||||
400 | $label = $fieldInfo['help']; |
||||
401 | } else { |
||||
402 | $label = ucfirst(str_replace('_', ' ', $fieldInfo['name'])); |
||||
403 | } |
||||
404 | // make these congruent as some come in with colons and some do not |
||||
405 | $label = str_replace(':', '', $label); |
||||
406 | |||||
407 | $fieldName = (false === strpos($fieldInfo['name'], 'webtolead_email')) |
||||
408 | ? $fieldInfo['name'] |
||||
409 | : str_replace( |
||||
410 | 'webtolead_', |
||||
411 | '', |
||||
412 | $fieldInfo['name'] |
||||
413 | ); |
||||
414 | |||||
415 | $type = 'string'; |
||||
416 | if ('company' !== $sObject) { |
||||
417 | $sugarFields[$sObject][$fieldName.'__'.$sObject] = [ |
||||
418 | 'type' => $type, |
||||
419 | 'label' => $sObject.'-'.$label, |
||||
420 | 'required' => $isRequired($fieldInfo, $sObject), |
||||
421 | 'group' => $sObject, |
||||
422 | 'optionLabel' => $label, |
||||
423 | ]; |
||||
424 | } else { |
||||
425 | $sugarFields[$sObject][$fieldName] = [ |
||||
426 | 'type' => $type, |
||||
427 | 'label' => $label, |
||||
428 | 'required' => $isRequired($fieldInfo, $sObject), |
||||
429 | ]; |
||||
430 | } |
||||
431 | } |
||||
432 | } |
||||
433 | } |
||||
434 | } |
||||
435 | $this->cache->set('leadFields'.$cacheSuffix, $sugarFields[$sObject]); |
||||
436 | } |
||||
437 | } else { |
||||
438 | throw new ApiErrorException($this->authorizationError); |
||||
439 | } |
||||
440 | } |
||||
441 | } |
||||
442 | } catch (\Exception $e) { |
||||
443 | $this->logIntegrationError($e); |
||||
444 | |||||
445 | if (!$silenceExceptions) { |
||||
446 | throw $e; |
||||
447 | } |
||||
448 | } |
||||
449 | |||||
450 | return $sugarFields; |
||||
451 | } |
||||
452 | |||||
453 | /** |
||||
454 | * @param $params |
||||
455 | * |
||||
456 | * @return mixed |
||||
457 | */ |
||||
458 | public function getFetchQuery($params) |
||||
459 | { |
||||
460 | return $params; |
||||
461 | } |
||||
462 | |||||
463 | /** |
||||
464 | * @param array $params |
||||
465 | * @param array|null $query |
||||
466 | * |
||||
467 | * @return int|null |
||||
468 | */ |
||||
469 | public function getCompanies($params = [], $query = null, $executed = null) |
||||
0 ignored issues
–
show
The parameter
$executed is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.
Loading history...
|
|||||
470 | { |
||||
471 | $executed = null; |
||||
472 | |||||
473 | $sugarObject = 'Accounts'; |
||||
474 | $params['max_results'] = 100; |
||||
475 | if (!isset($params['offset'])) { |
||||
476 | //First call |
||||
477 | $params['offset'] = 0; |
||||
478 | } |
||||
479 | |||||
480 | $query = $params; |
||||
481 | |||||
482 | try { |
||||
483 | if ($this->isAuthorized()) { |
||||
484 | $result = $this->getApiHelper()->getLeads($query, $sugarObject); |
||||
0 ignored issues
–
show
The method
getLeads() does not exist on MauticPlugin\MauticCrmBundle\Api\CrmApi . It seems like you code against a sub-type of MauticPlugin\MauticCrmBundle\Api\CrmApi such as MauticPlugin\MauticCrmBundle\Api\DynamicsApi or MauticPlugin\MauticCrmBundle\Api\SalesforceApi or MauticPlugin\MauticCrmBundle\Api\ZohoApi or MauticPlugin\MauticCrmBundle\Api\SugarcrmApi .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
485 | $params['offset'] = $result['next_offset']; |
||||
486 | $executed += $this->amendLeadDataBeforeMauticPopulate($result, $sugarObject); |
||||
487 | if ( |
||||
488 | (isset($result['total_count']) && $result['total_count'] > $params['offset']) //Sugar 6 |
||||
489 | || (!isset($result['total_count']) && $params['offset'] > -1)) { //Sugar 7 |
||||
490 | $result = null; |
||||
0 ignored issues
–
show
|
|||||
491 | $executed += $this->getCompanies($params, null, $executed); |
||||
492 | } |
||||
493 | |||||
494 | return $executed; |
||||
495 | } |
||||
496 | } catch (\Exception $e) { |
||||
497 | $this->logIntegrationError($e); |
||||
498 | } |
||||
499 | |||||
500 | return $executed; |
||||
501 | } |
||||
502 | |||||
503 | /** |
||||
504 | * @param array $params |
||||
505 | * |
||||
506 | * @return int|null |
||||
507 | * |
||||
508 | * @throws \Exception |
||||
509 | * To be modified |
||||
510 | */ |
||||
511 | public function pushLeadActivity($params = []) |
||||
512 | { |
||||
513 | $executed = null; |
||||
514 | |||||
515 | $query = $this->getFetchQuery($params); |
||||
516 | $config = $this->mergeConfigToFeatureSettings([]); |
||||
517 | |||||
518 | /** @var SugarApi $apiHelper */ |
||||
519 | $apiHelper = $this->getApiHelper(); |
||||
520 | |||||
521 | $sugarObjects[] = 'Leads'; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
522 | if (isset($config['objects']) && !empty($config['objects'])) { |
||||
523 | $sugarObjects = $config['objects']; |
||||
524 | } |
||||
525 | |||||
526 | /** @var IntegrationEntityRepository $integrationEntityRepo */ |
||||
527 | $integrationEntityRepo = $this->em->getRepository('MauticPluginBundle:IntegrationEntity'); |
||||
528 | $startDate = new \DateTime($query['start']); |
||||
529 | $endDate = new \DateTime($query['end']); |
||||
530 | $limit = 100; |
||||
531 | |||||
532 | foreach ($sugarObjects as $object) { |
||||
533 | try { |
||||
534 | if ($this->isAuthorized()) { |
||||
535 | // Get first batch |
||||
536 | $start = 0; |
||||
537 | $sugarIds = $integrationEntityRepo->getIntegrationsEntityId( |
||||
538 | 'Sugarcrm', |
||||
539 | $object, |
||||
540 | 'lead', |
||||
541 | null, |
||||
542 | $startDate->format('Y-m-d H:i:s'), |
||||
543 | $endDate->format('Y-m-d H:i:s'), |
||||
544 | true, |
||||
545 | $start, |
||||
546 | $limit |
||||
547 | ); |
||||
548 | |||||
549 | while (!empty($sugarIds)) { |
||||
550 | $executed += count($sugarIds); |
||||
551 | |||||
552 | // Extract a list of lead Ids |
||||
553 | $leadIds = []; |
||||
554 | foreach ($sugarIds as $ids) { |
||||
555 | $leadIds[] = $ids['internal_entity_id']; |
||||
556 | } |
||||
557 | |||||
558 | // Collect lead activity for this batch |
||||
559 | $leadActivity = $this->getLeadData( |
||||
560 | $startDate, |
||||
561 | $endDate, |
||||
562 | $leadIds |
||||
563 | ); |
||||
564 | |||||
565 | $sugarLeadData = []; |
||||
566 | foreach ($sugarIds as $ids) { |
||||
567 | $leadId = $ids['internal_entity_id']; |
||||
568 | if (isset($leadActivity[$leadId])) { |
||||
569 | $sugarId = $ids['integration_entity_id']; |
||||
570 | $sugarLeadData[$sugarId] = $leadActivity[$leadId]; |
||||
571 | $sugarLeadData[$sugarId]['id'] = $ids['integration_entity_id']; |
||||
572 | $sugarLeadData[$sugarId]['leadId'] = $ids['internal_entity_id']; |
||||
573 | $sugarLeadData[$sugarId]['leadUrl'] = $this->router->generate( |
||||
574 | 'mautic_plugin_timeline_view', |
||||
575 | ['integration' => 'Sugarcrm', 'leadId' => $leadId], |
||||
576 | UrlGeneratorInterface::ABSOLUTE_URL |
||||
577 | ); |
||||
578 | } |
||||
579 | } |
||||
580 | |||||
581 | if (!empty($sugarLeadData)) { |
||||
582 | $apiHelper->createLeadActivity($sugarLeadData, $object); |
||||
583 | } |
||||
584 | |||||
585 | // Get the next batch |
||||
586 | $start += $limit; |
||||
587 | $sugarIds = $integrationEntityRepo->getIntegrationsEntityId( |
||||
588 | 'Sugarcrm', |
||||
589 | $object, |
||||
590 | 'lead', |
||||
591 | null, |
||||
592 | $startDate->format('Y-m-d H:i:s'), |
||||
593 | $endDate->format('Y-m-d H:i:s'), |
||||
594 | true, |
||||
595 | $start, |
||||
596 | $limit |
||||
597 | ); |
||||
598 | } |
||||
599 | } |
||||
600 | } catch (\Exception $e) { |
||||
601 | $this->logIntegrationError($e); |
||||
602 | } |
||||
603 | } |
||||
604 | |||||
605 | return $executed; |
||||
606 | } |
||||
607 | |||||
608 | /** |
||||
609 | * @param array $params |
||||
610 | * @param array|null $query |
||||
611 | * |
||||
612 | * @return int|null |
||||
613 | */ |
||||
614 | public function getLeads($params = [], $query = null, &$executed = null, $result = [], $object = 'Leads') |
||||
615 | { |
||||
616 | $params['max_results'] = 100; |
||||
617 | $config = $this->mergeConfigToFeatureSettings([]); |
||||
0 ignored issues
–
show
|
|||||
618 | |||||
619 | if (!isset($params['offset'])) { |
||||
620 | //First call |
||||
621 | $params['offset'] = 0; |
||||
622 | } |
||||
623 | $query = $params; |
||||
624 | |||||
625 | try { |
||||
626 | if ($this->isAuthorized()) { |
||||
627 | if ('Activity' !== $object and 'company' !== $object) { |
||||
628 | $result = $this->getApiHelper()->getLeads($query, $object); |
||||
629 | $params['offset'] = $result['next_offset']; |
||||
630 | $executed += $this->amendLeadDataBeforeMauticPopulate($result, $object); |
||||
631 | if ( |
||||
632 | (isset($result['total_count']) && $result['total_count'] > $params['offset']) //Sugar 6 |
||||
633 | || (!isset($result['total_count']) && $params['offset'] > -1)) { //Sugar 7 |
||||
634 | $params['object'] = $object; |
||||
635 | $executed += $this->getLeads($params, null, $executed, [], $object); |
||||
636 | } |
||||
637 | } |
||||
638 | |||||
639 | return $executed; |
||||
640 | } |
||||
641 | } catch (\Exception $e) { |
||||
642 | $this->logIntegrationError($e); |
||||
643 | } |
||||
644 | |||||
645 | return $executed; |
||||
646 | } |
||||
647 | |||||
648 | /** |
||||
649 | * @param $response |
||||
650 | * |
||||
651 | * @return string |
||||
652 | */ |
||||
653 | public function getErrorsFromResponse($response) |
||||
654 | { |
||||
655 | if ('6' == $this->keys['version']) { |
||||
656 | if (!empty($response['name'])) { |
||||
657 | return $response['description']; |
||||
658 | } else { |
||||
659 | return $this->translator->trans('mautic.integration.error.genericerror', [], 'flashes'); |
||||
660 | } |
||||
661 | } else { |
||||
662 | return parent::getErrorsFromResponse($response); |
||||
663 | } |
||||
664 | } |
||||
665 | |||||
666 | /** |
||||
667 | * {@inheritdoc} |
||||
668 | * |
||||
669 | * @return string |
||||
670 | */ |
||||
671 | public function getAuthenticationType() |
||||
672 | { |
||||
673 | return (isset($this->keys['version']) && '6' == $this->keys['version']) ? 'rest' : 'oauth2'; |
||||
674 | } |
||||
675 | |||||
676 | /** |
||||
677 | * {@inheritdoc} |
||||
678 | * |
||||
679 | * @return bool |
||||
680 | */ |
||||
681 | public function getDataPriority() |
||||
682 | { |
||||
683 | return true; |
||||
684 | } |
||||
685 | |||||
686 | /** |
||||
687 | * @param $url |
||||
688 | * @param $parameters |
||||
689 | * @param $method |
||||
690 | * @param $settings |
||||
691 | * @param $authType |
||||
692 | * |
||||
693 | * @return array |
||||
694 | */ |
||||
695 | public function prepareRequest($url, $parameters, $method, $settings, $authType) |
||||
696 | { |
||||
697 | if ('oauth2' == $authType && empty($settings['authorize_session']) && isset($this->keys['access_token'])) { |
||||
698 | // Append the access token as the oauth-token header |
||||
699 | $headers = [ |
||||
700 | "oauth-token: {$this->keys['access_token']}", |
||||
701 | ]; |
||||
702 | |||||
703 | return [$parameters, $headers]; |
||||
704 | } else { |
||||
705 | return parent::prepareRequest($url, $parameters, $method, $settings, $authType); |
||||
706 | } |
||||
707 | } |
||||
708 | |||||
709 | /** |
||||
710 | * {@inheritdoc} |
||||
711 | * |
||||
712 | * @return bool |
||||
713 | */ |
||||
714 | public function isAuthorized() |
||||
715 | { |
||||
716 | if (!$this->isConfigured()) { |
||||
717 | return false; |
||||
718 | } |
||||
719 | |||||
720 | if (!isset($this->keys['version'])) { |
||||
721 | return false; |
||||
722 | } |
||||
723 | |||||
724 | if ('6' == $this->keys['version']) { |
||||
725 | $loginParams = [ |
||||
726 | 'user_auth' => [ |
||||
727 | 'user_name' => $this->keys['username'], |
||||
728 | 'password' => md5($this->keys['password']), |
||||
729 | 'version' => '1', |
||||
730 | ], |
||||
731 | 'application_name' => 'Mautic', |
||||
732 | 'name_value_list' => [], |
||||
733 | 'method' => 'login', |
||||
734 | 'input_type' => 'JSON', |
||||
735 | 'response_type' => 'JSON', |
||||
736 | ]; |
||||
737 | $parameters = [ |
||||
738 | 'method' => 'login', |
||||
739 | 'input_type' => 'JSON', |
||||
740 | 'response_type' => 'JSON', |
||||
741 | 'rest_data' => json_encode($loginParams), |
||||
742 | ]; |
||||
743 | |||||
744 | $settings['auth_type'] = 'rest'; |
||||
745 | $settings['authorize_session'] = true; |
||||
746 | |||||
747 | $response = $this->makeRequest($this->getAccessTokenUrl(), $parameters, 'GET', $settings); |
||||
748 | |||||
749 | unset($response['module'], $response['name_value_list']); |
||||
750 | $error = $this->extractAuthKeys($response, 'id'); |
||||
751 | |||||
752 | $this->authorizationError = $error; |
||||
753 | |||||
754 | return empty($error); |
||||
755 | } else { |
||||
756 | if ($this->isConfigured()) { |
||||
757 | // SugarCRM 7 uses password grant type so login each time to ensure session is valid |
||||
758 | $this->authCallback(); |
||||
759 | } |
||||
760 | |||||
761 | return parent::isAuthorized(); |
||||
762 | } |
||||
763 | } |
||||
764 | |||||
765 | /** |
||||
766 | * {@inheritdoc} |
||||
767 | * |
||||
768 | * @param $data |
||||
769 | */ |
||||
770 | public function prepareResponseForExtraction($data) |
||||
771 | { |
||||
772 | // Extract expiry and set expires for 7.x |
||||
773 | if (is_array($data) && isset($data['expires_in'])) { |
||||
774 | $data['expires'] = $data['expires_in'] + time(); |
||||
775 | } |
||||
776 | |||||
777 | return $data; |
||||
778 | } |
||||
779 | |||||
780 | /** |
||||
781 | * Amend mapped lead data before creating to Mautic. |
||||
782 | * |
||||
783 | * @param array $data |
||||
784 | * @param string $object |
||||
785 | * |
||||
786 | * @return int |
||||
787 | */ |
||||
788 | public function amendLeadDataBeforeMauticPopulate($data, $object) |
||||
789 | { |
||||
790 | $settings['feature_settings']['objects'][] = $object; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
791 | $fields = array_keys($this->getAvailableLeadFields($settings)); |
||||
792 | $params['fields'] = implode(',', $fields); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
793 | |||||
794 | $count = 0; |
||||
795 | $entity = null; |
||||
796 | |||||
797 | /** @var IntegrationEntityRepository $integrationEntityRepo */ |
||||
798 | $integrationEntityRepo = $this->em->getRepository('MauticPluginBundle:IntegrationEntity'); |
||||
799 | $companyRepo = $this->em->getRepository('MauticLeadBundle:Company'); |
||||
800 | |||||
801 | $sugarRejectedLeads = []; |
||||
802 | if (isset($data['entry_list'])) { |
||||
803 | $SUGAR_VERSION = '6'; |
||||
804 | $RECORDS_LIST_NAME = 'entry_list'; |
||||
805 | $MODULE_FIELD_NAME = 'module_name'; |
||||
806 | } |
||||
807 | if (isset($data['records'])) { |
||||
808 | $SUGAR_VERSION = '7'; |
||||
809 | $RECORDS_LIST_NAME = 'records'; |
||||
810 | $MODULE_FIELD_NAME = '_module'; |
||||
811 | } |
||||
812 | |||||
813 | if (isset($data[$RECORDS_LIST_NAME]) and 'Activity' !== $object) { |
||||
814 | //Get assigned user ids |
||||
815 | $assignedUserIds = []; |
||||
816 | $onwerEmailByAssignedUserId = []; |
||||
817 | if ('Leads' == $object || 'Contacts' == $object || 'Accounts' == $object) { |
||||
818 | foreach ($data[$RECORDS_LIST_NAME] as $record) { |
||||
819 | if ('6' == $SUGAR_VERSION) { |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
820 | foreach ($record['name_value_list'] as $item) { |
||||
821 | if ('assigned_user_id' == $item['name'] && $item['value'] && '' != $item['value']) { |
||||
822 | $assignedUserIds[] = $item['value']; |
||||
823 | } |
||||
824 | } |
||||
825 | } else { |
||||
826 | if (isset($record['assigned_user_id']) && '' != $record['assigned_user_id']) { |
||||
827 | $assignedUserIds[] = $record['assigned_user_id']; |
||||
828 | } |
||||
829 | } |
||||
830 | } |
||||
831 | } |
||||
832 | if (!empty($assignedUserIds)) { |
||||
833 | $assignedUserIds = array_unique($assignedUserIds); |
||||
834 | $onwerEmailByAssignedUserId = $this->getApiHelper()->getEmailBySugarUserId(['ids' => $assignedUserIds]); |
||||
0 ignored issues
–
show
The method
getEmailBySugarUserId() does not exist on MauticPlugin\MauticCrmBundle\Api\CrmApi . It seems like you code against a sub-type of MauticPlugin\MauticCrmBundle\Api\CrmApi such as MauticPlugin\MauticCrmBundle\Api\SugarcrmApi .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
835 | } |
||||
836 | |||||
837 | //Get all leads emails |
||||
838 | $checkEmailsInSugar = []; |
||||
839 | if ('Leads' == $object) { |
||||
840 | if ('6' == $SUGAR_VERSION) { |
||||
841 | foreach ($data[$RECORDS_LIST_NAME] as $record) { |
||||
842 | foreach ($record['name_value_list'] as $item) { |
||||
843 | if ('email1' == $item['name'] && $item['value'] && '' != $item['value']) { |
||||
844 | $checkEmailsInSugar[] = $item['value']; |
||||
845 | } |
||||
846 | } |
||||
847 | } |
||||
848 | } else { |
||||
849 | if (isset($record['email1']) && '' != $record['email1']) { |
||||
850 | $checkEmailsInSugar[] = $record['email1']; |
||||
851 | } |
||||
852 | } |
||||
853 | } |
||||
854 | if (!empty($checkEmailsInSugar)) { |
||||
855 | $sugarLeads = $this->getApiHelper()->getLeads(['checkemail_contacts' => $checkEmailsInSugar, 'offset' => 0, 'max_results' => 1000], 'Contacts'); |
||||
856 | if (isset($sugarLeads[$RECORDS_LIST_NAME])) { |
||||
857 | foreach ($sugarLeads[$RECORDS_LIST_NAME] as $record) { |
||||
858 | $sugarLeadRecord = []; |
||||
0 ignored issues
–
show
|
|||||
859 | if ('6' == $SUGAR_VERSION) { |
||||
860 | foreach ($record['name_value_list'] as $item) { |
||||
861 | if ('email1' == $item['name'] && $item['value'] && '' != $item['value']) { |
||||
862 | $sugarRejectedLeads[] = $item['value']; |
||||
863 | } |
||||
864 | } |
||||
865 | } else { |
||||
866 | if (isset($record['email1']) && '' != $record['email1']) { |
||||
867 | $sugarRejectedLeads[] = $record['email1']; |
||||
868 | } |
||||
869 | } |
||||
870 | } |
||||
871 | } |
||||
872 | } |
||||
873 | |||||
874 | foreach ($data[$RECORDS_LIST_NAME] as $record) { |
||||
875 | $integrationEntities = []; |
||||
876 | $dataObject = []; |
||||
877 | if (isset($record[$MODULE_FIELD_NAME]) && 'Accounts' == $record[$MODULE_FIELD_NAME]) { |
||||
878 | $newName = ''; |
||||
879 | } else { |
||||
880 | $newName = '__'.$object; |
||||
881 | } |
||||
882 | if ('6' == $SUGAR_VERSION) { |
||||
883 | foreach ($record['name_value_list'] as $item) { |
||||
884 | if ('Activity' !== $object) { |
||||
885 | if ($this->checkIfSugarCrmMultiSelectString($item['value'])) { |
||||
886 | $convertedMultiSelectString = $this->convertSuiteCrmToMauticMultiSelect($item['value']); |
||||
887 | $dataObject[$item['name'].$newName] = $convertedMultiSelectString; |
||||
888 | } else { |
||||
889 | $dataObject[$item['name'].$newName] = $item['value']; |
||||
890 | } |
||||
891 | if ('date_entered' == $item['name']) { |
||||
892 | $itemDateEntered = new \DateTime($item['value']); |
||||
0 ignored issues
–
show
|
|||||
893 | } |
||||
894 | if ('date_modified' == $item['name']) { |
||||
895 | $itemDateModified = new \DateTime($item['value']); |
||||
0 ignored issues
–
show
|
|||||
896 | } |
||||
897 | } |
||||
898 | } |
||||
899 | } else { |
||||
900 | if ('Activity' !== $object) { |
||||
901 | if (isset($record['date_entered']) && '' != $record['date_entered']) { |
||||
902 | $itemDateEntered = new \DateTime($record['date_entered']); |
||||
903 | } |
||||
904 | if (isset($record['date_modified']) && '' != $record['date_modified']) { |
||||
905 | $itemDateEntered = new \DateTime($record['date_modified']); |
||||
906 | } |
||||
907 | foreach ($record as $k => $item) { |
||||
908 | $dataObject[$k.$newName] = $item; |
||||
909 | } |
||||
910 | } |
||||
911 | } |
||||
912 | if ('Leads' == $object && isset($dataObject['email1__Leads']) && null != $dataObject['email1__Leads'] |
||||
913 | && '' != $dataObject['email1__Leads'] && in_array($dataObject['email1__Leads'], $sugarRejectedLeads)) { |
||||
914 | continue; //Lead email is already in Sugar Contacts. Do not carry on |
||||
915 | } |
||||
916 | |||||
917 | if (!empty($dataObject)) { |
||||
918 | if ('Leads' == $object or 'Contacts' == $object) { |
||||
919 | if (isset($dataObject['assigned_user_id'.'__'.$object])) { |
||||
920 | $auid = $dataObject['assigned_user_id'.'__'.$object]; |
||||
921 | if (isset($onwerEmailByAssignedUserId[$auid])) { |
||||
922 | $dataObject['owner_email'] = $onwerEmailByAssignedUserId[$auid]; |
||||
923 | } |
||||
924 | } |
||||
925 | $mauticObjectReference = 'lead'; |
||||
926 | $entity = $this->getMauticLead($dataObject, true, null, null, $object); |
||||
927 | $detachClass = Lead::class; |
||||
928 | $company = null; |
||||
929 | $this->fetchDncToMautic($entity, $data); |
||||
930 | if ($entity && isset($dataObject['account_id'.$newName]) && '' != trim($dataObject['account_id'.$newName])) { |
||||
931 | $integrationCompanyEntity = $integrationEntityRepo->findOneBy( |
||||
932 | [ |
||||
933 | 'integration' => 'Sugarcrm', |
||||
934 | 'integrationEntity' => 'Accounts', |
||||
935 | 'internalEntity' => 'company', |
||||
936 | 'integrationEntityId' => $dataObject['account_id'.$newName], |
||||
937 | ] |
||||
938 | ); |
||||
939 | if (isset($integrationCompanyEntity)) { |
||||
940 | $companyId = $integrationCompanyEntity->getInternalEntityId(); |
||||
941 | $company = $companyRepo->find($companyId); |
||||
942 | |||||
943 | $this->companyModel->addLeadToCompany($company, $entity); |
||||
944 | $this->em->clear(Company::class); |
||||
945 | $this->em->detach($entity); |
||||
946 | } |
||||
947 | } |
||||
948 | } elseif ('Accounts' === $object) { |
||||
949 | $entity = $this->getMauticCompany($dataObject, $object); |
||||
950 | $detachClass = Company::class; |
||||
951 | $mauticObjectReference = 'company'; |
||||
952 | } else { |
||||
953 | $this->logIntegrationError( |
||||
954 | new \Exception( |
||||
955 | sprintf('Received an unexpected object without an internalObjectReference "%s"', $object) |
||||
956 | ) |
||||
957 | ); |
||||
958 | |||||
959 | continue; |
||||
960 | } |
||||
961 | |||||
962 | if ($entity) { |
||||
963 | $integrationId = $integrationEntityRepo->getIntegrationsEntityId( |
||||
964 | 'Sugarcrm', |
||||
965 | $object, |
||||
966 | $mauticObjectReference, |
||||
967 | $entity->getId() |
||||
968 | ); |
||||
969 | |||||
970 | if (null == $integrationId) { |
||||
971 | $integrationEntity = new IntegrationEntity(); |
||||
972 | $integrationEntity->setDateAdded(new \DateTime()); |
||||
973 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
974 | $integrationEntity->setIntegration('Sugarcrm'); |
||||
975 | $integrationEntity->setIntegrationEntity($object); |
||||
976 | $integrationEntity->setIntegrationEntityId($record['id']); |
||||
977 | $integrationEntity->setInternalEntity($mauticObjectReference); |
||||
978 | $integrationEntity->setInternalEntityId($entity->getId()); |
||||
979 | $integrationEntities[] = $integrationEntity; |
||||
980 | } else { |
||||
981 | $integrationEntity = $integrationEntityRepo->getEntity($integrationId[0]['id']); |
||||
982 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
983 | $integrationEntities[] = $integrationEntity; |
||||
984 | } |
||||
985 | $this->em->detach($entity); |
||||
0 ignored issues
–
show
The function
Doctrine\ORM\EntityManager::detach() has been deprecated: 2.7 This method is being removed from the ORM and won't have any replacement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.
Loading history...
|
|||||
986 | $this->em->clear($detachClass); |
||||
987 | unset($entity); |
||||
988 | } else { |
||||
989 | continue; |
||||
990 | } |
||||
991 | ++$count; |
||||
992 | } |
||||
993 | |||||
994 | $this->em->getRepository('MauticPluginBundle:IntegrationEntity')->saveEntities($integrationEntities); |
||||
995 | $this->em->clear('Mautic\PluginBundle\Entity\IntegrationEntity'); |
||||
996 | } |
||||
997 | unset($data); |
||||
998 | unset($integrationEntities); |
||||
999 | unset($dataObject); |
||||
1000 | } |
||||
1001 | |||||
1002 | return $count; |
||||
1003 | } |
||||
1004 | |||||
1005 | /** |
||||
1006 | * @param \Mautic\PluginBundle\Integration\Form|FormBuilder $builder |
||||
1007 | * @param array $data |
||||
1008 | * @param string $formArea |
||||
1009 | */ |
||||
1010 | public function appendToForm(&$builder, $data, $formArea) |
||||
1011 | { |
||||
1012 | if ('keys' == $formArea) { |
||||
1013 | $builder->add('version', ButtonGroupType::class, [ |
||||
1014 | 'choices' => [ |
||||
1015 | '6.x/community' => '6', |
||||
1016 | '7.x' => '7', |
||||
1017 | ], |
||||
1018 | 'label' => 'mautic.sugarcrm.form.version', |
||||
1019 | 'constraints' => [ |
||||
1020 | new NotBlank([ |
||||
1021 | 'message' => 'mautic.core.value.required', |
||||
1022 | ]), |
||||
1023 | ], |
||||
1024 | 'required' => true, |
||||
1025 | ]); |
||||
1026 | } |
||||
1027 | if ('features' == $formArea) { |
||||
1028 | $builder->add( |
||||
1029 | 'updateOwner', |
||||
1030 | ChoiceType::class, |
||||
1031 | [ |
||||
1032 | 'choices' => [ |
||||
1033 | 'mautic.sugarcrm.updateOwner' => 'updateOwner', |
||||
1034 | ], |
||||
1035 | 'expanded' => true, |
||||
1036 | 'multiple' => true, |
||||
1037 | 'label' => 'mautic.sugarcrm.form.updateOwner', |
||||
1038 | 'label_attr' => ['class' => 'control-label'], |
||||
1039 | 'placeholder' => false, |
||||
1040 | 'required' => false, |
||||
1041 | 'attr' => [ |
||||
1042 | 'onclick' => 'Mautic.postForm(mQuery(\'form[name="integration_details"]\'),\'\');', |
||||
1043 | ], |
||||
1044 | ] |
||||
1045 | ); |
||||
1046 | |||||
1047 | $builder->add( |
||||
1048 | 'updateDnc', |
||||
1049 | ChoiceType::class, |
||||
1050 | [ |
||||
1051 | 'choices' => [ |
||||
1052 | 'mautic.sugarcrm.updateDnc' => 'updateDnc', |
||||
1053 | ], |
||||
1054 | 'expanded' => true, |
||||
1055 | 'multiple' => true, |
||||
1056 | 'label' => 'mautic.sugarcrm.form.updateDnc', |
||||
1057 | 'label_attr' => ['class' => 'control-label'], |
||||
1058 | 'placeholder' => false, |
||||
1059 | 'required' => false, |
||||
1060 | 'attr' => [ |
||||
1061 | 'onclick' => 'Mautic.postForm(mQuery(\'form[name="integration_details"]\'),\'\');', |
||||
1062 | ], |
||||
1063 | ] |
||||
1064 | ); |
||||
1065 | |||||
1066 | $builder->add( |
||||
1067 | 'updateBlanks', |
||||
1068 | ChoiceType::class, |
||||
1069 | [ |
||||
1070 | 'choices' => [ |
||||
1071 | 'mautic.integrations.blanks' => 'updateBlanks', |
||||
1072 | ], |
||||
1073 | 'expanded' => true, |
||||
1074 | 'multiple' => true, |
||||
1075 | 'label' => 'mautic.integrations.form.blanks', |
||||
1076 | 'label_attr' => ['class' => 'control-label'], |
||||
1077 | 'placeholder' => false, |
||||
1078 | 'required' => false, |
||||
1079 | ] |
||||
1080 | ); |
||||
1081 | |||||
1082 | $builder->add( |
||||
1083 | 'objects', |
||||
1084 | ChoiceType::class, |
||||
1085 | [ |
||||
1086 | 'choices' => [ |
||||
1087 | 'mautic.sugarcrm.object.lead' => 'Leads', |
||||
1088 | 'mautic.sugarcrm.object.contact' => 'Contacts', |
||||
1089 | 'mautic.sugarcrm.object.company' => 'company', |
||||
1090 | ], |
||||
1091 | 'expanded' => true, |
||||
1092 | 'multiple' => true, |
||||
1093 | 'label' => 'mautic.sugarcrm.form.objects_to_pull_from', |
||||
1094 | 'label_attr' => ['class' => ''], |
||||
1095 | 'placeholder' => false, |
||||
1096 | 'required' => false, |
||||
1097 | ] |
||||
1098 | ); |
||||
1099 | |||||
1100 | $builder->add( |
||||
1101 | 'activityEvents', |
||||
1102 | ChoiceType::class, |
||||
1103 | [ |
||||
1104 | 'choices' => array_flip($this->leadModel->getEngagementTypes()), // Choice type expects labels as keys |
||||
1105 | 'label' => 'mautic.salesforce.form.activity_included_events', |
||||
1106 | 'label_attr' => [ |
||||
1107 | 'class' => 'control-label', |
||||
1108 | 'data-toggle' => 'tooltip', |
||||
1109 | 'title' => $this->translator->trans('mautic.salesforce.form.activity.events.tooltip'), |
||||
1110 | ], |
||||
1111 | 'multiple' => true, |
||||
1112 | 'empty_data' => ['point.gained', 'form.submitted', 'email.read'], // BC with pre 2.11.0 |
||||
1113 | 'required' => false, |
||||
1114 | ] |
||||
1115 | ); |
||||
1116 | } |
||||
1117 | } |
||||
1118 | |||||
1119 | /** |
||||
1120 | * @param \Mautic\LeadBundle\Entity\Lead $lead |
||||
1121 | * @param array $config |
||||
1122 | * |
||||
1123 | * @return array|bool |
||||
1124 | */ |
||||
1125 | public function pushLead($lead, $config = []) |
||||
1126 | { |
||||
1127 | $config = $this->mergeConfigToFeatureSettings($config); |
||||
1128 | |||||
1129 | if (empty($config['leadFields'])) { |
||||
1130 | return []; |
||||
1131 | } |
||||
1132 | |||||
1133 | $object = 'Leads'; //Sugar objects, default is Leads |
||||
1134 | |||||
1135 | //Check if lead has alredy been synched |
||||
1136 | /** @var IntegrationEntityRepository $integrationEntityRepo */ |
||||
1137 | $integrationEntityRepo = $this->em->getRepository('MauticPluginBundle:IntegrationEntity'); |
||||
1138 | //Check if it is a sugar CRM alredy synched lead |
||||
1139 | $integrationId = $integrationEntityRepo->getIntegrationsEntityId('Sugarcrm', $object, 'lead', $lead->getId()); |
||||
1140 | if (empty($integrationId)) { |
||||
1141 | //Check if it is a sugar CRM alredy synched lead |
||||
1142 | $integrationId = $integrationEntityRepo->getIntegrationsEntityId('Sugarcrm', 'Contacts', 'lead', $lead->getId()); |
||||
1143 | if (!empty($integrationId)) { |
||||
1144 | $object = 'Contacts'; |
||||
1145 | } |
||||
1146 | } |
||||
1147 | if (!empty($integrationId)) { |
||||
1148 | $integrationEntity = $integrationEntityRepo->getEntity($integrationId[0]['id']); |
||||
1149 | $lastSyncDate = $integrationEntity->getLastSyncDate(); |
||||
1150 | $addedSyncDate = $integrationEntity->getDateAdded(); |
||||
1151 | if ($addedSyncDate > $lastSyncDate) { |
||||
1152 | $lastSyncDate = $addedSyncDate; |
||||
1153 | } |
||||
1154 | |||||
1155 | $leadDateModified = $lead->getDateModified(); |
||||
1156 | $leadDateAdded = $lead->getDateAdded(); |
||||
1157 | $leadLastDate = $leadDateModified; |
||||
1158 | if ($leadDateAdded > $leadDateModified) { |
||||
1159 | $leadLastDate = $leadDateAdded; |
||||
1160 | } |
||||
1161 | |||||
1162 | if ($lastSyncDate >= $leadLastDate) { |
||||
1163 | return false; |
||||
1164 | } //Do not push lead if it was already synched |
||||
1165 | } |
||||
1166 | |||||
1167 | $fieldsToUpdateInSugar = isset($config['update_mautic']) ? array_keys($config['update_mautic'], 0) : []; |
||||
1168 | $leadSugarFieldsToCreate = $this->cleanSugarData($config, array_keys($config['leadFields']), $object); |
||||
1169 | $fieldsToUpdateInLeadsSugar = $this->cleanSugarData($config, $fieldsToUpdateInSugar, $object); |
||||
1170 | $leadFields = array_intersect_key($leadSugarFieldsToCreate, $fieldsToUpdateInLeadsSugar); |
||||
1171 | |||||
1172 | $mappedData[$object] = $this->populateLeadData($lead, ['leadFields' => $leadFields, 'object' => $object]); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
1173 | |||||
1174 | $this->amendLeadDataBeforePush($mappedData[$object]); |
||||
1175 | |||||
1176 | if (empty($mappedData[$object])) { |
||||
1177 | return false; |
||||
1178 | } |
||||
1179 | |||||
1180 | if (!empty($integrationId)) { |
||||
1181 | $integrationEntity = $integrationEntityRepo->findOneBy( |
||||
1182 | [ |
||||
1183 | 'integration' => 'Sugarcrm', |
||||
1184 | 'integrationEntity' => $object, |
||||
1185 | 'internalEntity' => 'lead', |
||||
1186 | 'internalEntityId' => $lead->getId(), |
||||
1187 | ] |
||||
1188 | ); |
||||
1189 | |||||
1190 | $mappedData[$object]['id'] = $integrationEntity->getIntegrationEntityId(); |
||||
1191 | } |
||||
1192 | try { |
||||
1193 | if ($this->isAuthorized()) { |
||||
1194 | if (!is_null($lead->getOwner())) { |
||||
1195 | $sugarOwnerId = $this->getApiHelper()->getIdBySugarEmail(['emails' => [$lead->getOwner()->getEmail()]]); |
||||
1196 | if (!empty($sugarOwnerId)) { |
||||
1197 | $mappedData[$object]['assigned_user_id'] = array_values($sugarOwnerId)[0]; |
||||
1198 | } |
||||
1199 | } |
||||
1200 | $createdLeadData = $this->getApiHelper()->createLead($mappedData[$object], $lead); |
||||
0 ignored issues
–
show
The call to
MauticPlugin\MauticCrmBu...pi\CrmApi::createLead() has too many arguments starting with $mappedData[$object] .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||
1201 | if (isset($createdLeadData['id'])) { |
||||
1202 | if (empty($integrationId)) { |
||||
1203 | $integrationEntity = new IntegrationEntity(); |
||||
1204 | $integrationEntity->setDateAdded(new \DateTime()); |
||||
1205 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1206 | $integrationEntity->setIntegration('Sugarcrm'); |
||||
1207 | $integrationEntity->setIntegrationEntity($object); |
||||
1208 | $integrationEntity->setIntegrationEntityId($createdLeadData['id']); |
||||
1209 | $integrationEntity->setInternalEntity('lead'); |
||||
1210 | $integrationEntity->setInternalEntityId($lead->getId()); |
||||
1211 | } else { |
||||
1212 | $integrationEntity = $integrationEntityRepo->getEntity($integrationId[0]['id']); |
||||
1213 | } |
||||
1214 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1215 | $this->em->persist($integrationEntity); |
||||
1216 | $this->em->flush($integrationEntity); |
||||
1217 | } |
||||
1218 | |||||
1219 | return true; |
||||
1220 | } |
||||
1221 | } catch (\Exception $e) { |
||||
1222 | $this->logIntegrationError($e); |
||||
1223 | } |
||||
1224 | |||||
1225 | return false; |
||||
1226 | } |
||||
1227 | |||||
1228 | /** |
||||
1229 | * Return key recognized by integration. |
||||
1230 | * |
||||
1231 | * @param $key |
||||
1232 | * @param $field |
||||
1233 | * |
||||
1234 | * @return mixed |
||||
1235 | */ |
||||
1236 | public function convertLeadFieldKey($key, $field) |
||||
1237 | { |
||||
1238 | $search = []; |
||||
1239 | foreach ($this->objects as $object) { |
||||
1240 | $search[] = '__'.$object; |
||||
1241 | } |
||||
1242 | |||||
1243 | return str_replace($search, '', $key); |
||||
1244 | } |
||||
1245 | |||||
1246 | /** |
||||
1247 | * @param array $fields |
||||
1248 | * @param array $keys |
||||
1249 | * @param string $object |
||||
1250 | * |
||||
1251 | * @return array |
||||
1252 | */ |
||||
1253 | public function cleanSugarData($fields, $keys, $object) |
||||
1254 | { |
||||
1255 | $leadFields = []; |
||||
1256 | |||||
1257 | foreach ($keys as $key) { |
||||
1258 | if (strstr($key, '__'.$object)) { |
||||
1259 | $newKey = str_replace('__'.$object, '', $key); |
||||
1260 | //$leadFields[$object][$newKey] = $fields['leadFields'][$key]; |
||||
1261 | $leadFields[$newKey] = $fields['leadFields'][$key]; |
||||
1262 | } |
||||
1263 | } |
||||
1264 | |||||
1265 | return $leadFields; |
||||
1266 | } |
||||
1267 | |||||
1268 | /** |
||||
1269 | * @param array $params |
||||
1270 | * |
||||
1271 | * @return mixed |
||||
1272 | */ |
||||
1273 | public function pushLeads($params = []) |
||||
1274 | { |
||||
1275 | list($fromDate, $toDate) = $this->getSyncTimeframeDates($params); |
||||
1276 | $limit = $params['limit']; |
||||
1277 | $config = $this->mergeConfigToFeatureSettings(); |
||||
1278 | $integrationEntityRepo = $this->em->getRepository('MauticPluginBundle:IntegrationEntity'); |
||||
1279 | $mauticData = $leadsToUpdate = $fields = []; |
||||
1280 | $fieldsToUpdateInSugar = isset($config['update_mautic']) ? array_keys($config['update_mautic'], 0) : []; |
||||
1281 | $leadFields = $config['leadFields']; |
||||
1282 | if (!empty($leadFields)) { |
||||
1283 | if ($keys = array_keys($leadFields, 'mauticContactTimelineLink')) { |
||||
1284 | foreach ($keys as $key) { |
||||
1285 | unset($leadFields[$key]); |
||||
1286 | } |
||||
1287 | } |
||||
1288 | |||||
1289 | if ($keys = array_keys($leadFields, 'mauticContactIsContactableByEmail')) { |
||||
1290 | foreach ($keys as $key) { |
||||
1291 | unset($leadFields[$key]); |
||||
1292 | } |
||||
1293 | } |
||||
1294 | |||||
1295 | $fields = implode(', l.', $leadFields); |
||||
1296 | $fields = 'l.owner_id,l.'.$fields; |
||||
1297 | $result = 0; |
||||
1298 | |||||
1299 | //Leads fields |
||||
1300 | $leadSugarFieldsToCreate = $this->cleanSugarData($config, array_keys($config['leadFields']), 'Leads'); |
||||
1301 | $fieldsToUpdateInLeadsSugar = $this->cleanSugarData($config, $fieldsToUpdateInSugar, 'Leads'); |
||||
1302 | $leadSugarFields = array_intersect_key($leadSugarFieldsToCreate, $fieldsToUpdateInLeadsSugar); |
||||
1303 | |||||
1304 | //Contacts fields |
||||
1305 | $contactSugarFields = $this->cleanSugarData($config, array_keys($config['leadFields']), 'Contacts'); |
||||
1306 | $fieldsToUpdateInContactsSugar = $this->cleanSugarData($config, $fieldsToUpdateInSugar, 'Contacts'); |
||||
1307 | $contactSugarFields = array_intersect_key($contactSugarFields, $fieldsToUpdateInContactsSugar); |
||||
1308 | |||||
1309 | $availableFields = $this->getAvailableLeadFields(['feature_settings' => ['objects' => ['Leads', 'Contacts']]]); |
||||
1310 | |||||
1311 | //update lead/contact records |
||||
1312 | $leadsToUpdate = $integrationEntityRepo->findLeadsToUpdate($this->getName(), 'lead', $fields, $limit, $fromDate, $toDate, ['Contacts', 'Leads']); |
||||
1313 | } |
||||
1314 | $checkEmailsInSugar = []; |
||||
1315 | $deletedSugarLeads = []; |
||||
1316 | foreach ($leadsToUpdate as $object => $records) { |
||||
1317 | foreach ($records as $lead) { |
||||
1318 | if (isset($lead['email']) && !empty($lead['email'])) { |
||||
1319 | $lead = $this->getCompoundMauticFields($lead); |
||||
1320 | $checkEmailsInSugar[$object][mb_strtolower($lead['email'])] = $lead; |
||||
1321 | } |
||||
1322 | } |
||||
1323 | } |
||||
1324 | // Only get the max limit |
||||
1325 | if ($limit) { |
||||
1326 | $limit -= count($leadsToUpdate); |
||||
1327 | } |
||||
1328 | |||||
1329 | //create lead records |
||||
1330 | if (null === $limit || $limit && !empty($fields)) { |
||||
1331 | $leadsToCreate = $integrationEntityRepo->findLeadsToCreate('Sugarcrm', $fields, $limit, $fromDate, $toDate); |
||||
1332 | foreach ($leadsToCreate as $lead) { |
||||
1333 | if (isset($lead['email'])) { |
||||
1334 | $lead = $this->getCompoundMauticFields($lead); |
||||
1335 | $checkEmailsInSugar['Leads'][mb_strtolower($lead['email'])] = $lead; |
||||
1336 | } |
||||
1337 | } |
||||
1338 | } |
||||
1339 | |||||
1340 | foreach ($checkEmailsInSugar as $object => $checkObjectEmailsInSugar) { |
||||
1341 | list($checkEmailsUpdatedInSugar, $deletedRedords) = $this->getObjectDataToUpdate($checkObjectEmailsInSugar, $mauticData, $availableFields, $contactSugarFields, $leadSugarFields, $object); |
||||
1342 | //recheck synced records that might have been deleted in Sugar (deleted records don't come back in the query) |
||||
1343 | foreach ($checkEmailsUpdatedInSugar as $key => $deletedSugarRedords) { |
||||
1344 | if (isset($deletedSugarRedords['integration_entity_id']) && !empty($deletedSugarRedords['integration_entity_id'])) { |
||||
1345 | $deletedSugarLeads[$key] = $deletedSugarRedords['integration_entity_id']; |
||||
1346 | } |
||||
1347 | unset($checkEmailsUpdatedInSugar[$key]); |
||||
1348 | } |
||||
1349 | } |
||||
1350 | |||||
1351 | if (!empty($checkEmailsUpdatedInSugar)) { |
||||
1352 | $checkEmailsInSugar = array_merge($checkEmailsUpdatedInSugar, $checkEmailsInSugar); |
||||
1353 | } |
||||
1354 | // If there are any deleted, mark it as so to prevent them from being queried over and over or recreated |
||||
1355 | if ($deletedSugarLeads) { |
||||
1356 | $integrationEntityRepo->markAsDeleted($deletedSugarLeads, $this->getName(), 'lead'); |
||||
1357 | } |
||||
1358 | |||||
1359 | // Create any left over |
||||
1360 | if ($checkEmailsInSugar && isset($checkEmailsInSugar['Leads'])) { |
||||
1361 | list($checkEmailsInSugar, $deletedSugarLeads) = $this->getObjectDataToUpdate($checkEmailsInSugar['Leads'], $mauticData, $availableFields, $contactSugarFields, $leadSugarFields, 'Leads'); |
||||
1362 | $ownerAssignedUserIdByEmail = null; |
||||
1363 | foreach ($checkEmailsInSugar as $lead) { |
||||
1364 | if (isset($lead['email'])) { |
||||
1365 | $lead['owner_email'] = $this->getOwnerEmail($lead); |
||||
1366 | if ($lead['owner_email']) { |
||||
1367 | $ownerAssignedUserIdByEmail = $this->getApiHelper()->getIdBySugarEmail(['emails' => [$lead['owner_email']]]); |
||||
1368 | } |
||||
1369 | $this->buildCompositeBody( |
||||
1370 | $mauticData, |
||||
1371 | $availableFields, |
||||
1372 | $leadSugarFieldsToCreate, //use all matched fields when creating new records in Sugar |
||||
1373 | 'Leads', |
||||
1374 | $lead, |
||||
1375 | $ownerAssignedUserIdByEmail |
||||
1376 | ); |
||||
1377 | } |
||||
1378 | } |
||||
1379 | } |
||||
1380 | /** @var SugarcrmApi $apiHelper */ |
||||
1381 | $apiHelper = $this->getApiHelper(); |
||||
1382 | if (!empty($mauticData)) { |
||||
1383 | $result = $apiHelper->syncLeadsToSugar($mauticData); |
||||
1384 | } |
||||
1385 | |||||
1386 | return $this->processCompositeResponse($result); |
||||
1387 | } |
||||
1388 | |||||
1389 | /** |
||||
1390 | * Update body to sync. |
||||
1391 | */ |
||||
1392 | private function pushDncToSugar(array $lead, array &$body) |
||||
1393 | { |
||||
1394 | $features = $this->settings->getFeatureSettings(); |
||||
1395 | // update DNC sync disabled |
||||
1396 | if (empty($features['updateDnc'])) { |
||||
1397 | return; |
||||
1398 | } |
||||
1399 | $leadEntity = $this->leadModel->getEntity($lead['internal_entity_id']); |
||||
1400 | /** @var \Mautic\LeadBundle\Entity\DoNotContact[] $dncEntries */ |
||||
1401 | $dncEntries = $this->doNotContactModel->getDncRepo()->getEntriesByLeadAndChannel($leadEntity, 'email'); |
||||
1402 | $sugarDncKeys = array_combine(array_values($this->sugarDncKeys), $this->sugarDncKeys); |
||||
1403 | foreach ($dncEntries as $dncEntry) { |
||||
1404 | if (empty($sugarDncKeys)) { |
||||
1405 | continue; |
||||
1406 | } |
||||
1407 | // If DNC exists set to 1 |
||||
1408 | switch ($dncEntry->getReason()) { |
||||
1409 | case 1: |
||||
1410 | case 3: |
||||
1411 | $body[] = ['name' => 'email_opt_out', 'value' => 1]; |
||||
1412 | unset($sugarDncKeys['email_opt_out']); |
||||
1413 | break; |
||||
1414 | case 2: |
||||
1415 | $body[] = ['name' => 'invalid_email', 'value' => 1]; |
||||
1416 | unset($sugarDncKeys['invalid_email']); |
||||
1417 | break; |
||||
1418 | } |
||||
1419 | } |
||||
1420 | |||||
1421 | // uncheck |
||||
1422 | // If DNC doesn't exist set to 1 |
||||
1423 | if (!empty($sugarDncKeys)) { |
||||
1424 | foreach ($sugarDncKeys as $sugarDncKey) { |
||||
1425 | $body[] = ['name' => $sugarDncKey, 'value' => 0]; |
||||
1426 | } |
||||
1427 | } |
||||
1428 | } |
||||
1429 | |||||
1430 | private function fetchDncToMautic(Lead $lead = null, array $data) |
||||
1431 | { |
||||
1432 | if (is_null($lead)) { |
||||
1433 | return; |
||||
1434 | } |
||||
1435 | |||||
1436 | $features = $this->settings->getFeatureSettings(); |
||||
1437 | if (empty($features['updateDnc'])) { |
||||
1438 | return; |
||||
1439 | } |
||||
1440 | |||||
1441 | // try find opt_out value for lead |
||||
1442 | $isContactable = true; |
||||
1443 | foreach ($data['relationship_list'] as $relationshipList) { |
||||
1444 | foreach ($relationshipList['link_list'] as $links) { |
||||
1445 | if ('email_addresses' == $links['name']) { |
||||
1446 | foreach ($links['records'] as $records) { |
||||
1447 | if (!empty($records['link_value']['email_address']['value']) && $records['link_value']['email_address']['value'] == $lead->getEmail() && !empty($records['link_value']['opt_out']['value'])) { |
||||
1448 | $isContactable = false; |
||||
1449 | break 3; |
||||
1450 | } |
||||
1451 | } |
||||
1452 | } |
||||
1453 | } |
||||
1454 | } |
||||
1455 | |||||
1456 | $reason = \Mautic\LeadBundle\Entity\DoNotContact::UNSUBSCRIBED; |
||||
1457 | if (!$isContactable) { |
||||
1458 | $this->doNotContactModel->addDncForContact($lead->getId(), 'email', $reason, $this->getName()); |
||||
1459 | } else { |
||||
1460 | $this->doNotContactModel->removeDncForContact($lead->getId(), 'email', true, $reason); |
||||
1461 | } |
||||
1462 | } |
||||
1463 | |||||
1464 | /** |
||||
1465 | * @param $checkEmailsInSugar |
||||
1466 | * @param $mauticData |
||||
1467 | * @param $availableFields |
||||
1468 | * @param $contactSugarFields |
||||
1469 | * @param $leadSugarFields |
||||
1470 | * @param string $object |
||||
1471 | * |
||||
1472 | * @return array The first element is made up of records that exist in Mautic, but which no longer have a match in CRM. |
||||
1473 | * We therefore assume that they've been deleted in CRM and will mark them as deleted in the pushLeads function (~line 1320). |
||||
1474 | * The second element contains Ids of records that were explicitly marked as deleted in CRM. ATM, nothing is done with this data. |
||||
1475 | */ |
||||
1476 | public function getObjectDataToUpdate($checkEmailsInSugar, &$mauticData, $availableFields, $contactSugarFields, $leadSugarFields, $object = 'Leads') |
||||
1477 | { |
||||
1478 | $config = $this->mergeConfigToFeatureSettings([]); |
||||
1479 | $queryParam = ('Leads' == $object) ? 'checkemail' : 'checkemail_contacts'; |
||||
1480 | |||||
1481 | $sugarLead = $this->getApiHelper()->getLeads([$queryParam => array_keys($checkEmailsInSugar), 'offset' => 0, 'max_results' => 1000], $object); |
||||
1482 | $deletedSugarLeads = $sugarLeadRecords = []; |
||||
1483 | |||||
1484 | if (isset($sugarLead['entry_list'])) { |
||||
1485 | //Sugar 6.X |
||||
1486 | $sugarLeadRecords = []; |
||||
1487 | foreach ($sugarLead['entry_list'] as $k => $record) { |
||||
1488 | $sugarLeadRecord = []; |
||||
1489 | $sugarLeadRecord['id'] = $record['id']; |
||||
1490 | $sugarLeadRecord['module_name'] = $record['module_name']; |
||||
1491 | foreach ($record['name_value_list'] as $item) { |
||||
1492 | $sugarLeadRecord[$item['name']] = $item['value']; |
||||
1493 | } |
||||
1494 | if (!isset($sugarLeadRecord['email1'])) { |
||||
1495 | foreach ($sugarLead['relationship_list'][$k]['link_list'] as $links) { |
||||
1496 | if ('email_addresses' == $links['name']) { |
||||
1497 | foreach ($links['records'] as $records) { |
||||
1498 | foreach ($records as $contactEmails) { |
||||
1499 | foreach ($contactEmails as $anyAddress) { |
||||
1500 | if ('email_address' == $anyAddress['name'] && !empty($anyAddress['value'])) { |
||||
1501 | $sugarLeadRecord['email1'] = $anyAddress['value']; |
||||
1502 | break; |
||||
1503 | } |
||||
1504 | } |
||||
1505 | } |
||||
1506 | } |
||||
1507 | } |
||||
1508 | } |
||||
1509 | } |
||||
1510 | $sugarLeadRecords[] = $sugarLeadRecord; |
||||
1511 | } |
||||
1512 | } elseif (isset($sugarLead['records'])) { //Sugar 7 |
||||
1513 | $sugarLeadRecords = $sugarLead['records']; |
||||
1514 | } |
||||
1515 | |||||
1516 | foreach ($sugarLeadRecords as $sugarLeadRecord) { |
||||
1517 | if ((isset($sugarLeadRecord) && $sugarLeadRecord)) { |
||||
1518 | $email = $sugarLeadRecord['email1']; |
||||
1519 | $key = mb_strtolower($email); |
||||
1520 | $leadOwnerEmails = []; |
||||
1521 | if (!empty($checkEmailsInSugar)) { |
||||
1522 | foreach ($checkEmailsInSugar as $emailKey => $mauticRecord) { |
||||
1523 | if ($key == $emailKey) { |
||||
1524 | $isConverted = (isset($sugarLeadRecord['contact_id']) |
||||
1525 | && null != $sugarLeadRecord['contact_id'] |
||||
1526 | && '' != $sugarLeadRecord['contact_id']); |
||||
1527 | |||||
1528 | $sugarIdMapping[$checkEmailsInSugar[$key]['internal_entity_id']] = ($isConverted) ? $sugarLeadRecord['contact_id'] : $sugarLeadRecord['id']; |
||||
1529 | $lead['owner_email'] = $this->getOwnerEmail($mauticRecord); |
||||
1530 | if ($lead['owner_email']) { |
||||
1531 | $leadOwnerEmails[] = $lead['owner_email']; |
||||
1532 | } |
||||
1533 | $ownerAssignedUserIdByEmail = $this->getApiHelper()->getIdBySugarEmail(['emails' => array_unique($leadOwnerEmails)]); |
||||
1534 | if (empty($sugarLeadRecord['deleted']) || 0 == $sugarLeadRecord['deleted']) { |
||||
1535 | $sugarFieldMappings = $this->prepareFieldsForPush($availableFields); |
||||
1536 | |||||
1537 | if (isset($sugarFieldMappings['Contacts']) && !empty($sugarFieldMappings['Contacts'])) { |
||||
1538 | $contactSugarFields = $this->getBlankFieldsToUpdate($contactSugarFields, $sugarLeadRecord, $sugarFieldMappings['Contacts'], $config); |
||||
1539 | } |
||||
1540 | if (isset($sugarFieldMappings['Leads']) && !empty($sugarFieldMappings['Leads'])) { |
||||
1541 | $leadSugarFields = $this->getBlankFieldsToUpdate($leadSugarFields, $sugarLeadRecord, $sugarFieldMappings['Leads'], $config); |
||||
1542 | } |
||||
1543 | $this->buildCompositeBody( |
||||
1544 | $mauticData, |
||||
1545 | $availableFields, |
||||
1546 | $isConverted || ('Contacts' == $object) ? $contactSugarFields : $leadSugarFields, |
||||
1547 | $isConverted || ('Contacts' == $object) ? 'Contacts' : 'Leads', |
||||
1548 | $checkEmailsInSugar[$key], |
||||
1549 | $ownerAssignedUserIdByEmail, |
||||
1550 | $isConverted ? $sugarLeadRecord['contact_id'] : $sugarLeadRecord['id'] |
||||
1551 | ); |
||||
1552 | } else { |
||||
1553 | // @todo - Should return also deleted contacts from Sugar |
||||
1554 | $deletedSugarLeads[] = $sugarLeadRecord['id']; |
||||
1555 | if (!empty($sugarLeadRecord['contact_id']) || '' != $sugarLeadRecord['contact_id']) { |
||||
1556 | $deletedSugarLeads[] = $sugarLeadRecord['contact_id']; |
||||
1557 | } |
||||
1558 | } |
||||
1559 | unset($checkEmailsInSugar[$key]); |
||||
1560 | } |
||||
1561 | } |
||||
1562 | } |
||||
1563 | } |
||||
1564 | } |
||||
1565 | |||||
1566 | return [$checkEmailsInSugar, $deletedSugarLeads]; |
||||
1567 | } |
||||
1568 | |||||
1569 | /** |
||||
1570 | * @param $lead |
||||
1571 | * |
||||
1572 | * @return array |
||||
1573 | */ |
||||
1574 | public function getSugarLeadId($lead) |
||||
1575 | { |
||||
1576 | /** @var IntegrationEntityRepository $integrationEntityRepo */ |
||||
1577 | $integrationEntityRepo = $this->em->getRepository('MauticPluginBundle:IntegrationEntity'); |
||||
1578 | //try searching for lead as this has been changed before in updated done to the plugin |
||||
1579 | $result = $integrationEntityRepo->getIntegrationsEntityId('Sugarcrm', null, 'lead', $lead->getId()); |
||||
1580 | |||||
1581 | return $result; |
||||
1582 | } |
||||
1583 | |||||
1584 | /** |
||||
1585 | * @param array $lead |
||||
1586 | */ |
||||
1587 | protected function getOwnerEmail($lead) |
||||
1588 | { |
||||
1589 | if (isset($lead['owner_id']) && !empty($lead['owner_id'])) { |
||||
1590 | /** @var \Mautic\UserBundle\Entity\User $user */ |
||||
1591 | $user = $this->userModel->getEntity($lead['owner_id']); |
||||
1592 | |||||
1593 | return $user->getEmail(); |
||||
1594 | } |
||||
1595 | |||||
1596 | return null; |
||||
1597 | } |
||||
1598 | |||||
1599 | /** |
||||
1600 | * @param $mauticData |
||||
1601 | * @param $availableFields |
||||
1602 | * @param $object |
||||
1603 | * @param $lead |
||||
1604 | * @param null $objectId |
||||
1605 | */ |
||||
1606 | protected function buildCompositeBody(&$mauticData, $availableFields, $fieldsToUpdateInSugarUpdate, $object, $lead, $onwerAssignedUserIdByEmail = null, $objectId = null) |
||||
1607 | { |
||||
1608 | $body = []; |
||||
1609 | if (isset($lead['email']) && !empty($lead['email'])) { |
||||
1610 | //update and create (one query) every 200 records |
||||
1611 | |||||
1612 | foreach ($fieldsToUpdateInSugarUpdate as $sugarField => $mauticField) { |
||||
1613 | $required = !empty($availableFields[$object][$sugarField.'__'.$object]['required']); |
||||
1614 | if (isset($lead[$mauticField])) { |
||||
1615 | if (false !== strpos($lead[$mauticField], '|')) { |
||||
1616 | // Transform Mautic Multi Select into SugarCRM/SuiteCRM Multi Select format |
||||
1617 | $value = $this->convertMauticToSuiteCrmMultiSelect($lead[$mauticField]); |
||||
1618 | } else { |
||||
1619 | $value = $lead[$mauticField]; |
||||
1620 | } |
||||
1621 | $body[] = ['name' => $sugarField, 'value' => $value]; |
||||
1622 | } elseif ($required) { |
||||
1623 | $value = $this->translator->trans('mautic.integration.form.lead.unknown'); |
||||
1624 | $body[] = ['name' => $sugarField, 'value' => $value]; |
||||
1625 | } |
||||
1626 | } |
||||
1627 | |||||
1628 | if (!empty($body)) { |
||||
1629 | $id = $lead['internal_entity_id'].'-'.$object.(!empty($lead['id']) ? '-'.$lead['id'] : ''); |
||||
1630 | |||||
1631 | $body[] = ['name' => 'reference_id', 'value' => $id]; |
||||
1632 | |||||
1633 | if ($objectId) { |
||||
0 ignored issues
–
show
|
|||||
1634 | $body[] = ['name' => 'id', 'value' => $objectId]; |
||||
1635 | } |
||||
1636 | if (isset($onwerAssignedUserIdByEmail) && isset($lead['owner_email']) && isset($onwerAssignedUserIdByEmail[$lead['owner_email']])) { |
||||
1637 | $body[] = ['name' => 'assigned_user_id', 'value' => $onwerAssignedUserIdByEmail[$lead['owner_email']]]; |
||||
1638 | } |
||||
1639 | |||||
1640 | // pushd DNC to Sugar CRM |
||||
1641 | $this->pushDncToSugar($lead, $body); |
||||
1642 | |||||
1643 | $mauticData[$object][] = $body; |
||||
1644 | } |
||||
1645 | } |
||||
1646 | } |
||||
1647 | |||||
1648 | /** |
||||
1649 | * @param array $response |
||||
1650 | * |
||||
1651 | * @return array |
||||
1652 | */ |
||||
1653 | protected function processCompositeResponse($response) |
||||
1654 | { |
||||
1655 | $created = 0; |
||||
1656 | $errored = 0; |
||||
1657 | $updated = 0; |
||||
1658 | $object = 'Lead'; |
||||
1659 | $persistEntities = []; |
||||
1660 | if (is_array($response)) { |
||||
0 ignored issues
–
show
|
|||||
1661 | foreach ($response as $item) { |
||||
1662 | $contactId = $integrationEntityId = null; |
||||
1663 | if (!empty($item['reference_id'])) { |
||||
1664 | $reference = explode('-', $item['reference_id']); |
||||
1665 | if (3 === count($reference)) { |
||||
1666 | list($contactId, $object, $integrationEntityId) = $reference; |
||||
1667 | } else { |
||||
1668 | list($contactId, $object) = $reference; |
||||
1669 | } |
||||
1670 | } |
||||
1671 | |||||
1672 | if (isset($item['ko']) && $item['ko']) { |
||||
1673 | $this->logIntegrationError(new \Exception($item['error'])); |
||||
1674 | |||||
1675 | if ($integrationEntityId) { |
||||
1676 | $integrationEntity = $this->em->getReference('MauticPluginBundle:IntegrationEntity', $integrationEntityId); |
||||
1677 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1678 | |||||
1679 | $persistEntities[] = $integrationEntity; |
||||
1680 | } elseif ($contactId) { |
||||
1681 | $integrationEntity = new IntegrationEntity(); |
||||
1682 | $integrationEntity->setDateAdded(new \DateTime()); |
||||
1683 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1684 | $integrationEntity->setIntegration($this->getName()); |
||||
1685 | $integrationEntity->setIntegrationEntity($object); |
||||
1686 | $integrationEntity->setInternalEntity('lead-error'); |
||||
1687 | $integrationEntity->setInternal(['error' => $item['error']]); |
||||
1688 | $integrationEntity->setInternalEntityId($contactId); |
||||
1689 | |||||
1690 | $persistEntities[] = $integrationEntity; |
||||
1691 | ++$errored; |
||||
1692 | } |
||||
1693 | } elseif (!$item['ko']) { |
||||
1694 | if ($item['new']) { |
||||
1695 | // New object created |
||||
1696 | $integrationEntity = new IntegrationEntity(); |
||||
1697 | $integrationEntity->setDateAdded(new \DateTime()); |
||||
1698 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1699 | $integrationEntity->setIntegration($this->getName()); |
||||
1700 | $integrationEntity->setIntegrationEntity($object); |
||||
1701 | $integrationEntity->setIntegrationEntityId($item['id']); |
||||
1702 | $integrationEntity->setInternalEntity('lead'); |
||||
1703 | $integrationEntity->setInternalEntityId($contactId); |
||||
1704 | |||||
1705 | $persistEntities[] = $integrationEntity; |
||||
1706 | ++$created; |
||||
1707 | } else { |
||||
1708 | // Record was updated |
||||
1709 | if ($integrationEntityId) { |
||||
1710 | $integrationEntity = $this->em->getReference('MauticPluginBundle:IntegrationEntity', $integrationEntityId); |
||||
1711 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1712 | } else { |
||||
1713 | // Found in Sugarcrm so create a new record for it |
||||
1714 | $integrationEntity = new IntegrationEntity(); |
||||
1715 | $integrationEntity->setDateAdded(new \DateTime()); |
||||
1716 | $integrationEntity->setLastSyncDate(new \DateTime()); |
||||
1717 | $integrationEntity->setIntegration($this->getName()); |
||||
1718 | $integrationEntity->setIntegrationEntity($object); |
||||
1719 | $integrationEntity->setIntegrationEntityId($item['id']); |
||||
1720 | $integrationEntity->setInternalEntity('lead'); |
||||
1721 | $integrationEntity->setInternalEntityId($contactId); |
||||
1722 | } |
||||
1723 | |||||
1724 | $persistEntities[] = $integrationEntity; |
||||
1725 | ++$updated; |
||||
1726 | } |
||||
1727 | } else { |
||||
1728 | $error = 'Unknown status code '.$item['httpStatusCode']; |
||||
1729 | $this->logIntegrationError(new \Exception($error.' ('.$item['reference_id'].')')); |
||||
1730 | } |
||||
1731 | } |
||||
1732 | |||||
1733 | if ($persistEntities) { |
||||
1734 | $this->em->getRepository('MauticPluginBundle:IntegrationEntity')->saveEntities($persistEntities); |
||||
1735 | unset($persistEntities); |
||||
1736 | $this->em->clear(IntegrationEntity::class); |
||||
1737 | } |
||||
1738 | } |
||||
1739 | |||||
1740 | return [$updated, $created, $errored]; |
||||
1741 | } |
||||
1742 | |||||
1743 | /** |
||||
1744 | * @param $fieldsToUpdate |
||||
1745 | * @param array $objects |
||||
1746 | * |
||||
1747 | * @return array |
||||
1748 | */ |
||||
1749 | protected function cleanPriorityFields($fieldsToUpdate, $objects = null) |
||||
1750 | { |
||||
1751 | if (null === $objects) { |
||||
1752 | $objects = ['Leads', 'Contacts']; |
||||
1753 | } |
||||
1754 | |||||
1755 | if (isset($fieldsToUpdate['leadFields'])) { |
||||
1756 | // Pass in the whole config |
||||
1757 | $fields = $fieldsToUpdate; |
||||
1758 | } else { |
||||
1759 | $fields = array_flip($fieldsToUpdate); |
||||
1760 | } |
||||
1761 | |||||
1762 | return $this->prepareFieldsForSync($fields, $fieldsToUpdate, $objects); |
||||
1763 | } |
||||
1764 | |||||
1765 | /** |
||||
1766 | * @param array $fields |
||||
1767 | * @param array $keys |
||||
1768 | * @param mixed $object |
||||
1769 | * |
||||
1770 | * @return array |
||||
1771 | */ |
||||
1772 | public function prepareFieldsForSync($fields, $keys, $object = null) |
||||
1773 | { |
||||
1774 | $leadFields = []; |
||||
1775 | if (null === $object) { |
||||
1776 | $object = 'Lead'; |
||||
1777 | } |
||||
1778 | |||||
1779 | $objects = (!is_array($object)) ? [$object] : $object; |
||||
1780 | if (is_string($object) && 'Accounts' === $object) { |
||||
1781 | return isset($fields['companyFields']) ? $fields['companyFields'] : $fields; |
||||
1782 | } |
||||
1783 | |||||
1784 | if (isset($fields['leadFields'])) { |
||||
1785 | $fields = $fields['leadFields']; |
||||
1786 | $keys = array_keys($fields); |
||||
1787 | } |
||||
1788 | |||||
1789 | foreach ($objects as $obj) { |
||||
1790 | if (!isset($leadFields[$obj])) { |
||||
1791 | $leadFields[$obj] = []; |
||||
1792 | } |
||||
1793 | |||||
1794 | foreach ($keys as $key) { |
||||
1795 | if (strpos($key, '__'.$obj)) { |
||||
1796 | $newKey = str_replace('__'.$obj, '', $key); |
||||
1797 | if ('Id' === $newKey) { |
||||
1798 | // Don't map Id for push |
||||
1799 | continue; |
||||
1800 | } |
||||
1801 | |||||
1802 | $leadFields[$obj][$newKey] = $fields[$key]; |
||||
1803 | } |
||||
1804 | } |
||||
1805 | } |
||||
1806 | |||||
1807 | return (is_array($object)) ? $leadFields : $leadFields[$object]; |
||||
1808 | } |
||||
1809 | |||||
1810 | /** |
||||
1811 | * @param $config |
||||
1812 | * @param null $object |
||||
1813 | * @param string $priorityObject |
||||
1814 | * |
||||
1815 | * @return mixed |
||||
1816 | */ |
||||
1817 | protected function getPriorityFieldsForMautic($config, $object = null, $priorityObject = 'mautic') |
||||
1818 | { |
||||
1819 | $fields = parent::getPriorityFieldsForMautic($config, $object, $priorityObject); |
||||
1820 | |||||
1821 | return ($object && isset($fields[$object])) ? $fields[$object] : $fields; |
||||
1822 | } |
||||
1823 | |||||
1824 | /** |
||||
1825 | * @param $fields |
||||
1826 | * |
||||
1827 | * @return array |
||||
1828 | */ |
||||
1829 | protected function prepareFieldsForPush($fields) |
||||
1830 | { |
||||
1831 | $fieldMappings = []; |
||||
1832 | $required = []; |
||||
1833 | $config = $this->mergeConfigToFeatureSettings(); |
||||
1834 | |||||
1835 | $contactFields = $this->cleanSugarData($config, array_keys($config['leadFields']), 'Contacts'); |
||||
1836 | $leadFields = $this->cleanSugarData($config, array_keys($config['leadFields']), 'Leads'); |
||||
1837 | if (!empty($contactFields)) { |
||||
1838 | foreach ($fields['Contacts'] as $key => $field) { |
||||
1839 | if ($field['required']) { |
||||
1840 | $required[$key] = $field; |
||||
1841 | } |
||||
1842 | } |
||||
1843 | $fieldMappings['Contacts']['required'] = [ |
||||
1844 | 'fields' => $required, |
||||
1845 | ]; |
||||
1846 | $fieldMappings['Contacts']['create'] = $contactFields; |
||||
1847 | } |
||||
1848 | if (!empty($leadFields)) { |
||||
1849 | foreach ($fields['Leads'] as $key => $field) { |
||||
1850 | if ($field['required']) { |
||||
1851 | $required[$key] = $field; |
||||
1852 | } |
||||
1853 | } |
||||
1854 | $fieldMappings['Leads']['required'] = [ |
||||
1855 | 'fields' => $required, |
||||
1856 | ]; |
||||
1857 | $fieldMappings['Leads']['create'] = $leadFields; |
||||
1858 | } |
||||
1859 | |||||
1860 | return $fieldMappings; |
||||
1861 | } |
||||
1862 | |||||
1863 | /** |
||||
1864 | * Converts Mautic Multi-Select String into the format used to store Multi-Select values used by SuiteCRM / SugarCRM 6.x. |
||||
1865 | * |
||||
1866 | * @param string |
||||
1867 | * |
||||
1868 | * @return string |
||||
1869 | */ |
||||
1870 | public function convertMauticToSuiteCrmMultiSelect($mauticMultiSelectStringToConvert) |
||||
1871 | { |
||||
1872 | //$mauticMultiSelectStringToConvert = 'test|enhancedapi|dataservices'; |
||||
1873 | $multiSelectArrayValues = explode('|', $mauticMultiSelectStringToConvert); |
||||
1874 | $convertedSugarCrmMultiSelectString = ''; |
||||
1875 | foreach ($multiSelectArrayValues as $item) { |
||||
1876 | $convertedSugarCrmMultiSelectString = $convertedSugarCrmMultiSelectString.'^'.$item.'^'.','; |
||||
1877 | } |
||||
1878 | |||||
1879 | return substr($convertedSugarCrmMultiSelectString, 0, -1); |
||||
1880 | } |
||||
1881 | |||||
1882 | /** |
||||
1883 | * Checks if a string contains SuiteCRM / SugarCRM 6.x Multi-Select values. |
||||
1884 | * |
||||
1885 | * @param string |
||||
1886 | * |
||||
1887 | * @return bool |
||||
1888 | */ |
||||
1889 | public function checkIfSugarCrmMultiSelectString($stringToCheck) |
||||
1890 | { |
||||
1891 | // Regular Express to check SugarCRM/SuiteCRM Multi-Select format below |
||||
1892 | // example format: '^choice1^,^choice2^,^choice_3^' |
||||
1893 | $regex = '/(\^)(?:([A-Za-z0-9\-\_]+))(\^)/'; |
||||
1894 | if (preg_match($regex, $stringToCheck)) { |
||||
1895 | return true; |
||||
1896 | } else { |
||||
1897 | return false; |
||||
1898 | } |
||||
1899 | } |
||||
1900 | |||||
1901 | /** |
||||
1902 | * Converts a SuiteCRM / SugarCRM 6.x Multi-Select String into the format used to store Multi-Select values used by Mautic. |
||||
1903 | * |
||||
1904 | * @param string |
||||
1905 | * |
||||
1906 | * @return string |
||||
1907 | */ |
||||
1908 | public function convertSuiteCrmToMauticMultiSelect($suiteCrmMultiSelectStringToConvert) |
||||
1909 | { |
||||
1910 | // Mautic Multi Select format - 'choice1|choice2|choice_3' |
||||
1911 | $regexString = '/(\^)(?:([A-Za-z0-9\-\_]+))(\^)/'; |
||||
1912 | preg_match_all($regexString, $suiteCrmMultiSelectStringToConvert, $matches, PREG_SET_ORDER, 0); |
||||
1913 | $convertedString = ''; |
||||
1914 | foreach ($matches as $innerArray) { |
||||
1915 | $convertedString = $convertedString.$innerArray[2].'|'; |
||||
1916 | } |
||||
1917 | |||||
1918 | return substr($convertedString, 0, -1); |
||||
1919 | } |
||||
1920 | } |
||||
1921 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.