Passed
Pull Request — master (#507)
by
unknown
02:32
created

Cloudflare::queueRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 2
b 0
f 0
nc 1
nop 5
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
/*
4
 * This file is part of the FOSHttpCache package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\HttpCache\ProxyClient;
13
14
use FOS\HttpCache\ProxyClient\Invalidation\ClearCapable;
15
use FOS\HttpCache\ProxyClient\Invalidation\PurgeCapable;
16
use FOS\HttpCache\ProxyClient\Invalidation\TagCapable;
17
18
/**
19
 * Cloudflare HTTP cache invalidator.
20
 *
21
 * Additional constructor options:
22
 * - zone_identifier       Identifier for your Cloudflare zone you want to purge the cache for
23
 * - authentication_token  API authorization token, requires Zone.Cache Purge permissions
24
 *
25
 * @author Simon Jones <[email protected]>
26
 */
27
class Cloudflare extends HttpProxyClient implements ClearCapable, PurgeCapable, TagCapable
28
{
29
    /**
30
     * @see https://api.cloudflare.com/#getting-started-endpoints
31
     */
32
    private const API_ENDPOINT = '/client/v4';
33
34
    /**
35
     * Batch URL purge limit.
36
     *
37
     * @see https://api.cloudflare.com/#zone-purge-files-by-url
38
     */
39
    private const URL_BATCH_PURGE_LIMIT = 30;
40
41
    /**
42
     * Array of data to send to Cloudflare for purge by URLs request.
43
     *
44
     * @var array
45
     */
46
    private $purgeByUrlsData = [];
47
48
    /**
49
     * JSON encode data.
50
     *
51
     * @param $data
52
     *
53
     * @return string
54
     *
55
     * @throws InvalidArgumentException
56
     */
57 3
    private function encode($data)
58
    {
59 3
        $json = json_encode($data, JSON_UNESCAPED_SLASHES);
60 3
        if (false === $json) {
61
            throw new \InvalidArgumentException(sprintf('Cannot encode "$data": %s', json_last_error_msg()));
62
        }
63
64 3
        return $json;
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     *
70
     * Tag invalidation only available with Cloudflare enterprise account
71
     *
72
     * @see https://api.cloudflare.com/#zone-purge-files-by-cache-tags,-host-or-prefix
73
     */
74 1
    public function invalidateTags(array $tags)
75
    {
76 1
        $this->queueRequest(
77 1
            'POST',
78 1
            sprintf(self::API_ENDPOINT.'/zones/%s/purge_cache', $this->options['zone_identifier']),
79 1
            [],
80 1
            false,
81 1
            $this->encode(['tags' => $tags])
82
        );
83
84 1
        return $this;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     *
90
     * @see https://api.cloudflare.com/#zone-purge-files-by-url
91
     * @see https://developers.cloudflare.com/cache/how-to/purge-cache#purge-by-single-file-by-url For details on headers you can pass to clear the cache correctly
92
     */
93 1
    public function purge($url, array $headers = [])
94
    {
95 1
        if (!empty($headers)) {
96 1
            $this->purgeByUrlsData[] = [
97 1
                'url' => $url,
98 1
                'headers' => $headers,
99
            ];
100
        } else {
101 1
            $this->purgeByUrlsData[] = $url;
102
        }
103
104 1
        return $this;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     *
110
     * @see https://api.cloudflare.com/#zone-purge-all-files
111
     */
112 1
    public function clear()
113
    {
114 1
        $this->queueRequest(
115 1
            'POST',
116 1
            sprintf(self::API_ENDPOINT.'/zones/%s/purge_cache', $this->options['zone_identifier']),
117 1
            ['Accept' => 'application/json'],
118 1
            false,
119 1
            $this->encode(['purge_everything' => true])
120
        );
121
122 1
        return $this;
123
    }
124
125
    /**
126
     * {@inheritdoc} Always provides authentication token
127
     */
128 3
    protected function queueRequest($method, $url, array $headers, $validateHost = true, $body = null)
129
    {
130 3
        parent::queueRequest(
131 3
            $method,
132
            $url,
133 3
            $headers + ['Authorization' => 'Bearer '.$this->options['authentication_token']],
134
            $validateHost,
135
            $body
136
        );
137 3
    }
138
139
    /**
140
     * {@inheritdoc} Queue requests for purge by URLs
141
     */
142 1
    public function flush()
143
    {
144
        // Queue requests for purge by URL
145 1
        foreach (\array_chunk($this->purgeByUrlsData, self::URL_BATCH_PURGE_LIMIT) as $urlChunk) {
146 1
            $this->queueRequest(
147 1
                'POST',
148 1
                sprintf(self::API_ENDPOINT.'/zones/%s/purge_cache', $this->options['zone_identifier']),
149 1
                [],
150 1
                false,
151 1
                $this->encode(['files' => $urlChunk])
152
            );
153
        }
154
155 1
        return parent::flush();
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 3
    protected function configureOptions()
162
    {
163 3
        $resolver = parent::configureOptions();
164
165 3
        $resolver->setRequired([
166 3
            'authentication_token',
167
            'zone_identifier',
168
        ]);
169
170 3
        return $resolver;
171
    }
172
}
173