1
+ <?php
2
+
3
+ App::uses ('DboSource ' , 'Model/Datasource ' );
4
+
5
+ class Waferpie extends DboSource {
6
+
7
+ public $ description = 'Rest Source ' ;
8
+
9
+ public $ headers = array ();
10
+
11
+ /**
12
+ * __construct
13
+ *
14
+ * We are not a dbo source - we are secretly a datasource and just want the log functions, hence we extend
15
+ * DboSource
16
+ *
17
+ * @param mixed $config
18
+ * @param mixed $autoConnect
19
+ * @return void
20
+ */
21
+ public function __construct ($ config = null , $ autoConnect = true ) {
22
+ DataSource::__construct ($ config );
23
+ $ this ->fullDebug = Configure::read ('debug ' ) > 1 ;
24
+ }
25
+
26
+ /**
27
+ * Execute a custom query against the REST server
28
+ *
29
+ * $model->get('custom_method',)
30
+ * $model->post('custom_method', array())
31
+ *
32
+ * @param string $method The HTTP verb to execute (get, post, pull, delete)
33
+ * @param array $pass The raw configuration
34
+ * @param Model $model The model that triggered the call
35
+ * @return mixed
36
+ */
37
+ public function query ($ method , $ pass , Model $ model ) {
38
+ if (empty ($ pass )) {
39
+ throw new Exception ('Missing information about the HTTP request ' );
40
+ }
41
+
42
+ $ t = microtime (true );
43
+
44
+ $ config = $ pass [0 ];
45
+ if (!is_array ($ config )) {
46
+ $ config = array ('action ' => $ config );
47
+ }
48
+
49
+ if (empty ($ config ['action ' ])) {
50
+ throw new Exception ('Missing action key ' );
51
+ }
52
+
53
+ $ url = sprintf ('/%s/%s ' , $ model ->remoteResource , $ config ['action ' ]);
54
+
55
+ $ cu = new \Nodes \Curl ($ this ->getBaseUrl () . $ url );
56
+ $ this ->applyConfiguration ($ cu );
57
+
58
+ $ data = null ;
59
+ if (in_array ($ method , array ('put ' , 'post ' )) && isset ($ pass [1 ])) {
60
+ $ data = $ pass [1 ];
61
+ }
62
+
63
+ try {
64
+ $ response = call_user_func (array ($ cu , $ method ), $ data );
65
+
66
+ if ($ this ->fullDebug ) {
67
+ $ this ->took = round ((microtime (true ) - $ t ) * 1000 , 0 );
68
+ $ this ->numRows = $ this ->affected = $ response ['data ' ] ? count (current ($ response ['data ' ])) : 0 ;
69
+ $ this ->logQuery ($ url , $ params );
70
+ }
71
+
72
+ return $ response ;
73
+
74
+ } catch (Exception $ e ) {
75
+ $ this ->logQuery ($ url , $ params );
76
+
77
+ CakeLog::error ($ e );
78
+ return array ();
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Execute a HTTP POST request against a REST resource
84
+ *
85
+ * @param Model $model The model that is executing the save()
86
+ * @param array $fields A list of fields that needs to be saved
87
+ * @param array $values A list of values that need to be saved
88
+ * @return mixed
89
+ */
90
+ public function create (Model $ model , $ fields = null , $ values = null ) {
91
+ $ t = microtime (true );
92
+
93
+ $ method = 'post ' ;
94
+ $ url = sprintf ('/%s ' , $ model ->remoteResource );
95
+ if (!empty ($ data ['id ' ])) {
96
+ $ url = sprintf ('/%s/%s ' , $ model ->remoteResource , $ data ['id ' ]);
97
+ $ method = 'put ' ;
98
+ }
99
+
100
+ $ data = array ();
101
+ if (!empty ($ fields ) && !empty ($ values )) {
102
+ $ data = array_combine ($ fields , $ values );
103
+ }
104
+
105
+ $ cu = new \Nodes \Curl ($ this ->getBaseUrl () . $ url );
106
+ $ this ->applyConfiguration ($ cu );
107
+
108
+ try {
109
+ $ response = call_user_func (array ($ cu , $ method ), $ data );
110
+
111
+ if ($ this ->fullDebug ) {
112
+ $ this ->took = round ((microtime (true ) - $ t ) * 1000 , 0 );
113
+ $ responseData = $ response ->getResponseBody ('data ' );
114
+ $ this ->numRows = $ this ->affected = isset ($ responseData ['data ' ]) ? count (current ($ responseData ['data ' ])) : 0 ;
115
+ $ this ->logQuery ($ url , $ data );
116
+ }
117
+
118
+ return $ response ;
119
+ } catch (Exception $ e ) {
120
+ if ($ this ->fullDebug ) {
121
+ $ this ->logQuery ($ url );
122
+ }
123
+ CakeLog::error ($ e );
124
+ return array ();
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Execute a GET request against a REST resource
130
+ *
131
+ * @param Model $model The model that is executing find() / read()
132
+ * @param array $queryData The conditions for the find - currently we only support "id" => $value
133
+ * @return mixed
134
+ */
135
+ public function read (Model $ model , $ queryData = array ()) {
136
+ $ t = microtime (true );
137
+
138
+ $ url = $ this ->config ['host ' ] . DS . $ model ->remoteResource ;
139
+
140
+ if (isset ($ queryData ['action ' ])) {
141
+ $ url .= DS . $ queryData ['action ' ];
142
+ }
143
+
144
+ if (!empty ($ queryData ['conditions ' ]['id ' ])) {
145
+ $ url .= DS . $ queryData ['conditions ' ]['id ' ];
146
+ unset($ queryData ['conditions ' ]['id ' ]);
147
+ }
148
+
149
+ if (!empty ($ this ->config ['format ' ])) {
150
+ $ url = trim ($ url , DS ) . '. ' . $ this ->config ['format ' ];
151
+ }
152
+
153
+ if (!empty ($ queryData ['limit ' ])) {
154
+ $ queryData ['conditions ' ]['limit ' ] = $ queryData ['limit ' ];
155
+ }
156
+
157
+ if (!empty ($ queryData ['offset ' ])) {
158
+ $ queryData ['conditions ' ]['offset ' ] = $ queryData ['offset ' ];
159
+ }
160
+
161
+ if (!empty ($ queryData ['order ' ])) {
162
+ $ queryData ['conditions ' ]['order ' ] = $ queryData ['order ' ];
163
+ }
164
+
165
+ if (!empty ($ queryData ['page ' ])) {
166
+ $ queryData ['conditions ' ]['page ' ] = $ queryData ['page ' ];
167
+ }
168
+
169
+ if (!empty ($ queryData ['conditions ' ])) {
170
+ $ url .= '? ' . http_build_query ($ queryData ['conditions ' ]);
171
+ }
172
+
173
+ try {
174
+ $ cu = new \Nodes \Curl ($ url );
175
+ $ this ->applyConfiguration ($ cu );
176
+
177
+ $ response = $ cu ->get ()->getResponseBody ();
178
+
179
+ if ($ this ->fullDebug ) {
180
+ $ this ->took = round ((microtime (true ) - $ t ) * 1000 , 0 );
181
+ $ current = is_array ($ response ['data ' ]) ? current ($ response ['data ' ]) : array ();
182
+ $ this ->numRows = $ this ->affected = $ response ['data ' ] ? count ($ current ) : 0 ;
183
+ $ this ->logQuery ($ url , $ queryData );
184
+ }
185
+
186
+ if (empty ($ response ['success ' ])) {
187
+ return array ();
188
+ }
189
+ return $ response ['data ' ];
190
+ } catch (Exception $ e ) {
191
+ if ($ this ->fullDebug ) {
192
+ $ this ->logQuery ($ url , $ queryData );
193
+ }
194
+
195
+ CakeLog::error ($ e );
196
+ return array ();
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Execute a PUT request against a REST resource
202
+ *
203
+ * @param Model $model The model that is executing the save()
204
+ * @param array $fields A list of fields that needs to be saved
205
+ * @param array $values A list of values that need to be saved
206
+ * @param array $conditions Update conditions - currently not used
207
+ * @return mixed
208
+ */
209
+ public function update (Model $ model , $ fields = array (), $ values = null , $ conditions = null ) {
210
+ $ data = array_combine ($ fields , $ values );
211
+ $ url = sprintf ('/%s ' , $ model ->remoteResource );
212
+ $ cu = new \Nodes \Curl ($ this ->getBaseUrl () . $ url );
213
+ $ this ->applyConfiguration ($ cu );
214
+
215
+ try {
216
+ return $ cu ->put ($ data );
217
+ } catch (Exception $ e ) {
218
+ CakeLog::error ($ e );
219
+ return array ();
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Execute a DELETE request against a REST resource
225
+ *
226
+ * @param Model $model The model that is executing the delete()
227
+ * @param mixed $id The resource ID to delete
228
+ * @return mixed
229
+ */
230
+ public function delete (Model $ model , $ id = null ) {
231
+ $ url = sprintf ('/%s/%s ' , $ model ->remoteResource , $ id );
232
+ $ cu = new \Nodes \Curl ($ this ->getBaseUrl () . $ url );
233
+ $ this ->applyConfiguration ($ cu );
234
+
235
+ try {
236
+ return $ cu ->delete ();
237
+ } catch (Exception $ e ) {
238
+ CakeLog::error ($ e );
239
+ return array ();
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Build the baseURL based on configuration options
245
+ * - protocol string Can be HTTP or HTTPS (default)
246
+ * - hostname string The hostname of the application server
247
+ * - admin boolean If the remote URL is within an admin routing
248
+ *
249
+ * @return string
250
+ */
251
+ public function getBaseUrl () {
252
+ return $ this ->config ['host ' ];
253
+ }
254
+
255
+ /**
256
+ * Caches/returns cached results for child instances
257
+ *
258
+ * @param mixed $data
259
+ * @return array Array of sources available in this datasource.
260
+ */
261
+ public function listSources ($ data = null ) {
262
+ return true ;
263
+ }
264
+
265
+ /**
266
+ * Apply some custom confiuration to our cURL object
267
+ * - Set the Platform-Token HTTP header for remote authentication
268
+ * - Set the
269
+ *
270
+ * @param Curl $cu The cURL object we want to apply configuration for
271
+ * @return void
272
+ */
273
+ public function applyConfiguration (\Nodes \Curl $ cu ) {
274
+ $ check = array_map (function ($ h ) { return current (explode (': ' , $ h )); }, $ this ->headers );
275
+ if (!in_array ('X-Authorization ' , $ check )) {
276
+ throw new InternalErrorException ('No API token provided ' );
277
+ }
278
+ $ cu ->setOption (CURLOPT_HTTPHEADER , $ this ->headers );
279
+ }
280
+
281
+ }
0 commit comments