Issues (3627)

app/bundles/LeadBundle/Model/CompanyModel.php (3 issues)

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 Mautic\LeadBundle\Model;
13
14
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
15
use Mautic\CoreBundle\Form\RequestTrait;
16
use Mautic\CoreBundle\Helper\DateTimeHelper;
17
use Mautic\CoreBundle\Helper\InputHelper;
18
use Mautic\CoreBundle\Model\AjaxLookupModelInterface;
19
use Mautic\CoreBundle\Model\FormModel as CommonFormModel;
20
use Mautic\EmailBundle\Helper\EmailValidator;
21
use Mautic\LeadBundle\Entity\Company;
22
use Mautic\LeadBundle\Entity\CompanyLead;
23
use Mautic\LeadBundle\Entity\Lead;
24
use Mautic\LeadBundle\Entity\LeadEventLog;
25
use Mautic\LeadBundle\Entity\LeadField;
26
use Mautic\LeadBundle\Event\CompanyEvent;
27
use Mautic\LeadBundle\Event\LeadChangeCompanyEvent;
28
use Mautic\LeadBundle\Form\Type\CompanyType;
29
use Mautic\LeadBundle\LeadEvents;
30
use Symfony\Component\EventDispatcher\Event;
31
use Symfony\Component\HttpFoundation\Session\Session;
32
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
33
34
/**
35
 * Class CompanyModel.
36
 */
