EmailController   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
c 1
b 0
f 0
lcom 1
cbo 8
dl 0
loc 152
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
B run() 0 97 6
A addMessageStrategy() 0 15 1
A getEventDispatcher() 0 4 1
A on() 0 4 1
A error() 0 4 1
A success() 0 4 1
1
<?php
2
3
namespace AramisAuto\EmailController;
4
5
use AramisAuto\EmailController\Event\ErrorEvent;
6
use AramisAuto\EmailController\Event\MessageEvent;
7
use AramisAuto\EmailController\Exception\NoMessageStrategyException;
8
use AramisAuto\EmailController\MessageStrategy\AbstractMessageStrategy;
9
use Psr\Log\LoggerAwareInterface;
10
use Psr\Log\LoggerAwareTrait;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
use Symfony\Component\EventDispatcher\EventDispatcher;
14
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
15
16
class EmailController implements LoggerAwareInterface
17
{
18
    use LoggerAwareTrait;
19
20
    private $eventDispatcher;
21
    private $payloadDecoder;
22
    private $messageStrategies = array();
23
24
    public function __construct(PayloadDecoder\PayloadDecoderInterface $payloadDecoder, LoggerInterface $logger = null)
25
    {
26
        $this->eventDispatcher = new EventDispatcher();
27
        $this->payloadDecoder = $payloadDecoder;
28
        if (is_null($logger)) {
29
            $logger = new NullLogger();
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $logger. This often makes code more readable.
Loading history...
30
        }
31
        $this->setLogger($logger);
32
    }
33
34
    public function run($payload)
35
    {
36
        // Decode payload
37
        $this->logger->info(
38
            'Using payload decoder',
39
            array('payloadDecoder' => get_class($this->payloadDecoder))
40
        );
41
        $messages = $this->payloadDecoder->decode($payload);
42
43
        $this->logger->info('Decoded payload', $messages);
44
45
        // Execute applicable message strategies
46
        foreach ($messages as $message) {
47
            $matched = false;
48
            $language = new ExpressionLanguage();
49
            foreach ($this->messageStrategies as $expression => $spec) {
50
                // Log
51
                $this->logger->info(
52
                    'Evaluating expression against message',
53
                    array(
54
                        'expression' => $expression,
55
                        'messageId' => $message->id,
56
                    )
57
                );
58
                $this->logger->debug(
59
                    'Evaluating expression against message',
60
                    array(
61
                        'expression' => $expression,
62
                        'message' => $message,
63
                        'messageId' => $message->id,
64
                    )
65
                );
66
67
                // Evaluate expression against message
68
                if ($language->evaluate($expression, array('message' => $message))) {
69
                    $matched = true;
70
71
                    // Instanciate strategy
72
                    $strategy = $spec[0];
73
                    $strategy->setMessage($message);
74
75
                    // Log
76
                    $this->logger->info(
77
                        'Expression matched, executing related strategy',
78
                        array(
79
                            'expression' => $expression,
80
                            'strategy' => get_class($strategy),
81
                            'messageId' => $message->id,
82
                        )
83
                    );
84
85
                    // Global success event
86
                    $strategy->on($strategy->success(), function (MessageEvent $event) use ($strategy) {
87
                        $this->logger->info(
88
                            'Strategy execution succeeded',
89
                            array(
90
                                'strategy' => get_class($strategy),
91
                                'messageId' => $strategy->getMessage()->id,
92
                            )
93
                        );
94
                        $this->getEventDispatcher()->dispatch($this->success(), $event);
95
                    });
96
97
                    // Global error event
98
                    $strategy->on($strategy->error(), function (ErrorEvent $event) use ($strategy) {
99
                        $this->logger->info(
100
                            'Strategy execution failed',
101
                            array(
102
                                'strategy' => get_class($strategy),
103
                                'messageId' => $strategy->getMessage()->id,
104
                                'error' => $event->getError(),
105
                            )
106
                        );
107
                        $this->getEventDispatcher()->dispatch($this->error(), $event);
108
                    });
109
110
                    // Execute strategy
111
                    $strategy->execute();
112
113
                    // Continue to search for strategies applicable to message ?
114
                    if ($spec[1] !== true) {
115
                        break;
116
                    }
117
                }
118
            }
119
120
            // Throw an error if no appropriate strategy was found
121
            if (!$matched) {
122
                throw new NoMessageStrategyException(
123
                    sprintf(
124
                        'No applicable strategy found for message - %s',
125
                        json_encode(array('message' => $message), JSON_UNESCAPED_SLASHES)
126
                    )
127
                );
128
            }
129
        }
130
    }
131
132
    public function addMessageStrategy($expression, AbstractMessageStrategy $strategy, $continue = false)
133
    {
134
        // Configure strategy
135
        $strategy->setEventDispatcher($this->getEventDispatcher());
136
        $strategy->setLogger($this->logger);
137
138
        // Store strategy
139
        $this->messageStrategies[$expression] = array($strategy, $continue);
140
141
        // Log
142
        $this->logger->info(
143
            'Added message strategy rule',
144
            array('expression' => $expression, 'strategy' => get_class($strategy))
145
        );
146
    }
147
148
    protected function getEventDispatcher()
149
    {
150
        return $this->eventDispatcher;
151
    }
152
153
    public function on($eventName, $callback)
154
    {
155
        $this->getEventDispatcher()->addListener($eventName, $callback);
156
    }
157
158
    public function error()
159
    {
160
        return 'emailcontroller.error';
161
    }
162
163
    public function success()
164
    {
165
        return 'emailcontroller.success';
166
    }
167
}
168