Issues (3627)

app/bundles/CampaignBundle/Model/CampaignModel.php (1 issue)

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\CampaignBundle\Model;
13
14
use Doctrine\ORM\PersistentCollection;
15
use Mautic\CampaignBundle\CampaignEvents;
16
use Mautic\CampaignBundle\Entity\Campaign;
17
use Mautic\CampaignBundle\Entity\Event;
18
use Mautic\CampaignBundle\Entity\Lead as CampaignLead;
19
use Mautic\CampaignBundle\Event as Events;
20
use Mautic\CampaignBundle\EventCollector\EventCollector;
21
use Mautic\CampaignBundle\Executioner\ContactFinder\Limiter\ContactLimiter;
22
use Mautic\CampaignBundle\Form\Type\CampaignType;
23
use Mautic\CampaignBundle\Helper\ChannelExtractor;
24
use Mautic\CampaignBundle\Membership\MembershipBuilder;
25
use Mautic\CoreBundle\Helper\Chart\ChartQuery;
26
use Mautic\CoreBundle\Helper\Chart\LineChart;
27
use Mautic\CoreBundle\Model\FormModel as CommonFormModel;
28
use Mautic\FormBundle\Entity\Form;
29
use Mautic\FormBundle\Model\FormModel;
30
use Mautic\LeadBundle\Entity\Lead;
31
use Mautic\LeadBundle\Model\ListModel;
32
use Mautic\LeadBundle\Tracker\ContactTracker;
33
use Symfony\Component\Console\Output\OutputInterface;
34
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
35
36
class CampaignModel extends CommonFormModel
37
{
38
    /**
39
     * @var ListModel
40
     */
41
    protected $leadListModel;
42
43
    /**
44
     * @var FormModel
45
     */
46
    protected $formModel;
47
48
    /**
49
     * @var EventCollector
50
     */
51
    private $eventCollector;
52
53
    /**
54
     * @var MembershipBuilder
55
     */
56
    private $membershipBuilder;
57
58
    /**
59
     * @var ContactTracker
60
     */
61
    private $contactTracker;
62
63
    public function __construct(
64
        ListModel $leadListModel,
65
        FormModel $formModel,
66
        EventCollector $eventCollector,
67
        MembershipBuilder $membershipBuilder,
68
        ContactTracker $contactTracker
69
    ) {
70
        $this->leadListModel     = $leadListModel;
71
        $this->formModel         = $formModel;
72
        $this->eventCollector    = $eventCollector;
73
        $this->membershipBuilder = $membershipBuilder;
74
        $this->contactTracker    = $contactTracker;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     *
80
     * @return \Mautic\CampaignBundle\Entity\CampaignRepository
81
     */
82
    public function getRepository()
83
    {
84
        $repo = $this->em->getRepository('MauticCampaignBundle:Campaign');
85
        $repo->setCurrentUser($this->userHelper->getUser());
86
87
        return $repo;
88
    }
89
90
    /**
91
     * @return \Mautic\CampaignBundle\Entity\EventRepository
92
     */
93
    public function getEventRepository()
94
    {
95
        return $this->em->getRepository('MauticCampaignBundle:Event');
96
    }
97
98
    /**
99
     * @return \Mautic\CampaignBundle\Entity\LeadRepository
100
     */
101
    public function getCampaignLeadRepository()
102
    {
103
        return $this->em->getRepository('MauticCampaignBundle:Lead');
104
    }
105
106
    /**
107
     * @return \Mautic\CampaignBundle\Entity\LeadEventLogRepository
108
     */
109
    public function getCampaignLeadEventLogRepository()
110
    {
111
        return $this->em->getRepository('MauticCampaignBundle:LeadEventLog');
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     *
117
     * @return string
118
     */
119
    public function getPermissionBase()
120
    {
121
        return 'campaign:campaigns';
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     *
127
     * @param       $entity
128
     * @param       $formFactory
129
     * @param null  $action
130
     * @param array $options
131
     *
132
     * @return mixed
133
     *
134
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
135
     */
136
    public function createForm($entity, $formFactory, $action = null, $options = [])
137
    {
138
        if (!$entity instanceof Campaign) {
139
            throw new MethodNotAllowedHttpException(['Campaign']);
140
        }
141
142
        if (!empty($action)) {
143
            $options['action'] = $action;
144
        }
145
146
        return $formFactory->create(CampaignType::class, $entity, $options);
147
    }
148
149
    /**
150
     * Get a specific entity or generate a new one if id is empty.
151
     *
152
     * @param $id
153
     *
154
     * @return Campaign|null
155
     */
156
    public function getEntity($id = null)
157
    {
158
        if (null === $id) {
159
            return new Campaign();
160
        }
161
162
        return parent::getEntity($id);
163
    }
164
165
    /**
166
     * @param object $entity
167
     */
168
    public function deleteEntity($entity)
169
    {
170
        // Null all the event parents for this campaign to avoid database constraints
171
        $this->getEventRepository()->nullEventParents($entity->getId());
172
173
        parent::deleteEntity($entity);
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     *
179
     * @param $action
180
     * @param $event
181
     * @param $entity
182
     * @param $isNew
183
     *
184
     * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
185
     */
186
    protected function dispatchEvent($action, &$entity, $isNew = false, \Symfony\Component\EventDispatcher\Event $event = null)
187
    {
188
        if ($entity instanceof \Mautic\CampaignBundle\Entity\Lead) {
189
            return;
190
        }
191
192
        if (!$entity instanceof Campaign) {
193
            throw new MethodNotAllowedHttpException(['Campaign']);
194
        }
195
196
        switch ($action) {
197
            case 'pre_save':
198
                $name = CampaignEvents::CAMPAIGN_PRE_SAVE;
199
                break;
200
            case 'post_save':
201
                $name = CampaignEvents::CAMPAIGN_POST_SAVE;
202
                break;
203
            case 'pre_delete':
204
                $name = CampaignEvents::CAMPAIGN_PRE_DELETE;
205
                break;
206
            case 'post_delete':
207
                $name = CampaignEvents::CAMPAIGN_POST_DELETE;
208
                break;
209
            default:
210
                return null;
211
        }
212
213
        if ($this->dispatcher->hasListeners($name)) {
214
            if (empty($event)) {
215
                $event = new Events\CampaignEvent($entity, $isNew);
216
            }
217
218
            $this->dispatcher->dispatch($name, $event);
219
220
            return $event;
221
        } else {
222
            return null;
223
        }
224
    }
225
226
    /**
227
     * @param $sessionEvents
228
     * @param $sessionConnections
229
     * @param $deletedEvents
230
     *
231
     * @return array
232
     */
233
    public function setEvents(Campaign $entity, $sessionEvents, $sessionConnections, $deletedEvents)
234
    {
235
        $existingEvents = $entity->getEvents()->toArray();
236
        $events         = [];
237
        $hierarchy      = [];
238
239
        foreach ($sessionEvents as $properties) {
240
            $isNew = (!empty($properties['id']) && isset($existingEvents[$properties['id']])) ? false : true;
241
            $event = !$isNew ? $existingEvents[$properties['id']] : new Event();
242
243
            foreach ($properties as $f => $v) {
244
                if ('id' == $f && 0 === strpos($v, 'new')) {
245
                    //set the temp ID used to be able to match up connections
246
                    $event->setTempId($v);
247
                }
248
249
                if (in_array($f, ['id', 'parent'])) {
250
                    continue;
251
                }
252
253
                $func = 'set'.ucfirst($f);
254
                if (method_exists($event, $func)) {
255
                    $event->$func($v);
256
                }
257
            }
258
259
            ChannelExtractor::setChannel($event, $event, $this->eventCollector->getEventConfig($event));
260
261
            $event->setCampaign($entity);
262
            $events[$properties['id']] = $event;
263
        }
264
265
        foreach ($deletedEvents as $deleteMe) {
266
            if (isset($existingEvents[$deleteMe])) {
267
                // Remove child from parent
268
                $parent = $existingEvents[$deleteMe]->getParent();
269
                if ($parent) {
270
                    $parent->removeChild($existingEvents[$deleteMe]);
271
                    $existingEvents[$deleteMe]->removeParent();
272
                }
273
274
                $entity->removeEvent($existingEvents[$deleteMe]);
275
276
                unset($events[$deleteMe]);
277
            }
278
        }
279
280
        $relationships = [];
281
282
        if (isset($sessionConnections['connections'])) {
283
            foreach ($sessionConnections['connections'] as $connection) {
284
                $source = $connection['sourceId'];
285
                $target = $connection['targetId'];
286
287
                if (in_array($source, ['lists', 'forms'])) {
288
                    // Only concerned with events and not sources
289
                    continue;
290
                }
291
292
                if (isset($connection['anchors']['source'])) {
293
                    $sourceDecision = $connection['anchors']['source'];
294
                } else {
295
                    $sourceDecision = (!empty($connection['anchors'][0])) ? $connection['anchors'][0]['endpoint'] : null;
296
                }
297
298
                if ('leadsource' == $sourceDecision) {
299
                    // Lead source connection that does not matter
300
                    continue;
301
                }
302
303
                $relationships[$target] = [
304
                    'parent'   => $source,
305
                    'decision' => $sourceDecision,
306
                ];
307
            }
308
        }
309
310
        // Assign parent/child relationships
311
        foreach ($events as $id => $e) {
312
            if (isset($relationships[$id])) {
313
                // Has a parent
314
                $anchor = in_array($relationships[$id]['decision'], ['yes', 'no']) ? $relationships[$id]['decision'] : null;
315
                $events[$id]->setDecisionPath($anchor);
316
317
                $parentId = $relationships[$id]['parent'];
318
                $events[$id]->setParent($events[$parentId]);
319
320
                $hierarchy[$id] = $parentId;
321
            } elseif ($events[$id]->getParent()) {
322
                // No longer has a parent so null it out
323
324
                // Remove decision so that it doesn't affect execution
325
                $events[$id]->setDecisionPath(null);
326
327
                // Remove child from parent
328
                $parent = $events[$id]->getParent();
329
                $parent->removeChild($events[$id]);
330
331
                // Remove parent from child
332
                $events[$id]->removeParent();
333
                $hierarchy[$id] = 'null';
334
            } else {
335
                // Is a parent
336
                $hierarchy[$id] = 'null';
337
338
                // Remove decision so that it doesn't affect execution
339
                $events[$id]->setDecisionPath(null);
340
            }
341
        }
342
343
        $entity->addEvents($events);
344
345
        //set event order used when querying the events
346
        $this->buildOrder($hierarchy, $events, $entity);
347
348
        uasort(
349
            $events,
350
            function ($a, $b) {
351
                $aOrder = $a->getOrder();
352
                $bOrder = $b->getOrder();
353
                if ($aOrder == $bOrder) {
354
                    return 0;
355
                }
356
357
                return ($aOrder < $bOrder) ? -1 : 1;
358
            }
359
        );
360
361
        // Persist events if campaign is being edited
362
        if ($entity->getId()) {
363
            $this->getEventRepository()->saveEntities($events);
364
        }
365
366
        return $events;
367
    }
368
369
    /**
370
     * @param      $entity
371
     * @param      $settings
372
     * @param bool $persist
373
     * @param null $events
374
     *
375
     * @return array
376
     */
377
    public function setCanvasSettings($entity, $settings, $persist = true, $events = null)
378
    {
379
        if (null === $events) {
380
            $events = $entity->getEvents();
381
        }
382
383
        $tempIds = [];
384
385
        foreach ($events as $e) {
386
            if ($e instanceof Event) {
387
                $tempIds[$e->getTempId()] = $e->getId();
388
            } else {
389
                $tempIds[$e['tempId']] = $e['id'];
390
            }
391
        }
392
393
        if (!isset($settings['nodes'])) {
394
            $settings['nodes'] = [];
395
        }
396
397
        foreach ($settings['nodes'] as &$node) {
398
            if (false !== strpos($node['id'], 'new')) {
399
                // Find the real one and update the node
400
                $node['id'] = str_replace($node['id'], $tempIds[$node['id']], $node['id']);
401
            }
402
        }
403
404
        if (!isset($settings['connections'])) {
405
            $settings['connections'] = [];
406
        }
407
408
        foreach ($settings['connections'] as &$connection) {
409
            // Check source
410
            if (false !== strpos($connection['sourceId'], 'new')) {
411
                // Find the real one and update the node
412
                $connection['sourceId'] = str_replace($connection['sourceId'], $tempIds[$connection['sourceId']], $connection['sourceId']);
413
            }
414
415
            // Check target
416
            if (false !== strpos($connection['targetId'], 'new')) {
417
                // Find the real one and update the node
418
                $connection['targetId'] = str_replace($connection['targetId'], $tempIds[$connection['targetId']], $connection['targetId']);
419
            }
420
421
            // Rebuild anchors
422
            if (!isset($connection['anchors']['source'])) {
423
                $anchors = [];
424
                foreach ($connection['anchors'] as $k => $anchor) {
425
                    $type           = (0 === $k) ? 'source' : 'target';
426
                    $anchors[$type] = $anchor['endpoint'];
427
                }
428
429
                $connection['anchors'] = $anchors;
430
            }
431
        }
432
433
        $entity->setCanvasSettings($settings);
434
435
        if ($persist) {
436
            $this->getRepository()->saveEntity($entity);
437
        }
438
439
        return $settings;
440
    }
441
442
    /**
443
     * Get list of sources for a campaign.
444
     *
445
     * @param $campaign
446
     *
447
     * @return array
448
     */
449
    public function getLeadSources($campaign)
450
    {
451
        $campaignId = ($campaign instanceof Campaign) ? $campaign->getId() : $campaign;
452
453
        $sources = [];
454
455
        // Lead lists
456
        $sources['lists'] = $this->getRepository()->getCampaignListSources($campaignId);
457
458
        // Forms
459
        $sources['forms'] = $this->getRepository()->getCampaignFormSources($campaignId);
460
461
        return $sources;
462
    }
463
464
    /**
465
     * Add and/or delete lead sources from a campaign.
466
     *
467
     * @param $entity
468
     * @param $addedSources
469
     * @param $deletedSources
470
     */
471
    public function setLeadSources(Campaign $entity, $addedSources, $deletedSources)
472
    {
473
        foreach ($addedSources as $type => $sources) {
474
            foreach ($sources as $id => $label) {
475
                switch ($type) {
476
                    case 'lists':
477
                        $entity->addList($this->em->getReference('MauticLeadBundle:LeadList', $id));
478
                        break;
479
                    case 'forms':
480
                        $entity->addForm($this->em->getReference('MauticFormBundle:Form', $id));
481
                        break;
482
                    default:
483
                        break;
484
                }
485
            }
486
        }
487
488
        foreach ($deletedSources as $type => $sources) {
489
            foreach ($sources as $id => $label) {
490
                switch ($type) {
491
                    case 'lists':
492
                        $entity->removeList($this->em->getReference('MauticLeadBundle:LeadList', $id));
493
                        break;
494
                    case 'forms':
495
                        $entity->removeForm($this->em->getReference('MauticFormBundle:Form', $id));
496
                        break;
497
                    default:
498
                        break;
499
                }
500
            }
501
        }
502
    }
503
504
    /**
505
     * Get a list of source choices.
506
     *
507
     * @param string $sourceType
508
     * @param bool   $globalOnly
509
     *
510
     * @return array
511
     */
512
    public function getSourceLists($sourceType = null, $globalOnly = false)
513
    {
514
        $choices = [];
515
        switch ($sourceType) {
516
            case 'lists':
517
            case null:
518
                $choices['lists'] = [];
519
                $lists            = $globalOnly ? $this->leadListModel->getGlobalLists() : $this->leadListModel->getUserLists();
520
521
                if ($lists) {
522
                    foreach ($lists as $list) {
523
                        $choices['lists'][$list['id']] = $list['name'];
524
                    }
525
                }
526
527
            // no break
528
            case 'forms':
529
            case null:
530
                $choices['forms'] = [];
531
                $viewOther        = $this->security->isGranted('form:forms:viewother');
532
                $repo             = $this->formModel->getRepository();
533
                $repo->setCurrentUser($this->userHelper->getUser());
534
535
                $forms = $repo->getFormList('', 0, 0, $viewOther, 'campaign');
536
537
                if ($forms) {
538
                    foreach ($forms as $form) {
539
                        $choices['forms'][$form['id']] = $form['name'];
540
                    }
541
                }
542
        }
543
544
        foreach ($choices as &$typeChoices) {
545
            asort($typeChoices);
546
        }
547
548
        return (null == $sourceType) ? $choices : $choices[$sourceType];
0 ignored issues
show
It seems like you are loosely comparing $sourceType of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
549
    }
550
551
    /**
552
     * @param mixed $form
553
     *
554
     * @return array
555
     */
556
    public function getCampaignsByForm($form)
557
    {
558
        $formId = ($form instanceof Form) ? $form->getId() : $form;
559
560
        return $this->getRepository()->findByFormId($formId);
561
    }
562
563
    /**
564
     * Gets the campaigns a specific lead is part of.
565
     *
566
     * @param Lead $lead
567
     * @param bool $forList
568
     *
569
     * @return mixed
570
     */
571
    public function getLeadCampaigns(Lead $lead = null, $forList = false)
572
    {
573
        static $campaigns = [];
574
575
        if (null === $lead) {
576
            $lead = $this->contactTracker->getContact();
577
        }
578
579
        if (!isset($campaigns[$lead->getId()])) {
580
            $repo   = $this->getRepository();
581
            $leadId = $lead->getId();
582
            //get the campaigns the lead is currently part of
583
            $campaigns[$leadId] = $repo->getPublishedCampaigns(
584
                null,
585
                $lead->getId(),
586
                $forList,
587
                $this->security->isGranted($this->getPermissionBase().':viewother')
588
            );
589
        }
590
591
        return $campaigns[$lead->getId()];
592
    }
593
594
    /**
595
     * Gets a list of published campaigns.
596
     *
597
     * @param bool $forList
598
     *
599
     * @return array
600
     */
601
    public function getPublishedCampaigns($forList = false)
602
    {
603
        static $campaigns = [];
604
605
        if (empty($campaigns)) {
606
            $campaigns = $this->getRepository()->getPublishedCampaigns(
607
                null,
608
                null,
609
                $forList,
610
                $this->security->isGranted($this->getPermissionBase().':viewother')
611
            );
612
        }
613
614
        return $campaigns;
615
    }
616
617
    /**
618
     * Saves a campaign lead, logs the error if saving fails.
619
     *
620
     * @return bool
621
     */
622
    public function saveCampaignLead(CampaignLead $campaignLead)
623
    {
624
        try {
625
            $this->getCampaignLeadRepository()->saveEntity($campaignLead);
626
627
            return true;
628
        } catch (\Exception $exception) {
629
            $this->logger->log('error', $exception->getMessage(), ['exception' => $exception]);
630
631
            return false;
632
        }
633
    }
634
635
    /**
636
     * Get details of leads in a campaign.
637
     *
638
     * @param      $campaign
639
     * @param null $leads
640
     *
641
     * @return mixed
642
     */
643
    public function getLeadDetails($campaign, $leads = null)
644
    {
645
        $campaignId = ($campaign instanceof Campaign) ? $campaign->getId() : $campaign;
646
647
        if ($leads instanceof PersistentCollection) {
648
            $leads = array_keys($leads->toArray());
649
        }
650
651
        return $this->em->getRepository('MauticCampaignBundle:Lead')->getLeadDetails($campaignId, $leads);
652
    }
653
654
    /**
655
     * Get leads for a campaign.  If $event is passed in, only leads who have not triggered the event are returned.
656
     *
657
     * @param Campaign $campaign
658
     * @param array    $event
659
     *
660
     * @return mixed
661
     */
662
    public function getCampaignLeads($campaign, $event = null)
663
    {
664
        $campaignId = ($campaign instanceof Campaign) ? $campaign->getId() : $campaign;
665
        $eventId    = (is_array($event) && isset($event['id'])) ? $event['id'] : $event;
666
667
        return $this->em->getRepository('MauticCampaignBundle:Lead')->getLeads($campaignId, $eventId);
668
    }
669
670
    /**
671
     * @param $id
672
     *
673
     * @return array
674
     */
675
    public function getCampaignListIds($id)
676
    {
677
        return $this->getRepository()->getCampaignListIds((int) $id);
678
    }
679
680
    /**
681
     * Get line chart data of leads added to campaigns.
682
     *
683
     * @param string $unit          {@link php.net/manual/en/function.date.php#refsect1-function.date-parameters}
684
     * @param string $dateFormat
685
     * @param array  $filter
686
     * @param bool   $canViewOthers
687
     *
688
     * @return array
689
     */
690
    public function getLeadsAddedLineChartData($unit, \DateTime $dateFrom, \DateTime $dateTo, $dateFormat = null, $filter = [], $canViewOthers = true)
691
    {
692
        $chart = new LineChart($unit, $dateFrom, $dateTo, $dateFormat);
693
        $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo);
694
        $q     = $query->prepareTimeDataQuery('campaign_leads', 'date_added', $filter);
695
696
        if (!$canViewOthers) {
697
            $q->join('t', MAUTIC_TABLE_PREFIX.'campaigns', 'c', 'c.id = c.campaign_id')
698
                ->andWhere('c.created_by = :userId')
699
                ->setParameter('userId', $this->userHelper->getUser()->getId());
700
        }
701
702
        $data = $query->loadAndBuildTimeData($q);
703
        $chart->setDataset($this->translator->trans('mautic.campaign.campaign.leads'), $data);
704
705
        return $chart->render();
706
    }
707
708
    /**
709
     * Get line chart data of hits.
710
     *
711
     * @param string $unit       {@link php.net/manual/en/function.date.php#refsect1-function.date-parameters}
712
     * @param string $dateFormat
713
     * @param array  $filter
714
     *
715
     * @return array
716
     */
717
    public function getCampaignMetricsLineChartData($unit, \DateTime $dateFrom, \DateTime $dateTo, $dateFormat = null, $filter = [])
718
    {
719
        $events = [];
720
        $chart  = new LineChart($unit, $dateFrom, $dateTo, $dateFormat);
721
        $query  = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo);
722
723
        $contacts = $query->fetchTimeData('campaign_leads', 'date_added', $filter);
724
        $chart->setDataset($this->translator->trans('mautic.campaign.campaign.leads'), $contacts);
725
726
        if (isset($filter['campaign_id'])) {
727
            $rawEvents = $this->getEventRepository()->getCampaignEvents($filter['campaign_id']);
728
729
            // Group events by type
730
            if ($rawEvents) {
731
                foreach ($rawEvents as $event) {
732
                    if (isset($events[$event['type']])) {
733
                        $events[$event['type']][] = $event['id'];
734
                    } else {
735
                        $events[$event['type']] = [$event['id']];
736
                    }
737
                }
738
            }
739
740
            if ($events) {
741
                foreach ($events as $type => $eventIds) {
742
                    $filter['event_id'] = $eventIds;
743
744
                    // Exclude failed events
745
                    $failedSq = $this->em->getConnection()->createQueryBuilder();
746
                    $failedSq->select('null')
747
                        ->from(MAUTIC_TABLE_PREFIX.'campaign_lead_event_failed_log', 'fe')
748
                        ->where(
749
                            $failedSq->expr()->eq('fe.log_id', 't.id')
750
                        );
751
                    $filter['failed_events'] = [
752
                        'subquery' => sprintf('NOT EXISTS (%s)', $failedSq->getSQL()),
753
                    ];
754
755
                    $q       = $query->prepareTimeDataQuery('campaign_lead_event_log', 'date_triggered', $filter);
756
                    $rawData = $q->execute()->fetchAll();
757
758
                    if (!empty($rawData)) {
759
                        $triggers = $query->completeTimeData($rawData);
760
                        $chart->setDataset($this->translator->trans('mautic.campaign.'.$type), $triggers);
761
                    }
762
                }
763
                unset($filter['event_id']);
764
            }
765
        }
766
767
        return $chart->render();
768
    }
769
770
    /**
771
     * @param          $hierarchy
772
     * @param          $events
773
     * @param Campaign $entity
774
     * @param string   $root
775
     * @param int      $order
776
     */
777
    protected function buildOrder($hierarchy, &$events, $entity, $root = 'null', $order = 1)
778
    {
779
        $count = count($hierarchy);
780
        if (1 === $count && 'null' === array_unique(array_values($hierarchy))[0]) {
781
            // no parents so leave order as is
782
783
            return;
784
        } else {
785
            foreach ($hierarchy as $eventId => $parent) {
786
                if ($parent == $root || 1 === $count) {
787
                    $events[$eventId]->setOrder($order);
788
                    unset($hierarchy[$eventId]);
789
                    if (count($hierarchy)) {
790
                        $this->buildOrder($hierarchy, $events, $entity, $eventId, $order + 1);
791
                    }
792
                }
793
            }
794
        }
795
    }
796
797
    /**
798
     * @param int             $limit
799
     * @param bool            $maxLeads
800
     * @param OutputInterface $output
801
     *
802
     * @return int
803
     */
804
    public function rebuildCampaignLeads(Campaign $campaign, $limit = 1000, $maxLeads = false, OutputInterface $output = null)
805
    {
806
        $contactLimiter = new ContactLimiter($limit);
807
808
        return $this->membershipBuilder->build($campaign, $contactLimiter, $maxLeads, $output);
809
    }
810
811
    /**
812
     * @param $segmentId
813
     *
814
     * @return array
815
     */
816
    public function getCampaignIdsWithDependenciesOnSegment($segmentId)
817
    {
818
        $entities = $this->getRepository()->getEntities(
819
            [
820
                'filter'    => [
821
                    'force' => [
822
                        [
823
                            'column' => 'l.id',
824
                            'expr'   => 'eq',
825
                            'value'  => $segmentId,
826
                        ],
827
                    ],
828
                ],
829
                'joinLists' => true,
830
            ]
831
        );
832
833
        $ids = [];
834
        foreach ($entities as $entity) {
835
            $ids[] = $entity->getId();
836
        }
837
838
        return $ids;
839
    }
840
}
841