Completed
Push — master ( 92bedd...993497 )
by Marcel
01:25 queued 10s
created

Route::matches()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace BeyondCode\Mailbox\Routing;
4
5
use BeyondCode\Mailbox\Concerns\HandlesParameters;
6
use BeyondCode\Mailbox\Concerns\HandlesRegularExpressions;
7
use BeyondCode\Mailbox\InboundEmail;
8
use Illuminate\Container\Container;
9
use Illuminate\Routing\RouteDependencyResolverTrait;
10
use Illuminate\Support\Collection;
11
use Illuminate\Support\Str;
12
use ReflectionFunction;
13
use ZBateson\MailMimeParser\Header\Part\AddressPart;
14
15
class Route
16
{
17
    use HandlesParameters;
18
    use HandlesRegularExpressions;
19
    use RouteDependencyResolverTrait;
20
21
    const FROM = 'from';
22
    const TO = 'to';
23
    const CC = 'cc';
24
    const BCC = 'bcc';
25
    const SUBJECT = 'subject';
26
    const FALLBACK = 'fallback';
27
    const CATCH_ALL = 'catch-all';
28
29
    protected $mailbox;
30
31
    protected $subject;
32
33
    protected $pattern;
34
35
    protected $action;
36
37
    protected $container;
38
39
    protected $matches = [];
40
41
    protected $wheres = [];
42
43
    public function __construct(string $subject, string $pattern, $action)
44
    {
45
        $this->subject = $subject;
46
        $this->pattern = $pattern;
47
        $this->action = $action;
48
    }
49
50
    public function setContainer(Container $container)
51
    {
52
        $this->container = $container;
53
54
        return $this;
55
    }
56
57
    public function subject()
58
    {
59
        return $this->subject;
60
    }
61
62
    public function action()
63
    {
64
        return $this->action;
65
    }
66
67
    public function pattern()
68
    {
69
        return $this->pattern;
70
    }
71
72
    public function matches(InboundEmail $message): bool
73
    {
74
        $subjects = $this->gatherMatchSubjectsFromMessage($message);
75
76
        return Collection::make($subjects)->first(function (string $subject) {
77
            return $this->matchesRegularExpression($subject);
78
        }) !== null;
79
    }
80
81
    protected function gatherMatchSubjectsFromMessage(InboundEmail $message)
82
    {
83
        switch ($this->subject) {
84
            case self::FROM:
85
                return [$message->from()];
86
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
87
            case self::TO:
88
                return $this->convertMessageAddresses($message->to());
89
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
90
            case self::CC:
91
                return $this->convertMessageAddresses($message->cc());
92
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
93
            case self::BCC:
94
                return $this->convertMessageAddresses($message->bcc());
95
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
96
            case self::SUBJECT:
97
                return [$message->subject()];
98
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
99
        }
100
    }
101
102
    /**
103
     * @param $addresses AddressPart[]
104
     * @return array
105
     */
106
    protected function convertMessageAddresses($addresses): array
107
    {
108
        return Collection::make($addresses)
109
            ->map(function (AddressPart $address) {
110
                return $address->getEmail();
111
            })->toArray();
112
    }
113
114
    public function run(InboundEmail $email)
115
    {
116
        $this->container = $this->container ?: new Container;
117
118
        if ($this->isMailboxAction()) {
119
            $this->runMailbox($email);
120
        } else {
121
            $this->runCallable($email);
122
        }
123
    }
124
125
    protected function isMailboxAction()
126
    {
127
        return is_string($this->action);
128
    }
129
130
    protected function runMailbox(InboundEmail $email)
131
    {
132
        $method = $this->getMailboxMethod();
133
134
        $parameters = $this->resolveClassMethodDependencies(
135
            [$email] + $this->parametersWithoutNulls(), $this->getMailbox(), $method
136
        );
137
138
        return $this->getMailbox()->{$method}(...array_values($parameters));
139
    }
140
141
    protected function runCallable(InboundEmail $email)
142
    {
143
        $callable = $this->action;
144
145
        return $callable(...array_values($this->resolveMethodDependencies(
146
            [$email] + $this->parametersWithoutNulls(), new ReflectionFunction($this->action)
147
        )));
148
    }
149
150
    public function getMailbox()
151
    {
152
        if (! $this->mailbox) {
153
            $class = $this->parseMailboxCallback()[0];
154
155
            $this->mailbox = $this->container->make(ltrim($class, '\\'));
156
        }
157
158
        return $this->mailbox;
159
    }
160
161
    /**
162
     * Get the controller method used for the route.
163
     *
164
     * @return string
165
     */
166
    protected function getMailboxMethod()
167
    {
168
        return $this->parseMailboxCallback()[1] ?? '__invoke';
169
    }
170
171
    /**
172
     * Parse the controller.
173
     *
174
     * @return array
175
     */
176
    protected function parseMailboxCallback()
177
    {
178
        return Str::parseCallback($this->action);
179
    }
180
}
181