1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Tapp\Airtable\Api; |
4
|
|
|
|
5
|
|
|
use GuzzleHttp\Client; |
6
|
|
|
use Illuminate\Support\Str; |
7
|
|
|
|
8
|
|
|
class AirtableApiClient implements ApiClient |
9
|
|
|
{ |
10
|
|
|
private $client; |
11
|
|
|
|
12
|
|
|
private $base; |
13
|
|
|
private $table; |
14
|
|
|
|
15
|
|
|
private $filters = []; |
16
|
|
|
private $pageSize = 100; |
17
|
|
|
private $maxRecords = 100; |
18
|
|
|
|
19
|
|
|
public function __construct($base, $table, $access_token, Client $client = null) |
20
|
|
|
{ |
21
|
|
|
$this->base = $base; |
22
|
|
|
$this->table = $table; |
23
|
|
|
$this->client = $client ?? $this->buildClient($access_token) ; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
private function buildClient($access_token) |
27
|
|
|
{ |
28
|
|
|
$stack = \GuzzleHttp\HandlerStack::create(); |
29
|
|
|
$stack->push( |
30
|
|
|
\GuzzleHttp\Middleware::log( |
31
|
|
|
new \Monolog\Logger('Logger'), |
32
|
|
|
new \GuzzleHttp\MessageFormatter('{request} >>> {res_body}') |
33
|
|
|
) |
34
|
|
|
); |
35
|
|
|
|
36
|
|
|
return new Client([ |
37
|
|
|
'base_uri' => 'https://api.airtable.com', |
38
|
|
|
'headers' => [ |
39
|
|
|
'Authorization' => "Bearer {$access_token}", |
40
|
|
|
'content-type' => 'application/json', |
41
|
|
|
], |
42
|
|
|
// uncomment to log requests |
43
|
|
|
'handler' => $stack, |
44
|
|
|
]); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public function addFilter($column, $operation, $value) |
48
|
|
|
{ |
49
|
|
|
$this->filters [] = "{{$column}}{$operation}\"{$value}\""; |
50
|
|
|
|
51
|
|
|
return $this; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function table($table) |
55
|
|
|
{ |
56
|
|
|
$this->table = $table; |
57
|
|
|
|
58
|
|
|
return $this; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
public function get(?string $id = null) |
62
|
|
|
{ |
63
|
|
|
$url = $this->getEndpointUrl($id); |
64
|
|
|
|
65
|
|
|
return $this->decodeResponse($this->client->get($url)); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
public function getAllPages() |
69
|
|
|
{ |
70
|
|
|
$url = $this->getEndpointUrl(); |
71
|
|
|
|
72
|
|
|
$response = $this->client->get($url, [ |
73
|
|
|
'query' => [ |
74
|
|
|
'pageSize' => $this->pageSize, |
75
|
|
|
'maxRecords' => $this->maxRecords, |
76
|
|
|
], |
77
|
|
|
]); |
78
|
|
|
|
79
|
|
|
//TODO: loop through offset to get more than one page when more than 100 records exist |
80
|
|
|
|
81
|
|
|
return $this->decodeResponse($response); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
public function post($contents = null) |
85
|
|
|
{ |
86
|
|
|
$url = $this->getEndpointUrl(); |
87
|
|
|
|
88
|
|
|
$params = ['json' => ['fields' => (object) $contents]]; |
89
|
|
|
|
90
|
|
|
return $this->decodeResponse($this->client->post($url, $params)); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
public function put(string $id, $contents = null) |
94
|
|
|
{ |
95
|
|
|
$url = $this->getEndpointUrl($id); |
96
|
|
|
|
97
|
|
|
$params = ['json' => ['fields' => (object) $contents]]; |
98
|
|
|
|
99
|
|
|
return $this->decodeResponse($this->client->put($url, $params)); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
public function patch(string $id, $contents = null) |
103
|
|
|
{ |
104
|
|
|
$url = $this->getEndpointUrl($id); |
105
|
|
|
|
106
|
|
|
$params = ['json' => ['fields' => (object) $contents]]; |
107
|
|
|
|
108
|
|
|
return $this->decodeResponse($this->client->patch($url, $params)); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
public function delete(string $id) |
112
|
|
|
{ |
113
|
|
|
$url = $this->getEndpointUrl($id); |
114
|
|
|
|
115
|
|
|
return $this->decodeResponse($this->client->delete($url)); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
public function responseToJson($response) |
119
|
|
|
{ |
120
|
|
|
$body = (string) $response->getBody(); |
121
|
|
|
|
122
|
|
|
return $body; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
public function responseToCollection($response) |
126
|
|
|
{ |
127
|
|
|
$body = (string) $response->getBody(); |
128
|
|
|
|
129
|
|
|
if ($body === '') { |
130
|
|
|
return collect([]); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$object = json_decode($body); |
134
|
|
|
|
135
|
|
|
return isset($object->records) ? collect($object->records) : $object; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
public function decodeResponse($response) |
139
|
|
|
{ |
140
|
|
|
$body = (string) $response->getBody(); |
141
|
|
|
|
142
|
|
|
if ($body === '') { |
143
|
|
|
return []; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
return json_decode($body, true); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
protected function getEndpointUrl(?string $id = null): string |
150
|
|
|
{ |
151
|
|
|
if ($id) { |
152
|
|
|
$url = '/v0/~/~/~'; |
153
|
|
|
|
154
|
|
|
return Str::replaceArray('~', [ |
155
|
|
|
$this->base, |
156
|
|
|
$this->table, |
157
|
|
|
$id, |
158
|
|
|
], $url); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
$url = '/v0/~/~'; |
162
|
|
|
|
163
|
|
|
$url = Str::replaceArray('~', [ |
164
|
|
|
$this->base, |
165
|
|
|
$this->table |
166
|
|
|
], $url); |
167
|
|
|
|
168
|
|
|
if ($this->filters) { |
|
|
|
|
169
|
|
|
$url .= '?' . http_build_query([ |
170
|
|
|
'filterByFormula' => implode('&', $this->filters), |
171
|
|
|
]); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return $url; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.