Passed
Pull Request — master (#6)
by
unknown
03:19
created

Send::resolveRecipients()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 9
ccs 0
cts 6
cp 0
crap 12
rs 10
1
<?php
2
3
namespace Slides\Connector\Auth\Clients\Mandrill\Commands;
4
5
use Exception;
6
use Illuminate\Console\Command;
7
use Illuminate\Support\Fluent;
8
use Illuminate\Support\Str;
9
use Slides\Connector\Auth\Clients\Mandrill\Client;
10
use Slides\Connector\Auth\Clients\Mandrill\Mailer;
11
use Slides\Connector\Auth\Helpers\ConsoleHelper;
12
13
/**
14
 * Class Send
15
 *
16
 * @package Slides\Connector\Auth\Clients\Mandrill\Commands
17
 */
18
class Send extends Command
19
{
20
    /**
21
     * The name and signature of the console command.
22
     *
23
     * @var string
24
     */
25
    protected $signature = 'mandrill:send
26
                           {--r|recipients=   : The list of recipients or name of the file with recipients }
27
                           {--t|template=     : Name of the email template }
28
                           {--p|params=       : The list of parameters for an email }
29
                           {--f|from=         : The sender email address and name }
30
                           {--apiToken=       : The Mandrill API token }
31
                           {--s|subject=      : The message subject }';
32
33
    /**
34
     * The console command description.
35
     *
36
     * @var string
37
     */
38
    protected $description = 'Send a new transactional message through Mandrill using a template.';
39
40
    /**
41
     * @var Client
42
     */
43
    protected $client;
44
45
    /**
46
     * @var array
47
     */
48
    protected $result = [
49
        'requests' => 0,
50
        'emails' => 0,
51
        'success' => 0,
52
        'failed' => [],
53
        'responses' => null
54
    ];
55
56
    /**
57
     * @var Mailer
58
     */
59
    protected $mailer;
60
61
    public function __construct(Mailer $mailer)
62
    {
63
        $this->mailer = $mailer;
64
65
        parent::__construct();
66
    }
67
68
    /**
69
     * Execute the console command.
70
     *
71
     * @return void|null
72
     *
73
     * @throws Exception
74
     */
75
    public function handle()
76
    {
77
        $recipients = $this->resolveRecipients();
78
79
        if ($secret = $this->option('apiToken')) {
80
            $this->mailer = $this->mailer->setToken($secret);
81
        }
82
83
        if (!$template = $this->option('template')) {
84
            throw new Exception('Please, pass the --template option');
85
        }
86
87
        $builder = $this->mailer->template($template)
88
            ->recipients($recipients)
89
            ->variables(ConsoleHelper::stringToArray($this->option('params')));
90
91
        if ($from = $this->option('from')) {
92
            $builder->from(...array_pad(explode(':', $from), 2, null));
0 ignored issues
show
Bug introduced by
array_pad(explode(':', $from), 2, null) is expanded, but the parameter $email of Slides\Connector\Auth\Cl...\Builders\Email::from() does not expect variable arguments. ( Ignorable by Annotation )

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

92
            $builder->from(/** @scrutinizer ignore-type */ ...array_pad(explode(':', $from), 2, null));
Loading history...
93
        }
94
95
        if ($subject = $this->option('subject')) {
96
            $builder->subject($subject);
97
        }
98
99
        if (!$this->confirm('Do you want to send ' . count($recipients) . ' emails?', true)) {
100
            return;
101
        }
102
103
        $start = time();
104
105
        $bar = $this->output->createProgressBar();
106
        $this->output->newLine('2');
107
        $bar->start(count($recipients));
108
109
        foreach ($builder->sendChunk(1000) as $response) {
110
            $this->parseResponse($response);
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type null and string; however, parameter $response of Slides\Connector\Auth\Cl...s\Send::parseResponse() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

110
            $this->parseResponse(/** @scrutinizer ignore-type */ $response);
Loading history...
111
112
            $bar->advance(count($response));
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type string; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

112
            $bar->advance(count(/** @scrutinizer ignore-type */ $response));
Loading history...
113
        }
114
115
        $bar->finish();
116
117
        $this->output->newLine(2);
118
119
        $this->result['spent'] = time() - $start;
120
121
        $this->printResult(new Fluent($this->result));
122
    }
123
124
    /**
125
     * Resolve email recipients.
126
     *
127
     * @return array|null
128
     *
129
     * @throws Exception
130
     */
131
    protected function resolveRecipients(): ?array
132
    {
133
        if (!$option = $this->option('recipients')) {
134
            throw new Exception('Please, pass the --recipients option');
135
        }
136
137
        return Str::contains($option, '@')
138
            ? ConsoleHelper::stringToArray($option)
139
            : explode(PHP_EOL, file_get_contents($option));
140
    }
141
142
    /**
143
     * Parse Mandrill response.
144
     *
145
     * @param array $response
146
     *
147
     * @return void
148
     */
149
    protected function parseResponse(array $response): void
150
    {
151
        $result = collect($response);
152
153
        $this->result['requests']++;
154
        $this->result['emails'] += $result->count();
155
        $this->result['success'] += $result->whereNotIn('status', ['rejected', 'invalid'])->count();
156
157
        $this->result['failed'] = $result->whereIn('status', ['rejected', 'invalid'])->pluck('email')->merge($this->result['failed'])->toArray();
158
        $this->result['responses'] .= json_encode($response) . PHP_EOL;
159
    }
160
161
    /**
162
     * Print the result of execution.
163
     *
164
     * @param Fluent $result
165
     *
166
     * @return void
167
     */
168
    protected function printResult(Fluent $result): void
169
    {
170
        $this->warn('######################################################');
171
172
        $this->comment('Number of requests: ' . $result->get('requests'));
173
        $this->comment('Number of emails: ' . $result->get('emails'));
174
        $this->comment('Success: ' . $result->get('success'));
175
        $this->comment('Total time spent: ' . $result->get('spent') . 's');
176
177
        if ($failed = $result->get('failed')) {
178
            $filename = 'mandrill_failed_emails_' . time() . '.log';
179
180
            file_put_contents(storage_path('logs/' . $filename), implode(PHP_EOL, $failed));
181
182
            $this->output->newLine();
183
            $this->error('Failed emails saved to ' . $filename);
184
        }
185
186
        $responsesFilename = 'mandrill_responses_' . time() . '.log';
187
188
        file_put_contents(storage_path('logs/' . $responsesFilename), $result->get('responses'));
189
190
        $this->info('Responses saved to ' . $responsesFilename);
191
    }
192
}