Completed
Pull Request — master (#6)
by
unknown
03:18
created

Send::handle()   B

Complexity

Conditions 7
Paths 26

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 26
c 1
b 0
f 0
nc 26
nop 0
dl 0
loc 48
ccs 0
cts 27
cp 0
crap 56
rs 8.5706
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
                           {--c|context=      : The list of context variables }
30
                           {--f|from=         : The sender email address and name }
31
                           {--apiToken=       : The Mandrill API token }
32
                           {--s|subject=      : The message subject }';
33
34
    /**
35
     * The console command description.
36
     *
37
     * @var string
38
     */
39
    protected $description = 'Send a new transactional message through Mandrill using a template.';
40
41
    /**
42
     * @var Client
43
     */
44
    protected $client;
45
46
    /**
47
     * @var array
48
     */
49
    protected $result = [
50
        'requests' => 0,
51
        'emails' => 0,
52
        'success' => 0,
53
        'failed' => [],
54
        'responses' => null
55
    ];
56
57
    /**
58
     * @var Mailer
59
     */
60
    protected $mailer;
61
62
    public function __construct(Mailer $mailer)
63
    {
64
        $this->mailer = $mailer;
65
66
        parent::__construct();
67
    }
68
69
    /**
70
     * Execute the console command.
71
     *
72
     * @return void|null
73
     *
74
     * @throws Exception
75
     */
76
    public function handle()
77
    {
78
        $recipients = $this->resolveRecipients();
79
80
        if ($secret = $this->option('apiToken')) {
81
            $this->mailer = $this->mailer->setToken($secret);
82
        }
83
84
        if (!$template = $this->option('template')) {
85
            throw new Exception('Please, pass the --template option');
86
        }
87
88
        $builder = $this->mailer->template($template)
89
            ->recipients($recipients)
90
            ->variables(ConsoleHelper::stringToArray($this->option('params')))
91
            ->context(ConsoleHelper::stringToArray($this->option('context')));
92
93
        if ($from = $this->option('from')) {
94
            $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

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

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

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