bristol-su /
airtable
| 1 | <?php |
||||
| 2 | |||||
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||||
| 3 | namespace BristolSU\AirTable; |
||||
| 4 | |||||
| 5 | use GuzzleHttp\Psr7\Response; |
||||
| 6 | use Psr\Http\Message\ResponseInterface; |
||||
| 7 | |||||
| 8 | class AirTable |
||||
|
0 ignored issues
–
show
|
|||||
| 9 | { |
||||
| 10 | |||||
| 11 | /** |
||||
| 12 | * The ID of the Progress base to use |
||||
| 13 | * |
||||
| 14 | * @var string |
||||
| 15 | */ |
||||
| 16 | private string $baseId; |
||||
|
0 ignored issues
–
show
|
|||||
| 17 | |||||
| 18 | /** |
||||
| 19 | * The name of the table to use |
||||
| 20 | * |
||||
| 21 | * @var string |
||||
| 22 | */ |
||||
| 23 | private string $tableName; |
||||
|
0 ignored issues
–
show
|
|||||
| 24 | |||||
| 25 | /** |
||||
| 26 | * API key to use for authentication |
||||
| 27 | * |
||||
| 28 | * @var string |
||||
| 29 | */ |
||||
| 30 | private string $apiKey; |
||||
|
0 ignored issues
–
show
|
|||||
| 31 | |||||
| 32 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 33 | * @var \GuzzleHttp\Client |
||||
| 34 | */ |
||||
| 35 | private \GuzzleHttp\Client $client; |
||||
|
0 ignored issues
–
show
|
|||||
| 36 | |||||
| 37 | public static $rateLimitCooldown = 30; |
||||
| 38 | |||||
| 39 | 10 | public function __construct(\GuzzleHttp\Client $client) |
|||
|
0 ignored issues
–
show
|
|||||
| 40 | { |
||||
| 41 | 10 | $this->client = $client; |
|||
| 42 | 10 | } |
|||
| 43 | |||||
| 44 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 45 | * @return string |
||||
| 46 | */ |
||||
| 47 | 1 | public function getBaseId(): string |
|||
| 48 | { |
||||
| 49 | 1 | return $this->baseId; |
|||
| 50 | } |
||||
| 51 | |||||
| 52 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 53 | * @param string $baseId |
||||
|
0 ignored issues
–
show
|
|||||
| 54 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 55 | 8 | public function setBaseId(string $baseId): void |
|||
| 56 | { |
||||
| 57 | 8 | $this->baseId = $baseId; |
|||
| 58 | 8 | } |
|||
| 59 | |||||
| 60 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 61 | * @return string |
||||
| 62 | */ |
||||
| 63 | 1 | public function getTableName(): string |
|||
| 64 | { |
||||
| 65 | 1 | return $this->tableName; |
|||
| 66 | } |
||||
| 67 | |||||
| 68 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 69 | * @param string $tableName |
||||
|
0 ignored issues
–
show
|
|||||
| 70 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 71 | 8 | public function setTableName(string $tableName): void |
|||
| 72 | { |
||||
| 73 | 8 | $this->tableName = $tableName; |
|||
| 74 | 8 | } |
|||
| 75 | |||||
| 76 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 77 | * @return string |
||||
| 78 | */ |
||||
| 79 | 1 | public function getApiKey(): string |
|||
| 80 | { |
||||
| 81 | 1 | return $this->apiKey; |
|||
| 82 | } |
||||
| 83 | |||||
| 84 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 85 | * @param string $apiKey |
||||
|
0 ignored issues
–
show
|
|||||
| 86 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 87 | 8 | public function setApiKey(string $apiKey): void |
|||
| 88 | { |
||||
| 89 | 8 | $this->apiKey = $apiKey; |
|||
| 90 | 8 | } |
|||
| 91 | |||||
| 92 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 93 | * @param string $method |
||||
|
0 ignored issues
–
show
|
|||||
| 94 | * @param array|null $data |
||||
|
0 ignored issues
–
show
|
|||||
| 95 | * |
||||
| 96 | * @return ResponseInterface |
||||
| 97 | * |
||||
| 98 | * @throws \GuzzleHttp\Exception\GuzzleException |
||||
| 99 | */ |
||||
| 100 | 7 | protected function request(string $method = 'get', array $data = null): ResponseInterface |
|||
| 101 | { |
||||
| 102 | $options = [ |
||||
| 103 | 'headers' => [ |
||||
| 104 | 7 | 'Authorization' => 'Bearer ' . $this->apiKey |
|||
| 105 | ] |
||||
| 106 | ]; |
||||
| 107 | 7 | if($data !== null) { |
|||
|
0 ignored issues
–
show
|
|||||
| 108 | 7 | if($method === 'get' || $method === 'delete') { |
|||
|
0 ignored issues
–
show
|
|||||
| 109 | 4 | $options['query'] = $data; |
|||
| 110 | } else { |
||||
| 111 | 3 | $options['json'] = $data; |
|||
| 112 | } |
||||
| 113 | } |
||||
| 114 | 7 | return $this->client->request($method, |
|||
|
0 ignored issues
–
show
|
|||||
| 115 | 7 | sprintf('https://api.airtable.com/v0/%s/%s', $this->baseId, $this->tableName), |
|||
| 116 | $options |
||||
| 117 | ); |
||||
| 118 | } |
||||
| 119 | |||||
| 120 | 7 | protected function execute($dataChunk, \Closure $execution) |
|||
|
0 ignored issues
–
show
|
|||||
| 121 | { |
||||
| 122 | try { |
||||
| 123 | 7 | return $execution->call($this, $dataChunk); |
|||
| 124 | 1 | } catch (\GuzzleHttp\Exception\ClientException $exception) { |
|||
| 125 | 1 | if($exception->getCode() === 429) { |
|||
|
0 ignored issues
–
show
|
|||||
| 126 | 1 | sleep(static::$rateLimitCooldown); |
|||
| 127 | 1 | return $this->execute($dataChunk, $execution); |
|||
| 128 | } else { |
||||
| 129 | throw $exception; |
||||
| 130 | } |
||||
| 131 | } |
||||
| 132 | } |
||||
| 133 | |||||
| 134 | 5 | protected function chunkAndThrottle(array $data, \Closure $execution, int $delay = 1, int $chunkSize = 10) |
|||
|
0 ignored issues
–
show
|
|||||
| 135 | { |
||||
| 136 | 5 | $chunkedData = array_chunk($data, $chunkSize, false); |
|||
| 137 | 5 | foreach($chunkedData as $key => $dataChunk) { |
|||
|
0 ignored issues
–
show
|
|||||
| 138 | 5 | $this->execute($dataChunk, $execution); |
|||
| 139 | 5 | if($key !== array_key_last($chunkedData)) { |
|||
|
0 ignored issues
–
show
|
|||||
| 140 | 3 | sleep($delay); |
|||
| 141 | } |
||||
| 142 | } |
||||
| 143 | 5 | } |
|||
| 144 | |||||
| 145 | /** |
||||
| 146 | * Create Rows |
||||
| 147 | * |
||||
| 148 | * @param array $rows An array of arrays with the key as the field name and the value as the field value. E.g. |
||||
|
0 ignored issues
–
show
|
|||||
| 149 | * [ |
||||
|
0 ignored issues
–
show
|
|||||
| 150 | * ['Field1' => 'Val1', 'Field2' => 'Val2'], |
||||
|
0 ignored issues
–
show
|
|||||
| 151 | * ['Field1' => 'Val3', 'Field2' => 'Val3'] |
||||
|
0 ignored issues
–
show
|
|||||
| 152 | * ] |
||||
|
0 ignored issues
–
show
|
|||||
| 153 | * @param bool $typecast |
||||
|
0 ignored issues
–
show
|
|||||
| 154 | * |
||||
| 155 | * @throws \GuzzleHttp\Exception\GuzzleException |
||||
| 156 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 157 | 3 | public function createRows(array $rows, bool $typecast = true) |
|||
| 158 | { |
||||
| 159 | 3 | $data = []; |
|||
| 160 | 3 | foreach($rows as $row) { |
|||
|
0 ignored issues
–
show
|
|||||
| 161 | 3 | $data[] = ['fields' => $row]; |
|||
| 162 | } |
||||
| 163 | |||||
| 164 | $this->chunkAndThrottle($data, function($rowsToCreate) use ($typecast) { |
||||
|
0 ignored issues
–
show
|
|||||
| 165 | 3 | $this->request('post', [ |
|||
|
0 ignored issues
–
show
|
|||||
| 166 | 3 | 'records' => $rowsToCreate, 'typecast' => $typecast |
|||
| 167 | ]); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 168 | 3 | }); |
|||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 169 | 3 | } |
|||
| 170 | |||||
| 171 | /** |
||||
| 172 | * Delete Rows |
||||
| 173 | * |
||||
| 174 | * @param array $rowIds An array of row IDs to delete. E.g. ['rec123', 'rec456'] |
||||
| 175 | * |
||||
| 176 | * @throws \GuzzleHttp\Exception\GuzzleException |
||||
| 177 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 178 | 2 | public function deleteRows(array $rowIds) |
|||
| 179 | { |
||||
| 180 | $this->chunkAndThrottle($rowIds, function($rowIds) { |
||||
|
0 ignored issues
–
show
|
|||||
| 181 | 2 | $this->request('delete', [ |
|||
|
0 ignored issues
–
show
|
|||||
| 182 | 2 | 'records' => $rowIds |
|||
| 183 | ]); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 184 | 2 | }); |
|||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 185 | 2 | } |
|||
| 186 | |||||
| 187 | 3 | public function retrieveRecords() |
|||
|
0 ignored issues
–
show
|
|||||
| 188 | { |
||||
| 189 | 3 | $records = []; |
|||
| 190 | 3 | $offset = null; |
|||
| 191 | do { |
||||
|
0 ignored issues
–
show
|
|||||
| 192 | $response = $this->execute([], function($data) use ($offset) { |
||||
|
0 ignored issues
–
show
The parameter
$data is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 193 | 3 | return $this->request('get', [ |
|||
|
0 ignored issues
–
show
|
|||||
| 194 | 3 | 'offset' => $offset |
|||
| 195 | ]); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 196 | 3 | }); |
|||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 197 | 3 | $responseData = json_decode($response->getBody()->getContents(), true); |
|||
| 198 | |||||
| 199 | try { |
||||
| 200 | 3 | $newRecords = $responseData['records']; |
|||
| 201 | } catch (\Exception $e) { |
||||
| 202 | $newRecords = []; |
||||
| 203 | } |
||||
| 204 | |||||
| 205 | 3 | $records = array_merge($records, $newRecords); |
|||
| 206 | 3 | if(array_key_exists('offset', $responseData)) { |
|||
|
0 ignored issues
–
show
|
|||||
| 207 | 3 | $offset = $responseData['offset']; |
|||
| 208 | } else { |
||||
| 209 | 3 | $offset = null; |
|||
| 210 | } |
||||
| 211 | 3 | } while($offset !== null); |
|||
| 212 | 3 | return $records; |
|||
| 213 | } |
||||
| 214 | |||||
| 215 | 2 | public function getIdsFromTable(): array |
|||
|
0 ignored issues
–
show
|
|||||
| 216 | { |
||||
| 217 | 2 | $ids = []; |
|||
| 218 | 2 | foreach($this->retrieveRecords() as $record) { |
|||
|
0 ignored issues
–
show
|
|||||
| 219 | 2 | $ids[] = $record['id']; |
|||
| 220 | } |
||||
| 221 | 2 | return $ids; |
|||
| 222 | } |
||||
| 223 | |||||
| 224 | 1 | public function flushTable() |
|||
|
0 ignored issues
–
show
|
|||||
| 225 | { |
||||
| 226 | 1 | $this->deleteRows( |
|||
| 227 | 1 | $this->getIdsFromTable() |
|||
| 228 | ); |
||||
| 229 | 1 | } |
|||
| 230 | |||||
| 231 | } |