Issues (3627)

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
    public function __construct(EventLogger $eventLogger, DecisionDispatcher $dispatcher)
44
    {
45
        $this->eventLogger = $eventLogger;
46
        $this->dispatcher  = $dispatcher;
47
    }
48
49
    /**
50
     * @param mixed       $passthrough
51
     * @param string|null $channel
52
     * @param int|null    $channelId
53
     *
54
     * @throws CannotProcessEventException
55
     * @throws DecisionNotApplicableException
56
     */
57
    public function evaluateForContact(DecisionAccessor $config, Event $event, Lead $contact, $passthrough = null, $channel = null, $channelId = null)
58
    {
59
        if (Event::TYPE_DECISION !== $event->getEventType()) {
60
            throw new CannotProcessEventException('Cannot process event ID '.$event->getId().' as a decision.');
61
        }
62
63
        $log = $this->eventLogger->buildLogEntry($event, $contact);
64
        $log->setChannel($channel)
65
            ->setChannelId($channelId);
66
67
        $decisionEvent = $this->dispatcher->dispatchRealTimeEvent($config, $log, $passthrough);
68
69
        if (!$decisionEvent->wasDecisionApplicable()) {
70
            throw new DecisionNotApplicableException('evaluation failed');
71
        }
72
73
        $this->eventLogger->persistLog($log);
74
    }
75
76
    /**
77
     * @return EvaluatedContacts
78
     *
79
     * @throws CannotProcessEventException
80
     */
81
    public function execute(AbstractEventAccessor $config, ArrayCollection $logs)
82
    {
83
        $evaluatedContacts = new EvaluatedContacts();
84
        $failedLogs        = [];
85
86
        /** @var LeadEventLog $log */
87
        foreach ($logs as $log) {
88
            if (Event::TYPE_DECISION !== $log->getEvent()->getEventType()) {
89
                throw new CannotProcessEventException('Event ID '.$log->getEvent()->getId().' is not a decision');
90
            }
91
92
            try {
93
                /* @var DecisionAccessor $config */
94
                $this->dispatchEvent($config, $log);
95
                $evaluatedContacts->pass($log->getLead());
96
97
                // Update the date triggered timestamp
98
                $log->setDateTriggered(new \DateTime());
99
            } catch (DecisionNotApplicableException $exception) {
100
                // Fail the contact but remove the log from being processed upstream
101
                // active/positive/green path while letting the InactiveExecutioner handle the inactive/negative/red paths
102
                $failedLogs[] = $log;
103
                $evaluatedContacts->fail($log->getLead());
104
            }
105
        }
106
107
        $this->dispatcher->dispatchDecisionResultsEvent($config, $logs, $evaluatedContacts);
108
109
        // Remove the logs
110
        foreach ($failedLogs as $log) {
111
            $logs->removeElement($log);
112
        }
113
114
        return $evaluatedContacts;
115
    }
116
117
    /**
118
     * @param mixed $passthrough
119
     *
120
     * @throws DecisionNotApplicableException
121
     */
122
    private function dispatchEvent(DecisionAccessor $config, LeadEventLog $log, $passthrough = null)
123
    {
124
        $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

124
        /** @scrutinizer ignore-call */ 
125
        $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...
125
126
        if (!$decisionEvent->wasDecisionApplicable()) {
127
            throw new DecisionNotApplicableException('evaluation failed');
128
        }
129
    }
130
}
131