Completed
Pull Request — master (#6)
by
unknown
03:48 queued 10s
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
90
        if ($params = $this->option('params')){
91
            $builder->variables(explode(',', $params));
92
        }
93
94
        if ($from = $this->option('from')) {
95
            $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

95
            $builder->from(/** @scrutinizer ignore-type */ ...array_pad(explode(':', $from), 2, null));
Loading history...
96
        }
97
98
        if ($subject = $this->option('subject')) {
99
            $builder->subject($subject);
100
        }
101
102
        if (!$this->confirm('Do you want to send ' . count($recipients) . ' emails?', true)) {
103
            return;
104
        }
105
106
        $start = time();
107
108
        $bar = $this->output->createProgressBar();
109
        $this->output->newLine('2');
110
        $bar->start(count($recipients));
111
112
        foreach ($builder->sendChunk(1000) as $response) {
113
            $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

113
            $this->parseResponse(/** @scrutinizer ignore-type */ $response);
Loading history...
114
115
            $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

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