Passed
Push — master ( c1f27d...16dff6 )
by Sébastien
02:29
created

Client::getClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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 81
    public function __construct(GuzzleClient $client, LoggerInterface $logger)
35
    {
36 81
        $this->client = $client;
37 81
        $this->logger = $logger;
38 81
    }
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
        return $zones->map(function (Zone $zone, $identifier) {
54 39
            return $this->delete($identifier, $zone);
55
        })->pipe(function ($promises) {
56 39
            return $this->settle($promises);
57 39
        })->wait();
58
    }
59
60
    /**
61
     * Block the given IP address.
62
     *
63
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $zones
64
     * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
65
     */
66 24
    public function blockIP($zones): Collection
67
    {
68
        return $zones->map(function (Zone $zone, $identifier) {
69 24
            return $this->client->postAsync("zones/{$identifier}/firewall/access_rules/rules", [
70 24
                \GuzzleHttp\RequestOptions::JSON => $zone,
71
            ]);
72
        })->pipe(function ($promises) {
73 24
            return $this->settle($promises);
74 24
        })->wait();
75
    }
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
        ]);
82
    }
83
84
    /**
85
     * 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 63
    protected function settle(Collection $promises): PromiseInterface
93
    {
94 63
        $results = new Collection();
95
96 63
        return Each::of(
97 63
            $promises->getIterator(),
98 63
            $this->onFulfilled($results),
99 63
            $this->onRejected($results)
100
        )->then(function () use ($results) {
101 63
            return $results;
102 63
        });
103
    }
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 63
    protected function onFulfilled(Collection $results)
112
    {
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 45
            return $results->put($identifier, $this->getBody($response));
120 63
        };
121
    }
122
123
    /**
124
     * Handle the rejected promise and put the errors into the results.
125
     *
126
     * @param  \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>  $results
127
     * @return \Closure
128
     */
129 63
    protected function onRejected(Collection $results)
130
    {
131
        /*
132
         * @param  \GuzzleHttp\Exception\RequestException $reason
133
         * @param  string                                 $identifier
134
         * @return \Illuminate\Support\Collection<string,\Sebdesign\ArtisanCloudflare\Zone>
135
         */
136
        return function ($reason, $identifier) use ($results) {
137 18
            $this->logger->error($reason->getMessage(), [
138 18
                'zone' => $identifier,
139 18
                'exception' => $reason,
140
            ]);
141
142 18
            return $results->put($identifier, $this->handleException($reason));
143 63
        };
144
    }
145
146
    /**
147
     * Transform a request exception into a result object.
148
     */
149 18
    protected function handleException(RequestException $e): Zone
150
    {
151 18
        if ($e->hasResponse()) {
152
            /** @var \Psr\Http\Message\ResponseInterface $response */
153 18
            $response = $e->getResponse();
154
155 18
            if ($e instanceof ClientException) {
156 9
                return $this->getBody($response);
157
            }
158
159 9
            $message = (string) $response->getBody();
160
        } else {
161 9
            $message = $e->getMessage();
162
        }
163
164 9
        return new Zone([
165 9
            'success' => false,
166
            'errors' => [
167
                [
168 9
                    'code' => $e->getCode(),
169 9
                    'message' => $message,
170
                ],
171
            ],
172
        ]);
173
    }
174
175
    /**
176
     * Transform the response body into a result object.
177
     */
178 54
    protected function getBody(ResponseInterface $response): Zone
179
    {
180 54
        return new Zone(json_decode($response->getBody(), true));
181
    }
182
183
    /**
184
     * Get the Guzzle client.
185
     */
186 9
    public function getClient(): GuzzleClient
187
    {
188 9
        return $this->client;
189
    }
190
}
191