Issues (3627)

CampaignActionJumpToEventSubscriber.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2018 Mautic Contributors. All rights reserved
5
 * @author      Mautic, Inc.
6
 *
7
 * @link        https://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CampaignBundle\EventListener;
13
14
use Mautic\CampaignBundle\CampaignEvents;
15
use Mautic\CampaignBundle\Entity\Event;
16
use Mautic\CampaignBundle\Entity\EventRepository;
17
use Mautic\CampaignBundle\Entity\LeadRepository;
18
use Mautic\CampaignBundle\Event\CampaignBuilderEvent;
19
use Mautic\CampaignBundle\Event\CampaignEvent;
20
use Mautic\CampaignBundle\Event\PendingEvent;
21
use Mautic\CampaignBundle\Executioner\EventExecutioner;
22
use Mautic\CampaignBundle\Form\Type\CampaignEventJumpToEventType;
23
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
24
use Symfony\Component\Translation\TranslatorInterface;
25
26
class CampaignActionJumpToEventSubscriber implements EventSubscriberInterface
27
{
28
    const EVENT_NAME = 'campaign.jump_to_event';
29
30
    /**
31
     * @var EventRepository
32
     */
33
    private $eventRepository;
34
35
    /**
36
     * @var EventExecutioner
37
     */
38
    private $eventExecutioner;
39
40
    /**
41
     * @var TranslatorInterface
42
     */
43
    private $translator;
44
45
    /**
46
     * @var LeadRepository
47
     */
48
    private $leadRepository;
49
50
    public function __construct(EventRepository $eventRepository, EventExecutioner $eventExecutioner, TranslatorInterface $translator, LeadRepository $leadRepository)
51
    {
52
        $this->eventRepository  = $eventRepository;
53
        $this->eventExecutioner = $eventExecutioner;
54
        $this->translator       = $translator;
55
        $this->leadRepository   = $leadRepository;
56
    }
57
58
    /**
59
     * @return array
60
     */
61
    public static function getSubscribedEvents()
62
    {
63
        return [
64
            CampaignEvents::CAMPAIGN_POST_SAVE     => ['processCampaignEventsAfterSave', 1],
65
            CampaignEvents::CAMPAIGN_ON_BUILD      => ['onCampaignBuild', 0],
66
            CampaignEvents::ON_EVENT_JUMP_TO_EVENT => ['onJumpToEvent', 0],
67
        ];
68
    }
69
70
    /**
71
     * Add event triggers and actions.
72
     */
73
    public function onCampaignBuild(CampaignBuilderEvent $event)
74
    {
75
        // Add action to jump to another event in the campaign flow.
76
        $event->addAction(self::EVENT_NAME, [
77
            'label'                  => 'mautic.campaign.event.jump_to_event',
78
            'description'            => 'mautic.campaign.event.jump_to_event_descr',
79
            'formType'               => CampaignEventJumpToEventType::class,
80
            'template'               => 'MauticCampaignBundle:Event:jump.html.php',
81
            'batchEventName'         => CampaignEvents::ON_EVENT_JUMP_TO_EVENT,
82
            'connectionRestrictions' => [
83
                'target' => [
84
                    Event::TYPE_DECISION  => ['none'],
85
                    Event::TYPE_ACTION    => ['none'],
86
                    Event::TYPE_CONDITION => ['none'],
87
                ],
88
            ],
89
        ]);
90
    }
91
92
    /**
93
     * Process campaign.jump_to_event actions.
94
     *
95
     * @throws \Mautic\CampaignBundle\Executioner\Dispatcher\Exception\LogNotProcessedException
96
     * @throws \Mautic\CampaignBundle\Executioner\Dispatcher\Exception\LogPassedAndFailedException
97
     * @throws \Mautic\CampaignBundle\Executioner\Exception\CannotProcessEventException
98
     * @throws \Mautic\CampaignBundle\Executioner\Scheduler\Exception\NotSchedulableException
99
     */
100
    public function onJumpToEvent(PendingEvent $campaignEvent)
101
    {
102
        $event      = $campaignEvent->getEvent();
103
        $jumpTarget = $this->getJumpTargetForEvent($event, 'e.id');
104
105
        if (null === $jumpTarget) {
106
            // Target event has been removed.
107
            $pending  = $campaignEvent->getPending();
108
            $contacts = $campaignEvent->getContacts();
109
            foreach ($contacts as $logId => $contact) {
110
                // Pass with an error for the UI.
111
                $campaignEvent->passWithError(
112
                    $pending->get($logId),
0 ignored issues
show
It seems like $pending->get($logId) can also be of type null; however, parameter $log of Mautic\CampaignBundle\Ev...gEvent::passWithError() does only seem to accept Mautic\CampaignBundle\Entity\LeadEventLog, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
                    /** @scrutinizer ignore-type */ $pending->get($logId),
Loading history...
113
                    $this->translator->trans('mautic.campaign.campaign.jump_to_event.target_not_exist')
114
                );
115
            }
116
        } else {
117
            // Increment the campaign rotation for the given contacts and current campaign
118
            $this->leadRepository->incrementCampaignRotationForContacts(
119
                $campaignEvent->getContactsKeyedById()->getKeys(),
120
                $event->getCampaign()->getId()
121
            );
122
            $this->eventExecutioner->executeForContacts($jumpTarget, $campaignEvent->getContactsKeyedById());
123
            $campaignEvent->passRemaining();
124
        }
125
    }
126
127
    /**
128
     * Update campaign events.
129
     *
130
     * This block specifically handles the campaign.jump_to_event properties
131
     * to ensure that it has the actual ID and not the temp_id as the
132
     * target for the jump.
133
     */
134
    public function processCampaignEventsAfterSave(CampaignEvent $campaignEvent)
135
    {
136
        $campaign = $campaignEvent->getCampaign();
137
        $events   = $campaign->getEvents();
138
        $toSave   = [];
139
140
        foreach ($events as $event) {
141
            if (self::EVENT_NAME !== $event->getType()) {
142
                continue;
143
            }
144
145
            $jumpTarget = $this->getJumpTargetForEvent($event, 'e.tempId');
146
147
            if (null !== $jumpTarget) {
148
                $event->setProperties(array_merge(
149
                    $event->getProperties(),
150
                    [
151
                        'jumpToEvent' => $jumpTarget->getId(),
152
                    ]
153
                ));
154
155
                $toSave[] = $event;
156
            }
157
        }
158
159
        if (count($toSave)) {
160
            $this->eventRepository->saveEntities($toSave);
161
        }
162
    }
163
164
    /**
165
     * Inspect a jump event and get its target.
166
     */
167
    private function getJumpTargetForEvent(Event $event, string $column): ?Event
168
    {
169
        $properties  = $event->getProperties();
170
        $jumpToEvent = $this->eventRepository->getEntities([
171
            'ignore_paginator' => true,
172
            'filter'           => [
173
                'force' => [
174
                    [
175
                        'column' => $column,
176
                        'value'  => $properties['jumpToEvent'],
177
                        'expr'   => 'eq',
178
                    ],
179
                    [
180
                        'column' => 'e.campaign',
181
                        'value'  => $event->getCampaign(),
182
                        'expr'   => 'eq',
183
                    ],
184
                ],
185
            ],
186
        ]);
187
188
        if (count($jumpToEvent)) {
189
            return $jumpToEvent[0];
190
        }
191
192
        return null;
193
    }
194
}
195