@@ -0,0 +1,246 @@
1+<?php
2+/**
3+ * Created by PhpStorm.
4+ * User: glali
5+ * Date: 2017-04-27
6+ * Time: 14:44
7+ */
8+
9+namespace TANIOS\Airtable;
10+
11+
12+class Response implements \ArrayAccess
13+{
14+
15+ /**
16+ * @var Airtable Instance of Airtable
17+ */
18+ private $airtable;
19+
20+ /**
21+ * @var Request Instance or Request
22+ */
23+ private $request;
24+
25+ /**
26+ * @var string Response content
27+ */
28+ private $content = "";
29+
30+ /**
31+ * @var bool|\stdClass Response
32+ */
33+ private $parsedContent = false;
34+
35+ /**
36+ * Response constructor.
37+ * @param Airtable $airtable Instance of Airtable
38+ * @param Request $request Instance of Request
39+ * @param string $content Content string
40+ */
41+ public function __construct( $airtable, $request, $content, $relations = false )
42+ {
43+
44+ $this->airtable = $airtable;
45+
46+ $this->request = $request;
47+
48+ $this->content = $content;
49+
50+ try
51+ {
52+ $this->parsedContent = json_decode( $content );
53+ }
54+ catch ( \Exception $e )
55+ {
56+ $this->parsedContent = false;
57+ }
58+
59+ if( is_array( $relations ) && count( $relations ) > 0 )
60+ {
61+
62+ if( array_keys( $relations ) !== range( 0, count( $relations ) - 1 ) )
63+ {
64+ foreach ( $relations as $related_field => $related_table )
65+ {
66+ $this->processRelatedField( $related_field, $related_table );
67+ }
68+ }
69+ else
70+ {
71+ foreach ( $relations as $related_field )
72+ {
73+ $this->processRelatedField( $related_field );
74+ }
75+ }
76+
77+ }
78+
79+ }
80+
81+ private function processRelatedField( $related_field, $related_table = false )
82+ {
83+
84+ if( isset( $this->parsedContent->records ) && is_array( $this->parsedContent->records ) && count( $this->parsedContent->records ) > 0 )
85+ {
86+ foreach ( $this->parsedContent->records as $record_key => $record )
87+ {
88+ $this->parsedContent->records[ $record_key ] = $this->loadRelatedField( $related_field, $related_table, $record );
89+ }
90+ }
91+ else
92+ {
93+ $this->parsedContent = $this->loadRelatedField( $related_field, $related_table, $this->parsedContent );
94+ }
95+
96+ }
97+
98+ private function loadRelatedField( $related_field, $related_table, $record )
99+ {
100+
101+
102+ if( ! isset( $record->fields ) || ! isset( $record->fields->$related_field ) )
103+ {
104+ return $record;
105+ }
106+
107+ if( empty( $related_table ) )
108+ {
109+ $related_table = $related_field;
110+ }
111+
112+ $relation_ids = $record->fields->$related_field;
113+
114+ if( ! is_array( $relation_ids ) )
115+ {
116+ $relation_ids = [ $relation_ids ];
117+ }
118+
119+ $relation_formula = "OR(";
120+ $relation_formula .= implode( ', ', array_map( function( $id ) { return "RECORD_ID() = '$id'"; }, $relation_ids ) );
121+ $relation_formula .= ")";
122+
123+ if( ! is_array( $related_table ) )
124+ {
125+ $relation_request = $this->airtable->getContent( "$related_table", [
126+ 'filterByFormula' => $relation_formula
127+ ] );
128+ }
129+ else
130+ {
131+ $related_table_relations = isset( $related_table[ 'relations' ] ) && is_array( $related_table[ 'relations' ] )
132+ ? $related_table[ 'relations' ]
133+ : false;
134+
135+ $related_table_name = ! empty( $related_table[ 'table' ] ) ? $related_table[ 'table' ] : $related_field;
136+
137+ $relation_request = $this->airtable->getContent( "$related_table_name", [
138+ 'filterByFormula' => $relation_formula
139+ ], $related_table_relations );
140+ }
141+
142+
143+ $related_records = [];
144+
145+ do
146+ {
147+ $relation_response = $relation_request->getResponse();
148+
149+ if( ! is_array( $relation_response->records ) || count( $relation_response->records ) < 0 )
150+ {
151+ break;
152+ }
153+
154+ foreach ( $relation_response->records as $related_record )
155+ {
156+ $formatted_record = $related_record->fields;
157+ $formatted_record->id = $related_record->id;
158+
159+ $related_records[] = $formatted_record;
160+ }
161+ }
162+ while( $relation_request = $relation_response->next() );
163+
164+ if( is_array( $record->fields->$related_field ) )
165+ {
166+ $record->fields->$related_field = $related_records;
167+ }
168+ else
169+ {
170+ $record->fields->$related_field = count( $related_records ) > 0
171+ ? $related_records[ 0 ]
172+ : null;
173+ }
174+
175+ return $record;
176+
177+ }
178+
179+ public function next()
180+ {
181+
182+ if( ! $this->parsedContent )
183+ {
184+ return false;
185+ }
186+
187+
188+ if( ! isset( $this[ 'offset' ] ) )
189+ {
190+ return false;
191+ }
192+
193+ $this->request->offset = $this[ 'offset' ];
194+
195+ return $this->request;
196+
197+ }
198+
199+ public function __get( $key )
200+ {
201+ if( ! $this->parsedContent || ! isset( $this->parsedContent->$key ) )
202+ {
203+ return null;
204+ }
205+
206+ return $this->parsedContent->$key;
207+ }
208+
209+ public function __toString()
210+ {
211+ return $this->content;
212+ }
213+
214+ public function __isset( $key )
215+ {
216+ return $this->parsedContent && isset( $this->parsedContent->$key );
217+ }
218+
219+ public function offsetExists($offset)
220+ {
221+ return $this->parsedContent && isset( $this->parsedContent->$offset );
222+ }
223+
224+ public function offsetGet($offset)
225+ {
226+ return $this->parsedContent && isset( $this->parsedContent->$offset )
227+ ? $this->parsedContent->$offset
228+ : null;
229+ }
230+
231+ public function offsetSet($offset, $value)
232+ {
233+ if( $this->parsedContent )
234+ {
235+ $this->parsedContent->$offset = $value;
236+ }
237+ }
238+
239+ public function offsetUnset($offset)
240+ {
241+ if( $this->parsedContent && isset( $this->parsedContent->$offset ) )
242+ {
243+ unset( $this->parsedContent->$offset );
244+ }
245+ }
246+}