Passed
Pull Request — master (#23)
by
unknown
23:38 queued 08:28
created

Client::settle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 1
dl 0
loc 10
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sebdesign\ArtisanCloudflare;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
use GuzzleHttp\Exception\ClientException;
7
use GuzzleHttp\Exception\RequestException;
8
use GuzzleHttp\Promise\Each;
9
use GuzzleHttp\Promise\PromiseInterface;
10
use Illuminate\Support\Collection;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Log\LoggerInterface;
13
14
class Client
15
{
16
    /**
17
     * Base URI.
18
     */
19
    const BASE_URI = 'https://api.cloudflare.com/client/v4/';
20
21
    /**
22
     * @var \GuzzleHttp\Client
23
     */
24
    protected $client;
25
26
    /**
27
     * @var \Psr\Log\LoggerInterface
28
     */
29
    protected $logger;
30
31
    /**
32
     * Constructor.
33
     */
34 51
    public function __construct(GuzzleClient $client, LoggerInterface $logger)
35
    {
36 51
        $this->client = $client;
37 51
        $this->logger = $logger;
38 17
    }
39
40
    /**
41
     * Delete all the given zones with their parameters.
42
     *
43
     * All the requests are asynchronous and sent concurrently.
44
     *
45
     * The promise waits until all the promises have been resolved or rejected
46
     * and returns the results of each request.
47
     *
48
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
49
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
50
     */
51 39
    public function purge(Collection $zones): Collection
52
    {
53 26
        return $zones->map(function (Zone $zone, $identifier) {
54 39
            return $this->delete($identifier, $zone);
55 26
        })->pipe(function ($promises) {
56 39
            return $this->settle($promises);
57 39
        })->wait();
58
    }
59
60 39
    /**
61
     * Block the given IP address.
62 39
     *
63 39
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
64 26
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
65
     */
66
    public function blockIP($zones): Collection
67
    {
68
        return $zones->map(function (Zone $zone, $identifier) {
69
            return $this->client->postAsync("zones/{$identifier}/firewall/access_rules/rules", [
70
                \GuzzleHttp\RequestOptions::JSON => $zone,
71
            ]);
72
        })->pipe(function ($promises) {
73
            return $this->settle($promises);
74
        })->wait();
75 39
    }
76
77 39
    protected function delete(string $identifier, Zone $zone): PromiseInterface
78
    {
79 39
        return $this->client->deleteAsync("zones/{$identifier}/purge_cache", [
80 39
            \GuzzleHttp\RequestOptions::JSON => $zone,
81 39
        ]);
82 39
    }
83 26
84 39
    /**
85 39
     * Returns a promise that is fulfilled when all of the provided promises have
86
     * been fulfilled or rejected.
87
     *
88
     * The returned promise is fulfilled with a collection of results.
89
     *
90
     * @param  \Illuminate\Support\Collection<string,\GuzzleHttp\Promise\PromiseInterface>  $promises
91
     */
92
    protected function settle(Collection $promises): PromiseInterface
93
    {
94 39
        $results = new Collection();
95
96
        return Each::of(
97
            $promises->getIterator(),
98
            $this->onFulfilled($results),
99
            $this->onRejected($results)
100
        )->then(function () use ($results) {
101 26
            return $results;
102 27
        });
103 39
    }
104
105
    /**
106
     * Put the body of the fulfilled promise into the results.
107
     *
108
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $results
109
     * @return \Closure
110
     */
111
    protected function onFulfilled(Collection $results)
112 39
    {
113
        /*
114
         * @param  \Psr\Http\Message\ResponseInterface $response
115
         * @param  string                              $identifier
116
         * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
117
         */
118
        return function ($response, $identifier) use ($results) {
119 26
            return $results->put($identifier, $this->getBody($response));
120 12
        };
121 12
    }
122 12
123 8
    /**
124
     * Handle the rejected promise and put the errors into the results.
125 12
     *
126 39
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $results
127
     * @return \Closure
128
     */
129
    protected function onRejected(Collection $results)
130
    {
131
        /*
132 12
         * @param  \GuzzleHttp\Exception\RequestException $reason
133
         * @param  string                                 $identifier
134 12
         * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
135
         */
136 12
        return function ($reason, $identifier) use ($results) {
137
            $this->logger->error($reason->getMessage(), [
138 12
                'zone' => $identifier,
139 6
                'exception' => $reason,
140
            ]);
141
142 6
            return $results->put($identifier, $this->handleException($reason));
143
        };
144 6
    }
145
146
    /**
147 6
     * Transform a request exception into a result object.
148 6
     */
149 4
    protected function handleException(RequestException $e): Zone
150 4
    {
151 6
        if ($e->hasResponse()) {
152 6
            /** @var \Psr\Http\Message\ResponseInterface $response */
153 4
            $response = $e->getResponse();
154 4
155 4
            if ($e instanceof ClientException) {
156
                return $this->getBody($response);
157
            }
158
159
            $message = (string) $response->getBody();
160
        } else {
161 33
            $message = $e->getMessage();
162
        }
163 33
164
        return new Zone([
165
            'success' => false,
166
            'errors' => [
167
                [
168
                    'code' => $e->getCode(),
169 9
                    'message' => $message,
170
                ],
171 9
            ],
172
        ]);
173
    }
174
175
    /**
176
     * Transform the response body into a result object.
177
     */
178
    protected function getBody(ResponseInterface $response): Zone
179
    {
180
        return new Zone(json_decode($response->getBody(), true));
181
    }
182
183
    /**
184
     * Get the Guzzle client.
185
     */
186
    public function getClient(): GuzzleClient
187
    {
188
        return $this->client;
189
    }
190
}
191