Passed
Push — staging ( 81ba0c...d71a8f )
by Woeler
14:37 queued 10s
created

Executioner/Event/DecisionExecutioner.php (1 issue)

Severity
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\Executioner\Event;
13
14
use Doctrine\Common\Collections\ArrayCollection;
15
use Mautic\CampaignBundle\Entity\Event;
16
use Mautic\CampaignBundle\Entity\LeadEventLog;
17
use Mautic\CampaignBundle\EventCollector\Accessor\Event\AbstractEventAccessor;
18
use Mautic\CampaignBundle\EventCollector\Accessor\Event\DecisionAccessor;
19
use Mautic\CampaignBundle\Executioner\Dispatcher\DecisionDispatcher;
20
use Mautic\CampaignBundle\Executioner\Exception\CannotProcessEventException;
21
use Mautic\CampaignBundle\Executioner\Exception\DecisionNotApplicableException;
22
use Mautic\CampaignBundle\Executioner\Logger\EventLogger;
23
use Mautic\CampaignBundle\Executioner\Result\EvaluatedContacts;
24
use Mautic\LeadBundle\Entity\Lead;
25
26
class DecisionExecutioner implements EventInterface
27
{
28
    const TYPE = 'decision';
29
30
    /**
31
     * @var EventLogger
32
     */
33
    private $eventLogger;
34
35
    /**
36
     * @var DecisionDispatcher
37
     */
38
    private $dispatcher;
39
40
    /**
41
     * DecisionExecutioner constructor.
42
     *
43
     * @param EventLogger        $eventLogger
44
     * @param DecisionDispatcher $dispatcher
45
     */
46
    public function __construct(EventLogger $eventLogger, DecisionDispatcher $dispatcher)
47
    {
48
        $this->eventLogger = $eventLogger;
49
        $this->dispatcher  = $dispatcher;
50
    }
51
52
    /**
53
     * @param DecisionAccessor $config
54
     * @param Event            $event
55
     * @param Lead             $contact
56
     * @param mixed            $passthrough
57
     * @param string|null      $channel
58
     * @param int|null         $channelId
59
     *
60
     * @throws CannotProcessEventException
61
     * @throws DecisionNotApplicableException
62
     */
63
    public function evaluateForContact(DecisionAccessor $config, Event $event, Lead $contact, $passthrough = null, $channel = null, $channelId = null)
64
    {
65
        if (Event::TYPE_DECISION !== $event->getEventType()) {
66
            throw new CannotProcessEventException('Cannot process event ID '.$event->getId().' as a decision.');
67
        }
68
69
        $log = $this->eventLogger->buildLogEntry($event, $contact);
70
        $log->setChannel($channel)
71
            ->setChannelId($channelId);
72
73
        $decisionEvent = $this->dispatcher->dispatchRealTimeEvent($config, $log, $passthrough);
74
75
        if (!$decisionEvent->wasDecisionApplicable()) {
76
            throw new DecisionNotApplicableException('evaluation failed');
77
        }
78
79
        $this->eventLogger->persistLog($log);
80
    }
81
82
    /**
83
     * @param AbstractEventAccessor $config
84
     * @param ArrayCollection       $logs
85
     *
86
     * @return EvaluatedContacts
87
     *
88
     * @throws CannotProcessEventException
89
     */
90
    public function execute(AbstractEventAccessor $config, ArrayCollection $logs)
91
    {
92
        $evaluatedContacts = new EvaluatedContacts();
93
        $failedLogs        = [];
94
95
        /** @var LeadEventLog $log */
96
        foreach ($logs as $log) {
97
            if (Event::TYPE_DECISION !== $log->getEvent()->getEventType()) {
98
                throw new CannotProcessEventException('Event ID '.$log->getEvent()->getId().' is not a decision');
99
            }
100
101
            try {
102
                /* @var DecisionAccessor $config */
103
                $this->dispatchEvent($config, $log);
104
                $evaluatedContacts->pass($log->getLead());
105
106
                // Update the date triggered timestamp
107
                $log->setDateTriggered(new \DateTime());
108
            } catch (DecisionNotApplicableException $exception) {
109
                // Fail the contact but remove the log from being processed upstream
110
                // active/positive/green path while letting the InactiveExecutioner handle the inactive/negative/red paths
111
                $failedLogs[] = $log;
112
                $evaluatedContacts->fail($log->getLead());
113
            }
114
        }
115
116
        $this->dispatcher->dispatchDecisionResultsEvent($config, $logs, $evaluatedContacts);
117
118
        // Remove the logs
119
        foreach ($failedLogs as $log) {
120
            $logs->removeElement($log);
121
        }
122
123
        return $evaluatedContacts;
124
    }
125
126
    /**
127
     * @param DecisionAccessor $config
128
     * @param LeadEventLog     $log
129
     * @param mixed            $passthrough
130
     *
131
     * @throws DecisionNotApplicableException
132
     */
133
    private function dispatchEvent(DecisionAccessor $config, LeadEventLog $log, $passthrough = null)
134
    {
135
        $decisionEvent = $this->dispatcher->dispatchEvaluationEvent($config, $log, $passthrough);
0 ignored issues
show
The call to Mautic\CampaignBundle\Ex...spatchEvaluationEvent() has too many arguments starting with $passthrough. ( Ignorable by Annotation )

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

135
        /** @scrutinizer ignore-call */ 
136
        $decisionEvent = $this->dispatcher->dispatchEvaluationEvent($config, $log, $passthrough);

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...
136
137
        if (!$decisionEvent->wasDecisionApplicable()) {
138
            throw new DecisionNotApplicableException('evaluation failed');
139
        }
140
    }
141
}
142