Purge::applyParameters()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 14
ccs 8
cts 8
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sebdesign\ArtisanCloudflare\Commands\Cache;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Collection;
7
use Sebdesign\ArtisanCloudflare\Client;
8
use Sebdesign\ArtisanCloudflare\Zone;
9
use Symfony\Component\Console\Helper\TableCell;
10
use Symfony\Component\Console\Helper\TableSeparator;
11
12
class Purge extends Command
13
{
14
    /**
15
     * The name of the console command.
16
     *
17
     * @var string
18
     */
19
    protected $name = 'cloudflare:cache:purge';
20
21
    /**
22
     * The name and signature of the console command.
23
     *
24
     * @var string
25
     */
26
    protected $signature = 'cloudflare:cache:purge {zone? : A zone identifier.}
27
      {--file=* : One or more files that should be removed from the cache.}
28
      {--tag=* : One or more tags that should be removed from the cache.}
29
      {--host=* : One or more hosts that should be removed from the cache.}';
30
31
    /**
32
     * The name and signature of the console command.
33
     *
34
     * @var string
35
     */
36
    protected $description = 'Purge files/tags from CloudFlare\'s cache.';
37
38
    /**
39
     * CloudFlare API client.
40
     *
41
     * @var \Sebdesign\ArtisanCloudflare\Client
42
     */
43
    private $client;
44
45
    /**
46
     * API item identifier tags.
47
     *
48
     * @var \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
49
     */
50
    private $zones;
51
52
    /**
53
     * Purge constructor.
54
     */
55 63
    public function __construct(array $zones)
56
    {
57 63
        parent::__construct();
58
59
        $this->zones = Collection::make($zones)->map(function (array $zone) {
60 57
            return new Zone(array_filter($zone));
61 63
        });
62 63
    }
63
64
    /**
65
     * Execute the console command.
66
     *
67
     * @param  \Sebdesign\ArtisanCloudflare\Client  $client
68
     * @return int
69
     */
70 33
    public function handle(Client $client)
71
    {
72 33
        $this->client = $client;
73
74 33
        $zones = $this->getZones();
75
76 33
        if ($zones->isEmpty()) {
77 3
            $this->error('Please supply a valid zone identifier in the input argument or the cloudflare config.');
78
79 3
            return 1;
80
        }
81
82 30
        $zones = $this->applyParameters($zones);
83
84 30
        $results = $this->purge($zones);
85
86 30
        $this->displayResults($zones, $results);
87
88 30
        return $this->getExitCode($results);
89
    }
90
91
    /**
92
     * Apply the paremeters for each zone.
93
     *
94
     * Use the config for each zone, unless options are passed in the command.
95
     *
96
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
97
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
98
     */
99 30
    private function applyParameters(Collection $zones): Collection
100
    {
101 30
        $defaults = array_filter([
102 30
            'files' => $this->option('file'),
103 30
            'tags' => $this->option('tag'),
104 30
            'hosts' => $this->option('host'),
105
        ]);
106
107 30
        if (empty($defaults)) {
108 15
            return $zones;
109
        }
110
111
        return $zones->each(function (Zone $zone) use ($defaults) {
112 15
            $zone->replace($defaults);
113 15
        });
114
    }
115
116
    /**
117
     * Execute the purging operations and return each result.
118
     *
119
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
120
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
121
     */
122 30
    private function purge(Collection $zones): Collection
123
    {
124 30
        $results = $this->client->purge($zones);
125
126 30
        return $results->reorder($zones->keys());
127
    }
128
129
    /**
130
     * Display a table with the results.
131
     *
132
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
133
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $results
134
     * @return void
135
     */
136 30
    private function displayResults(Collection $zones, Collection $results): void
137
    {
138 30
        $headers = ['Status', 'Zone', 'Files', 'Tags', 'Hosts', 'Errors'];
139
140
        $title = [
141 30
            new TableCell(
142 30
                'The following zones have been purged from CloudFlare.',
143 30
                ['colspan' => count($headers)]
144
            ),
145
        ];
146
147
        // Get the status emoji
148
        $emoji = $results->map(function (Zone $zone) {
149 30
            return $zone->get('success') ? '✅' : '❌';
150 30
        });
151
152
        // Get the zone identifiers
153 30
        $identifiers = $zones->keys();
154
155
        // Get the files as multiline strings
156
        $files = $zones->map(function (Zone $zone) {
157 30
            return $this->formatItems($zone->get('files', []));
158 30
        });
159
160
        // Get the tags as multiline strings
161
        $tags = $zones->map(function (Zone $zone) {
162 30
            return $this->formatItems($zone->get('tags', []));
163 30
        });
164
165
        // Get the hosts as multiline strings
166
        $hosts = $zones->map(function (Zone $zone) {
167 30
            return $this->formatItems($zone->get('hosts', []));
168 30
        });
169
170
        // Get the errors as red multiline strings
171
        $errors = $results->map(function (Zone $result) {
172 30
            return $this->formatErrors($result->get('errors', []));
173
        })->map(function (array $errors) {
174 30
            return $this->formatItems($errors);
175 30
        });
176
177 30
        $columns = Collection::make([
178 30
            'status' => $emoji,
179 30
            'identifier' => $identifiers,
180 30
            'files' => $files,
181 30
            'tags' => $tags,
182 30
            'hosts' => $hosts,
183 30
            'errors' => $errors,
184
        ]);
185
186 30
        $rows = $columns->_transpose()->insertBetween(new TableSeparator());
187
188 30
        $this->table([$title, $headers], $rows);
189 30
    }
190
191
    /**
192
     * Format an array into a multiline string.
193
     */
194 30
    private function formatItems(array $items): string
195
    {
196 30
        return implode("\n", $items);
197
    }
198
199
    /**
200
     * Format the errors.
201
     *
202
     * @param  array[]  $errors
203
     * @return string[]
204
     */
205 30
    private function formatErrors(array $errors): array
206
    {
207
        return array_map(function (array $error) {
208 6
            if (isset($error['code'])) {
209 6
                return "<fg=red>{$error['code']}: {$error['message']}</>";
210
            }
211
212 3
            return "<fg=red>{$error['message']}</>";
213 30
        }, $errors);
214
    }
215
216
    /**
217
     * Get the zone identifier from the input argument or the configuration.
218
     *
219
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
220
     */
221 33
    private function getZones(): Collection
222
    {
223 33
        if (! $zone = $this->argument('zone')) {
224 24
            return $this->zones;
225
        }
226
227 9
        $zones = $this->zones->only($zone);
228
229 9
        if ($zones->count()) {
230 3
            return $zones;
231
        }
232
233 6
        return new Collection([
234 6
            $zone => new Zone(),
235
        ]);
236
    }
237
238
    /**
239
     * Return 1 if all successes are false, otherwise return 0.
240
     *
241
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $results
242
     */
243 30
    private function getExitCode(Collection $results): int
244
    {
245
        return (int) $results->filter(function (Zone $zone) {
246 30
            return $zone->get('success');
247 30
        })->isEmpty();
248
    }
249
}
250