Skip to content

Commit e4eac37

Browse files
committed
Add requests rate control, findOrCreate method, simple cache layer, fix namespace
1 parent 8f6f215 commit e4eac37

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/Webflow/Api.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ class Api {
1212
private $client;
1313
private $token;
1414

15+
private $requests;
16+
private $start;
17+
private $finish;
18+
19+
private $cache = [];
20+
1521
function __construct(
1622
$token,
1723
$version = '1.0.0'
@@ -23,10 +29,17 @@ function __construct(
2329
$this->token = $token;
2430
$this->version = $version;
2531

32+
$this->rateRemaining = 60;
33+
2634
return $this;
2735
}
2836

2937
private function request(string $path, string $method, array $data = []) {
38+
if ($this->rateRemaining <= 1) {
39+
$sec = 60 + 30;
40+
// echo "Sleeping {$sec}s, X-RateLimit-Remaining: {$this->rateRemaining}", PHP_EOL;
41+
sleep($sec);
42+
}
3043
$curl = curl_init();
3144
$options = [
3245
CURLOPT_URL => self::WEBFLOW_API_ENDPOINT . $path,
@@ -38,6 +51,7 @@ private function request(string $path, string $method, array $data = []) {
3851
"Accept: application/json",
3952
"Content-Type: application/json",
4053
],
54+
CURLOPT_HEADER => true,
4155
CURLOPT_RETURNTRANSFER => true,
4256
];
4357
if (!empty($data)) {
@@ -48,7 +62,21 @@ private function request(string $path, string $method, array $data = []) {
4862
curl_setopt_array($curl, $options);
4963
$response = curl_exec($curl);
5064
curl_close($curl);
51-
return $this->parse($response);
65+
list($headers, $body) = explode("\r\n\r\n", $response, 2);
66+
$headers = explode(PHP_EOL, $headers);
67+
foreach($headers as $header) {
68+
if (strpos($header, ': ') > 0) {
69+
list($headerName, $headerValue) = explode(': ', $header, 2);
70+
if ($headerName == 'X-RateLimit-Limit') {
71+
$rateLimit = $headerValue;
72+
}
73+
if ($headerName == 'X-RateLimit-Remaining') {
74+
$rateRemaining = intval($headerValue);
75+
}
76+
}
77+
}
78+
$this->rateRemaining = $rateRemaining ?? $this->rateRemaining - 1;
79+
return $this->parse($body);
5280

5381
}
5482
private function get($path) {
@@ -68,7 +96,15 @@ private function delete($path, $data) {
6896
}
6997

7098
private function parse($response) {
71-
return json_decode($response);
99+
$json = json_decode($response);
100+
if (isset($json->code) && isset($json->msg)) {
101+
$error = $json->msg;
102+
if (isset($json->problems)) {
103+
$error .= PHP_EOL . implode(PHP_EOL, $json->problems);
104+
}
105+
throw new \Exception($error, $json->code);
106+
}
107+
return $json;
72108
}
73109
// Meta
74110

@@ -130,4 +166,34 @@ public function removeItem(string $collectionId, $itemId) {
130166
return $this->delete("/collections/{$collectionId}/items/{$itemId}");
131167
}
132168

169+
public function findOrCreateItemByName(string $collectionId, array $fields) {
170+
if (!isset($fields['name'])) {
171+
throw new WebflowException('name');
172+
}
173+
$cacheKey = "collection-{$collectionId}-items";
174+
$instance = $this;
175+
$items = $this->cache($cacheKey, function () use ($instance, $collectionId) {
176+
return $instance->items($collectionId)->items;
177+
});
178+
foreach ($items as $item) {
179+
if (strcasecmp($item->name, $fields['name']) === 0) {
180+
return $item;
181+
}
182+
}
183+
$newItem = $this->createItem($collectionId, $fields);
184+
$items[] = $newItem;
185+
$this->cacheSet($cacheKey, $items);
186+
return $newItem;
187+
}
188+
189+
private function cache($key, callable $callback) {
190+
if (!isset($this->cache[$key])) {
191+
$this->cache[$key] = $callback();
192+
}
193+
return $this->cache[$key];
194+
}
195+
196+
private function cacheSet($key, $value) {
197+
$this->cache[$key] = $value;
198+
}
133199
}

src/Webflow/WebflowException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
namespace Webflow;
4+
35
class WebflowException extends Exception {
46
public function __construct(string $argument){
57
$this->message = "Argument '{$argument}' is required but was not present";

0 commit comments

Comments
 (0)