37
class CompanyModel extends CommonFormModel implements AjaxLookupModelInterface
38
{
39
    use DefaultValueTrait;
40
    use RequestTrait;
41
42
    /**
43
     * @var Session
44
     */
45
    protected $session;
46
47
    /**
48
     * @var FieldModel
49
     */
50
    protected $leadFieldModel;
51
52
    /**
53
     * @var array
54
     */
55
    protected $companyFields;
56
57
    /**
58
     * @var EmailValidator
59
     */
60
    protected $emailValidator;
61
62
    /**
63
     * @var array
64
     */
65
    private $fields = [];
66
67
    /**
68
     * CompanyModel constructor.
69
     */
70
    public function __construct(FieldModel $leadFieldModel, Session $session, EmailValidator $validator)
71
    {
72
        $this->leadFieldModel = $leadFieldModel;
73
        $this->session        = $session;
74
        $this->emailValidator = $validator;
75
    }
76
77
    /**
78
     * @param Company $entity
79
     * @param bool    $unlock
80
     */
81
    public function saveEntity($entity, $unlock = true)
82
    {
83
        // Update leads primary company name
84
        $this->setEntityDefaultValues($entity, 'company');
85
        $this->getCompanyLeadRepository()->updateLeadsPrimaryCompanyName($entity);
86
87
        parent::saveEntity($entity, $unlock);
88
    }
89
90
    /**
91
     * Save an array of entities.
92
     *
93
     * @param array $entities
94
     * @param bool  $unlock
95
     *
96
     * @return array
97
     */
98
    public function saveEntities($entities, $unlock = true)
99
    {
100
        // Update leads primary company name
101
        foreach ($entities as $entity) {
102
            $this->setEntityDefaultValues($entity, 'company');
103
            $this->getCompanyLeadRepository()->updateLeadsPrimaryCompanyName($entity);
104
        }
105
        parent::saveEntities($entities, $unlock);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     *
111
     * @return \Mautic\LeadBundle\Entity\CompanyRepository
112
     */
113
    public function getRepository()
114
    {
115
        return $this->em->getRepository('MauticLeadBundle:Company');
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     *
121
     * @return \Mautic\LeadBundle\Entity\CompanyLeadRepository
122
     */
123
    public function getCompanyLeadRepository()
124
    {
125
        return $this->em->getRepository('MauticLeadBundle:CompanyLead');
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function getPermissionBase()
132
    {
133
        // We are using lead:leads in the CompanyController so this should match to prevent a BC break
134
        return 'lead:leads';
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     *
140
     * @return string
141
     */
142
    public function getNameGetter()
143
    {
144
        return 'getPrimaryIdentifier';
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     *
150
     * @throws MethodNotAllowedHttpException
151
     */
152
    public function createForm($entity, $formFactory, $action = null, $options = [])
153
    {
154
        if (!$entity instanceof Company) {
155
            throw new MethodNotAllowedHttpException(['Company']);
156
        }
157
        if (!empty($action)) {
158
            $options['action'] = $action;
159
        }
160
161
        return $formFactory->create(CompanyType::class, $entity, $options);
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     *
167
     * @return Company|null
168
     */
169
    public function getEntity($id = null)
170
    {
171
        if (null === $id) {
172
            return new Company();
173
        }
174
175
        return parent::getEntity($id);
176
    }
177
178
    /**
179
     * @return mixed
180
     */
181
    public function getUserCompanies()
182
    {
183
        $user = (!$this->security->isGranted('lead:leads:viewother')) ?
184
            $this->userHelper->getUser() : false;
185
186
        return $this->em->getRepository('MauticLeadBundle:Company')->getCompanies($user);
187
    }
188
189
    /**
190
     * Reorganizes a field list to be keyed by field's group then alias.
191
     *
192
     * @param $fields
193
     *
194
     * @return array
195
     */
196
    public function organizeFieldsByGroup($fields)
197
    {
198
        $array = [];
199
200
        foreach ($fields as $field) {
201
            if ($field instanceof LeadField) {
202
                $alias = $field->getAlias();
203
                if ('company' === $field->getObject()) {
204
                    $group                          = $field->getGroup();
205
                    $array[$group][$alias]['id']    = $field->getId();
206
                    $array[$group][$alias]['group'] = $group;
207
                    $array[$group][$alias]['label'] = $field->getLabel();
208
                    $array[$group][$alias]['alias'] = $alias;
209
                    $array[$group][$alias]['type']  = $field->getType();
210
                }
211
            } else {
212
                $alias   = $field['alias'];
213
                $field[] = $alias;
214
                if ('company' === $field['object']) {
215
                    $group                          = $field['group'];
216
                    $array[$group][$alias]['id']    = $field['id'];
217
                    $array[$group][$alias]['group'] = $group;
218
                    $array[$group][$alias]['label'] = $field['label'];
219
                    $array[$group][$alias]['alias'] = $alias;
220
                    $array[$group][$alias]['type']  = $field['type'];
221
                }
222
            }
223
        }
224
225
        //make sure each group key is present
226
        $groups = ['core', 'social', 'personal', 'professional'];
227
        foreach ($groups as $g) {
228
            if (!isset($array[$g])) {
229
                $array[$g] = [];
230
            }
231
        }
232
233
        return $array;
234
    }
235
236
    /**
237
     * Populates custom field values for updating the company.
238
     *
239
     * @param bool|false $overwriteWithBlank
240
     */
241
    public function setFieldValues(Company $company, array $data, $overwriteWithBlank = false)
242
    {
243
        //save the field values
244
        $fieldValues = $company->getFields();
245
246
        if (empty($fieldValues)) {
247
            // Lead is new or they haven't been populated so let's build the fields now
248
            if (empty($this->fields)) {
249
                $this->fields = $this->leadFieldModel->getEntities(
250
                    [
251
                        'filter'         => ['object' => 'company'],
252
                        'hydration_mode' => 'HYDRATE_ARRAY',
253
                    ]
254
                );
255
                $this->fields = $this->organizeFieldsByGroup($this->fields);
256
            }
257
            $fieldValues = $this->fields;
258
        }
259
260
        //update existing values
261
        foreach ($fieldValues as &$groupFields) {
262
            foreach ($groupFields as $alias => &$field) {
263
                if (!isset($field['value'])) {
264
                    $field['value'] = null;
265
                }
266
                // Only update fields that are part of the passed $data array
267
                if (array_key_exists($alias, $data)) {
268
                    $curValue = $field['value'];
269
                    $newValue = $data[$alias];
270
271
                    if (is_array($newValue)) {
272
                        $newValue = implode('|', $newValue);
273
                    }
274
275
                    if ($curValue !== $newValue && (strlen($newValue) > 0 || (0 === strlen($newValue) && $overwriteWithBlank))) {
276
                        $field['value'] = $newValue;
277
                        $company->addUpdatedField($alias, $newValue, $curValue);
278
                    }
279
                }
280
            }
281
        }
282
        $company->setFields($fieldValues);
283
    }
284
285
    /**
286
     * Add lead to company.
287
     *
288
     * @param array|Company $companies
289
     * @param array|Lead    $lead
290
     *
291
     * @return bool
292
     *
293
     * @throws \Doctrine\ORM\ORMException
294
     */
295
    public function addLeadToCompany($companies, $lead)
296
    {
297
        // Primary company name to be persisted to the lead's contact company field
298
        $companyName        = '';
299
        $companyLeadAdd     = [];
300
        $searchForCompanies = [];
301
302
        $dateManipulated = new \DateTime();
303
304
        if (!$lead instanceof Lead) {
305
            $leadId = (is_array($lead) && isset($lead['id'])) ? $lead['id'] : $lead;
306
            $lead   = $this->em->getReference('MauticLeadBundle:Lead', $leadId);
307
        }
308
309
        if ($companies instanceof Company) {
310
            $companyLeadAdd[$companies->getId()] = $companies;
311
            $companies                           = [$companies->getId()];
312
        } elseif (!is_array($companies)) {
313
            $companies = [$companies];
314
        }
315
316
        //make sure they are ints
317
        foreach ($companies as &$l) {
318
            $l = (int) $l;
319
320
            if (!isset($companyLeadAdd[$l])) {
321
                $searchForCompanies[] = $l;
322
            }
323
        }
324
325
        if (!empty($searchForCompanies)) {
326
            $companyEntities = $this->getEntities([
327
                'filter' => [
328
                    'force' => [
329
                        [
330
                            'column' => 'comp.id',
331
                            'expr'   => 'in',
332
                            'value'  => $searchForCompanies,
333
                        ],
334
                    ],
335
                ],
336
            ]);
337
338
            foreach ($companyEntities as $company) {
339
                $companyLeadAdd[$company->getId()] = $company;
340
            }
341
        }
342
343
        unset($companyEntities, $searchForCompanies);
344
345
        $persistCompany = [];
346
        $dispatchEvents = [];
347
        $contactAdded   = false;
348
        foreach ($companies as $companyId) {
349
            if (!isset($companyLeadAdd[$companyId])) {
350
                // List no longer exists in the DB so continue to the next
351
                continue;
352
            }
353
354
            $companyLead = $this->getCompanyLeadRepository()->findOneBy(
355
                [
356
                    'lead'    => $lead,
357
                    'company' => $companyLeadAdd[$companyId],
358
                ]
359
            );
360
361
            if (null != $companyLead) {
362
                // Detach from Doctrine
363
                $this->em->detach($companyLead);
364
365
                continue;
366
            } else {
367
                $companyLead = new CompanyLead();
368
                $companyLead->setCompany($companyLeadAdd[$companyId]);
369
                $companyLead->setLead($lead);
370
                $companyLead->setDateAdded($dateManipulated);
371
                $contactAdded     = true;
372
                $persistCompany[] = $companyLead;
373
                $dispatchEvents[] = $companyId;
374
                $companyName      = $companyLeadAdd[$companyId]->getName();
375
            }
376
        }
377
378
        if (!empty($persistCompany)) {
379
            $this->getCompanyLeadRepository()->saveEntities($persistCompany);
380
        }
381
382
        if (!empty($companyName)) {
383
            $currentCompanyName = $lead->getCompany();
384
            if ($currentCompanyName !== $companyName) {
385
                $lead->addUpdatedField('company', $companyName)
386
                    ->setDateModified(new \DateTime());
387
                $this->em->getRepository('MauticLeadBundle:Lead')->saveEntity($lead);
388
            }
389
        }
390
391
        if (!empty($dispatchEvents) && ($this->dispatcher->hasListeners(LeadEvents::LEAD_COMPANY_CHANGE))) {
392
            foreach ($dispatchEvents as $companyId) {
393
                $event = new LeadChangeCompanyEvent($lead, $companyLeadAdd[$companyId]);
394
                $this->dispatcher->dispatch(LeadEvents::LEAD_COMPANY_CHANGE, $event);
395
396
                unset($event);
397
            }
398
        }
399
400
        // Clear CompanyLead entities from Doctrine memory
401
        $this->em->clear(CompanyLead::class);
402
403
        return $contactAdded;
404
    }
405
406
    /**
407
     * Remove a lead from company.
408
     *
409
     * @param $companies
410
     * @param $lead
411
     *
412
     * @throws \Doctrine\ORM\ORMException
413
     */
414
    public function removeLeadFromCompany($companies, $lead)
415
    {
416
        if (!$lead instanceof Lead) {
417
            $leadId = (is_array($lead) && isset($lead['id'])) ? $lead['id'] : $lead;
418
            $lead   = $this->em->getReference('MauticLeadBundle:Lead', $leadId);
419
        }
420
421
        $companyLeadRemove = [];
422
        if (!$companies instanceof Company) {
423
            //make sure they are ints
424
            $searchForCompanies = [];
425
            foreach ($companies as &$l) {
426
                $l = (int) $l;
427
                if (!isset($companyLeadRemove[$l])) {
428
                    $searchForCompanies[] = $l;
429
                }
430
            }
431
            if (!empty($searchForCompanies)) {
432
                $companyEntities = $this->getEntities(
433
                    [
434
                        'filter' => [
435
                            'force' => [
436
                                [
437
                                    'column' => 'comp.id',
438
                                    'expr'   => 'in',
439
                                    'value'  => $searchForCompanies,
440
                                ],
441
                            ],
442
                        ],
443
                    ]
444
                );
445
446
                foreach ($companyEntities as $company) {
447
                    $companyLeadRemove[$company->getId()] = $company;
448
                }
449
            }
450
451
            unset($companyEntities, $searchForCompanies);
452
        } else {
453
            $companyLeadRemove[$companies->getId()] = $companies;
454
455
            $companies = [$companies->getId()];
456
        }
457
458
        if (!is_array($companies)) {
459
            $companies = [$companies];
460
        }
461
462
        $deleteCompany  = [];
463
        $dispatchEvents = [];
464
465
        foreach ($companies as $companyId) {
466
            if (!isset($companyLeadRemove[$companyId])) {
467
                continue;
468
            }
469
470
            $companyLead = $this->getCompanyLeadRepository()->findOneBy(
471
                [
472
                    'lead'    => $lead,
473
                    'company' => $companyLeadRemove[$companyId],
474
                ]
475
            );
476
477
            if (null == $companyLead) {
478
                // Lead is not part of this list
479
                continue;
480
            }
481
482
            //lead was manually added and now manually removed or was not manually added and now being removed
483
            $deleteCompanyLead[] = $companyLead;
484
            $dispatchEvents[]    = $companyId;
485
486
            unset($companyLead);
487
        }
488
489
        if (!empty($deleteCompanyLead)) {
490
            $this->getCompanyLeadRepository()->deleteEntities($deleteCompanyLead);
491
        }
492
493
        // Clear CompanyLead entities from Doctrine memory
494
        $this->em->clear(CompanyLead::class);
495
496
        if (!empty($dispatchEvents) && ($this->dispatcher->hasListeners(LeadEvents::LEAD_COMPANY_CHANGE))) {
497
            foreach ($dispatchEvents as $listId) {
498
                $event = new LeadChangeCompanyEvent($lead, $companyLeadRemove[$listId], false);
499
                $this->dispatcher->dispatch(LeadEvents::LEAD_COMPANY_CHANGE, $event);
500
501
                unset($event);
502
            }
503
        }
504
505
        unset($lead, $deleteCompany, $companies);
506
    }
507
508
    /**
509
     * Get list of entities for autopopulate fields.
510
     *
511
     * @param $type
512
     * @param $filter
513
     * @param $limit
514
     * @param $start
515
     *
516
     * @return array
517
     */
518
    public function getLookupResults($type, $filter = '', $limit = 10, $start = 0)
519
    {
520
        $results = [];
521
        switch ($type) {
522
            case 'companyfield':
523
            case 'lead.company':
524
                if ('lead.company' === $type) {
525
                    $column    = 'companyname';
526
                    $filterVal = $filter;
527
                } else {
528
                    if (is_array($filter)) {
529
                        $column    = $filter[0];
530
                        $filterVal = $filter[1];
531
                    } else {
532
                        $column = $filter;
533
                    }
534
                }
535
536
                $expr      = new ExpressionBuilder($this->em->getConnection());
537
                $composite = $expr->andX();
538
                $composite->add(
539
                    $expr->like("comp.$column", ':filterVar')
540
                );
541
542
                // Validate owner permissions
543
                if (!$this->security->isGranted('lead:leads:viewother')) {
544
                    $composite->add(
545
                        $expr->orX(
546
                            $expr->andX(
547
                                $expr->isNull('comp.owner_id'),
548
                                $expr->eq('comp.created_by', (int) $this->userHelper->getUser()->getId())
549
                            ),
550
                            $expr->eq('comp.owner_id', (int) $this->userHelper->getUser()->getId())
551
                        )
552
                    );
553
                }
554
555
                $results = $this->getRepository()->getAjaxSimpleList($composite, ['filterVar' => $filterVal.'%'], $column);
556
557
                break;
558
        }
559
560
        return $results;
561
    }
562
563
    /**
564
     * {@inheritdoc}
565
     *
566
     * @param $action
567
     * @param $event
568
     * @param $entity
569
     * @param $isNew
570
     *
571
     * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
572
     */
573
    protected function dispatchEvent($action, &$entity, $isNew = false, Event $event = null)
574
    {
575
        if (!$entity instanceof Company) {
576
            throw new MethodNotAllowedHttpException(['Email']);
577
        }
578
579
        switch ($action) {
580
            case 'pre_save':
581
                $name = LeadEvents::COMPANY_PRE_SAVE;
582
                break;
583
            case 'post_save':
584
                $name = LeadEvents::COMPANY_POST_SAVE;
585
                break;
586
            case 'pre_delete':
587
                $name = LeadEvents::COMPANY_PRE_DELETE;
588
                break;
589
            case 'post_delete':
590
                $name = LeadEvents::COMPANY_POST_DELETE;
591
                break;
592
            default:
593
                return null;
594
        }
595
596
        if ($this->dispatcher->hasListeners($name)) {
597
            if (empty($event)) {
598
                $event = new CompanyEvent($entity, $isNew);
599
                $event->setEntityManager($this->em);
600
            }
601
602
            $this->dispatcher->dispatch($name, $event);
603
604
            return $event;
605
        } else {
606
            return null;
607
        }
608
    }
609
610
    /**
611
     * Company Merge function, will merge $mainCompany with $secCompany -  empty records from main company will be
612
     * filled with secondary then secondary will be deleted.
613
     *
614
     * @param $mainCompany
615
     * @param $secCompany
616
     *
617
     * @return mixed
618
     */
619
    public function companyMerge($mainCompany, $secCompany)
620
    {
621
        $this->logger->debug('COMPANY: Merging companies');
622
623
        $mainCompanyId = $mainCompany->getId();
624
        $secCompanyId  = $secCompany->getId();
625
626
        //if they are the same lead, then just return one
627
        if ($mainCompanyId === $secCompanyId) {
628
            return $mainCompany;
629
        }
630
        //merge fields
631
        $mergeSecFields    = $secCompany->getFields();
632
        $mainCompanyFields = $mainCompany->getFields();
633
        foreach ($mergeSecFields as $group => $groupFields) {
634
            foreach ($groupFields as $alias => $details) {
635
                //fill in empty main company fields with secondary company fields
636
                if (empty($mainCompanyFields[$group][$alias]['value']) && !empty($details['value'])) {
637
                    $mainCompany->addUpdatedField($alias, $details['value']);
638
                    $this->logger->debug('Company: Updated '.$alias.' = '.$details['value']);
639
                }
640
            }
641
        }
642
643
        //merge owner
644
        $mainCompanyOwner = $mainCompany->getOwner();
645
        $secCompanyOwner  = $secCompany->getOwner();
646
647
        if (null === $mainCompanyOwner && null !== $secCompanyOwner) {
648
            $mainCompany->setOwner($secCompanyOwner);
649
        }
650
651
        //move all leads from secondary company to main company
652
        $companyLeadRepo = $this->getCompanyLeadRepository();
653
        $secCompanyLeads = $companyLeadRepo->getCompanyLeads($secCompanyId);
654
655
        foreach ($secCompanyLeads as $lead) {
656
            $this->addLeadToCompany($mainCompany->getId(), $lead['lead_id']);
657
        }
658
        //save the updated company
659
        $this->saveEntity($mainCompany, false);
660
661
        //delete the old company
662
        $this->deleteEntity($secCompany);
663
664
        //return the merged company
665
        return $mainCompany;
666
    }
667
668
    /**
669
     * @return array
670
     */
671
    public function fetchCompanyFields()
672
    {
673
        if (empty($this->companyFields)) {
674
            $this->companyFields = $this->leadFieldModel->getEntities(
675
                [
676
                    'filter' => [
677
                        'force' => [
678
                            [
679
                                'column' => 'f.isPublished',
680
                                'expr'   => 'eq',
681
                                'value'  => true,
682
                            ],
683
                            [
684
                                'column' => 'f.object',
685
                                'expr'   => 'eq',
686
                                'value'  => 'company',
687
                            ],
688
                        ],
689
                    ],
690
                    'hydration_mode' => 'HYDRATE_ARRAY',
691
                ]
692
            );
693
        }
694
695
        return $this->companyFields;
696
    }
697
698
    /**
699
     * @param $mappedFields
700
     * @param $data
701
     *
702
     * @return array
703
     */
704
    public function extractCompanyDataFromImport(array &$mappedFields, array &$data)
705
    {
706
        $companyData    = [];
707
        $companyFields  = [];
708
        $internalFields = $this->fetchCompanyFields();
709
710
        foreach ($mappedFields as $mauticField => $importField) {
711
            foreach ($internalFields as $entityField) {
712
                if ($entityField['alias'] === $mauticField) {
713
                    $companyData[$importField]   = $data[$importField];
714
                    $companyFields[$mauticField] = $importField;
715
                    unset($data[$importField]);
716
                    unset($mappedFields[$mauticField]);
717
                    break;
718
                }
719
            }
720
        }
721
722
        return [$companyFields, $companyData];
723
    }
724
725
    /**
726
     * @param array        $fields
727
     * @param array        $data
728
     * @param null         $owner
729
     * @param null         $list
730
     * @param null         $tags
731
     * @param bool         $persist
732
     * @param LeadEventLog $eventLog
733
     *
734
     * @return bool|null
735
     *
736
     * @throws \Exception
737
     */
738
    public function import($fields, $data, $owner = null, $list = null, $tags = null, $persist = true, LeadEventLog $eventLog = null)
0 ignored issues
show
The parameter $tags 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 ignore-unused  annotation

738
    public function import($fields, $data, $owner = null, $list = null, /** @scrutinizer ignore-unused */ $tags = null, $persist = true, LeadEventLog $eventLog = null)

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...
The parameter $list 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 ignore-unused  annotation

738
    public function import($fields, $data, $owner = null, /** @scrutinizer ignore-unused */ $list = null, $tags = null, $persist = true, LeadEventLog $eventLog = null)

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...
The parameter $eventLog 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 ignore-unused  annotation

738
    public function import($fields, $data, $owner = null, $list = null, $tags = null, $persist = true, /** @scrutinizer ignore-unused */ LeadEventLog $eventLog = null)

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...
739
    {
740
        $fields = array_flip($fields);
741
742
        // Let's check for an existing company by name
743
        $hasName  = (!empty($fields['companyname']) && !empty($data[$fields['companyname']]));
744
        $hasEmail = (!empty($fields['companyemail']) && !empty($data[$fields['companyemail']]));
745
746
        if ($hasEmail) {
747
            $this->emailValidator->validate($data[$fields['companyemail']], false);
748
        }
749
750
        if ($hasName) {
751
            $companyName    = isset($fields['companyname']) ? $data[$fields['companyname']] : null;
752
            $companyCity    = isset($fields['companycity']) ? $data[$fields['companycity']] : null;
753
            $companyCountry = isset($fields['companycountry']) ? $data[$fields['companycountry']] : null;
754
            $companyState   = isset($fields['companystate']) ? $data[$fields['companystate']] : null;
755
756
            $found   = $companyName ? $this->getRepository()->identifyCompany($companyName, $companyCity, $companyCountry, $companyState) : false;
757
            $company = ($found) ? $this->em->getReference('MauticLeadBundle:Company', $found['id']) : new Company();
758
            $merged  = $found;
759
        } else {
760
            return null;
761
        }
762
763
        if (!empty($fields['dateAdded']) && !empty($data[$fields['dateAdded']])) {
764
            $dateAdded = new DateTimeHelper($data[$fields['dateAdded']]);
765
            $company->setDateAdded($dateAdded->getUtcDateTime());
766
        }
767
        unset($fields['dateAdded']);
768
769
        if (!empty($fields['dateModified']) && !empty($data[$fields['dateModified']])) {
770
            $dateModified = new DateTimeHelper($data[$fields['dateModified']]);
771
            $company->setDateModified($dateModified->getUtcDateTime());
772
        }
773
        unset($fields['dateModified']);
774
775
        if (!empty($fields['createdByUser']) && !empty($data[$fields['createdByUser']])) {
776
            $userRepo      = $this->em->getRepository('MauticUserBundle:User');
777
            $createdByUser = $userRepo->findByIdentifier($data[$fields['createdByUser']]);
778
            if (null !== $createdByUser) {
779
                $company->setCreatedBy($createdByUser);
780
            }
781
        }
782
        unset($fields['createdByUser']);
783
784
        if (!empty($fields['modifiedByUser']) && !empty($data[$fields['modifiedByUser']])) {
785
            $userRepo       = $this->em->getRepository('MauticUserBundle:User');
786
            $modifiedByUser = $userRepo->findByIdentifier($data[$fields['modifiedByUser']]);
787
            if (null !== $modifiedByUser) {
788
                $company->setModifiedBy($modifiedByUser);
789
            }
790
        }
791
        unset($fields['modifiedByUser']);
792
793
        if (null !== $owner) {
794
            $company->setOwner($this->em->getReference('MauticUserBundle:User', $owner));
795
        }
796
797
        // Set profile data using the form so that values are validated
798
        $fieldData = [];
799
        foreach ($fields as $entityField => $importField) {
800
            // Prevent overwriting existing data with empty data
801
            if (array_key_exists($importField, $data) && !is_null($data[$importField]) && '' != $data[$importField]) {
802
                $fieldData[$entityField] = $data[$importField];
803
            }
804
        }
805
806
        $fieldErrors = [];
807
808
        foreach ($this->fetchCompanyFields() as $entityField) {
809
            if (isset($fieldData[$entityField['alias']])) {
810
                $fieldData[$entityField['alias']] = InputHelper::_($fieldData[$entityField['alias']], 'string');
811
812
                if ('NULL' === $fieldData[$entityField['alias']]) {
813
                    $fieldData[$entityField['alias']] = null;
814
815
                    continue;
816
                }
817
818
                try {
819
                    $this->cleanFields($fieldData, $entityField);
820
                } catch (\Exception $exception) {
821
                    $fieldErrors[] = $entityField['alias'].': '.$exception->getMessage();
822
                }
823
824
                // Skip if the value is in the CSV row
825
                continue;
826
            } elseif ($company->isNew() && $entityField['defaultValue']) {
827
                // Fill in the default value if any
828
                $fieldData[$entityField['alias']] = ('multiselect' === $entityField['type']) ? [$entityField['defaultValue']] : $entityField['defaultValue'];
829
            }
830
        }
831
832
        if ($fieldErrors) {
833
            $fieldErrors = implode("\n", $fieldErrors);
834
835
            throw new \Exception($fieldErrors);
836
        }
837
838
        // All clear
839
        foreach ($fieldData as $field => $value) {
840
            $company->addUpdatedField($field, $value);
841
        }
842
843
        if ($persist) {
844
            $this->saveEntity($company);
845
        }
846
847
        return $merged;
848
    }
849
}
850