Completed
Pull Request — master (#74)
by
unknown
13:23
created

Route::run()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 3
nc 4
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
            case self::TO:
87
                return $this->convertMessageAddresses($message->to());
88
            case self::CC:
89
                return $this->convertMessageAddresses($message->cc());
90
            case self::BCC:
91
                return $this->convertMessageAddresses($message->bcc());
92
            case self::SUBJECT:
93
                return [$message->subject()];
94
            default:
95
                return [];
96
        }
97
    }
98
99
    /**
100
     * @param $addresses AddressPart[]
101
     * @return array
102
     */
103
    protected function convertMessageAddresses($addresses): array
104
    {
105
        return Collection::make($addresses)
106
            ->map(function (AddressPart $address) {
107
                return $address->getEmail();
108
            })->toArray();
109
    }
110
111
    public function run(InboundEmail $email)
112
    {
113
        $this->container = $this->container ?: new Container;
114
115
        if ($this->isMailboxAction()) {
116
            $this->runMailbox($email);
117
        } else {
118
            $this->runCallable($email);
119
        }
120
    }
121
122
    protected function isMailboxAction()
123
    {
124
        return is_string($this->action);
125
    }
126
127
    protected function runMailbox(InboundEmail $email)
128
    {
129
        $method = $this->getMailboxMethod();
130
131
        $parameters = $this->resolveClassMethodDependencies(
132
            [$email] + $this->parametersWithoutNulls(), $this->getMailbox(), $method
133
        );
134
135
        return $this->getMailbox()->{$method}(...array_values($parameters));
136
    }
137
138
    protected function runCallable(InboundEmail $email)
139
    {
140
        $callable = $this->action;
141
142
        return $callable(...array_values($this->resolveMethodDependencies(
143
            [$email] + $this->parametersWithoutNulls(), new ReflectionFunction($this->action)
144
        )));
145
    }
146
147
    public function getMailbox()
148
    {
149
        if (! $this->mailbox) {
150
            $class = $this->parseMailboxCallback()[0];
151
152
            $this->mailbox = $this->container->make(ltrim($class, '\\'));
153
        }
154
155
        return $this->mailbox;
156
    }
157
158
    /**
159
     * Get the controller method used for the route.
160
     *
161
     * @return string
162
     */
163
    protected function getMailboxMethod()
164
    {
165
        return $this->parseMailboxCallback()[1] ?? '__invoke';
166
    }
167
168
    /**
169
     * Parse the controller.
170
     *
171
     * @return array
172
     */
173
    protected function parseMailboxCallback()
174
    {
175
        return Str::parseCallback($this->action);
176
    }
177
}
178