@@ -49,42 +49,95 @@ class QuickBase {
49
49
'responseAsObject ' => false
50
50
);
51
51
52
- public $ ch ;
52
+ public $ mch ;
53
+ public $ chs ;
53
54
54
55
public function __construct ($ options = array ()){
55
56
$ this ->settings = array_replace_recursive ($ this ->defaults , $ options );
56
57
57
- $ this ->ch = curl_init ();
58
-
59
- curl_setopt ($ this ->ch , CURLOPT_SSL_VERIFYPEER , false );
60
- curl_setopt ($ this ->ch , CURLOPT_RETURNTRANSFER , true );
61
- curl_setopt ($ this ->ch , CURLOPT_HEADER , true );
62
- curl_setopt ($ this ->ch , CURLOPT_FOLLOWLOCATION , true );
58
+ $ this ->mch = curl_multi_init ();
59
+ $ this ->chs = array ();
63
60
64
61
return $ this ;
65
62
}
66
63
67
64
public function __destruct (){
68
- curl_close ($ this ->ch );
65
+ for ($ i = 0 , $ l = count ($ this ->chs ); $ i < $ l ; ++$ i ){
66
+ curl_close ($ this ->chs [$ i ]);
67
+ }
68
+
69
+ curl_multi_close ($ this ->mch );
69
70
}
70
71
72
+ // final public function api($actions = array()){
71
73
final public function api ($ action , $ options = array ()){
72
- $ query = new QuickBaseQuery ($ this , $ action , $ options );
73
-
74
- $ query
75
- ->addFlags ()
76
- ->processOptions ()
77
- ->actionRequest ()
78
- ->constructPayload ()
79
- ->transmit ()
80
- ->checkForAndHandleError ()
81
- ->actionResponse ();
82
-
83
- if (isset ($ query ->options ['responseAsObject ' ]) && $ query ->options ['responseAsObject ' ]){
84
- QuickBaseQuery::arr2Obj ($ query ->response );
74
+ if (!is_array ($ action )){
75
+ $ actions = array (
76
+ array (
77
+ 'action ' => $ action ,
78
+ 'options ' => $ options
79
+ )
80
+ );
81
+ }else {
82
+ $ actions = $ action ;
83
+ }
84
+
85
+ $ nActions = count ($ actions );
86
+ $ queries = array ();
87
+ $ results = array ();
88
+
89
+ for ($ i = 0 ; $ i < $ nActions ; ++$ i ){
90
+ if (!isset ($ this ->chs [$ i ])){
91
+ $ this ->chs [] = self ::genCH ();
92
+ }
93
+
94
+ $ query = new QuickBaseQuery ($ this , $ actions [$ i ]['action ' ], $ actions [$ i ]['options ' ]);
95
+
96
+ $ query
97
+ ->addFlags ()
98
+ ->processOptions ()
99
+ ->actionRequest ()
100
+ ->constructPayload ()
101
+ ->prepareCH ($ this ->chs [$ i ]);
102
+
103
+ curl_multi_add_handle ($ this ->mch , $ this ->chs [$ i ]);
104
+
105
+ $ queries [] = $ query ;
106
+ }
107
+
108
+ do {
109
+ curl_multi_exec ($ this ->mch , $ running );
110
+ curl_multi_select ($ this ->mch );
111
+ }while ($ running > 0 );
112
+
113
+ for ($ i = 0 ; $ i < $ nActions ; ++$ i ){
114
+ $ queries [$ i ]
115
+ ->processCH ()
116
+ ->checkForAndHandleError ()
117
+ ->actionResponse ()
118
+ ->finalize ();
119
+
120
+ $ results [] = $ queries [$ i ]->response ;
121
+
122
+ curl_multi_remove_handle ($ this ->mch , $ this ->chs [$ i ]);
85
123
}
86
124
87
- return $ query ->response ;
125
+ if ($ nActions === 1 ){
126
+ return $ results [0 ];
127
+ }
128
+
129
+ return $ results ;
130
+ }
131
+
132
+ final public static function genCH (){
133
+ $ ch = curl_init ();
134
+
135
+ curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , false );
136
+ curl_setopt ($ ch , CURLOPT_RETURNTRANSFER , true );
137
+ curl_setopt ($ ch , CURLOPT_HEADER , true );
138
+ curl_setopt ($ ch , CURLOPT_FOLLOWLOCATION , true );
139
+
140
+ return $ ch ;
88
141
}
89
142
90
143
}
@@ -223,7 +276,9 @@ final public function checkForAndHandleError(){
223
276
224
277
return $ this
225
278
->constructPayload ()
226
- ->transmit ();
279
+ ->prepareCH ()
280
+ ->processCH ()
281
+ ->checkForAndHandleError ();
227
282
}catch (Exception $ newTicketErr ){
228
283
++$ this ->nErrors ;
229
284
@@ -241,24 +296,16 @@ final public function checkForAndHandleError(){
241
296
return $ this ;
242
297
}
243
298
244
- final public function processOptions (){
245
- if (isset ($ this ->options ['fields ' ])){
246
- $ this ->options ['field ' ] = $ this ->options ['fields ' ];
247
-
248
- unset($ this ->options ['fields ' ]);
249
- }
250
-
251
- foreach ($ this ->options as $ key => $ value ){
252
- if (method_exists ('\QuickBase\QuickBaseOption ' , $ key )){
253
- $ this ->options [$ key ] = QuickBaseOption::{$ key }($ value );
254
- }
299
+ final public function finalize (){
300
+ if (isset ($ this ->options ['responseAsObject ' ]) && $ this ->options ['responseAsObject ' ]){
301
+ QuickBaseQuery::arr2Obj ($ this ->response );
255
302
}
256
303
257
304
return $ this ;
258
305
}
259
306
260
- final public function transmit ( ){
261
- curl_setopt ($ this -> parent -> ch , CURLOPT_URL , implode ('' , array (
307
+ final public function prepareCH (& $ ch ){
308
+ curl_setopt ($ ch , CURLOPT_URL , implode ('' , array (
262
309
$ this ->settings ['useSSL ' ] ? 'https:// ' : 'http:// ' ,
263
310
$ this ->settings ['realm ' ],
264
311
'. ' ,
@@ -270,11 +317,11 @@ final public function transmit(){
270
317
$ this ->settings ['flags ' ]['useXML ' ] ? '' : $ this ->payload
271
318
)));
272
319
273
- curl_setopt ($ this -> parent -> ch , CURLOPT_PORT , $ this ->settings ['useSSL ' ] ? 443 : 80 );
320
+ curl_setopt ($ ch , CURLOPT_PORT , $ this ->settings ['useSSL ' ] ? 443 : 80 );
274
321
275
322
if ($ this ->settings ['flags ' ]['useXML ' ]){
276
- curl_setopt ($ this -> parent -> ch , CURLOPT_POST , true );
277
- curl_setopt ($ this -> parent -> ch , CURLOPT_HTTPHEADER , array (
323
+ curl_setopt ($ ch , CURLOPT_POST , true );
324
+ curl_setopt ($ ch , CURLOPT_HTTPHEADER , array (
278
325
'POST /db/ ' .(isset ($ this ->options ['dbid ' ]) ? $ this ->options ['dbid ' ] : 'main ' ).' HTTP/1.0 ' ,
279
326
'Content-Type: text/xml; ' ,
280
327
'Accept: text/xml ' ,
@@ -283,25 +330,31 @@ final public function transmit(){
283
330
'Content-Length: ' .strlen ($ this ->payload ),
284
331
'QUICKBASE-ACTION: ' .$ this ->action
285
332
));
286
- curl_setopt ($ this -> parent -> ch , CURLOPT_POSTFIELDS , $ this ->payload );
333
+ curl_setopt ($ ch , CURLOPT_POSTFIELDS , $ this ->payload );
287
334
}else {
288
- curl_setopt ($ this -> parent -> ch , CURLOPT_POST , false );
289
- curl_setopt ($ this -> parent -> ch , CURLOPT_HTTPHEADER , false );
290
- curl_setopt ($ this -> parent -> ch , CURLOPT_POSTFIELDS , false );
335
+ curl_setopt ($ ch , CURLOPT_POST , false );
336
+ curl_setopt ($ ch , CURLOPT_HTTPHEADER , false );
337
+ curl_setopt ($ ch , CURLOPT_POSTFIELDS , false );
291
338
}
292
339
293
- $ response = curl_exec ( $ this -> parent -> ch ) ;
340
+ $ this -> ch = $ ch ;
294
341
295
- $ errno = curl_errno ($ this ->parent ->ch );
296
- $ error = curl_error ($ this ->parent ->ch );
342
+ return $ this ;
343
+ }
344
+
345
+ final public function processCH (){
346
+ $ response = curl_multi_getcontent ($ this ->ch );
347
+
348
+ $ errno = curl_errno ($ this ->ch );
349
+ $ error = curl_error ($ this ->ch );
297
350
298
- $ headerSize = curl_getinfo ($ this ->parent -> ch , CURLINFO_HEADER_SIZE );
351
+ $ headerSize = curl_getinfo ($ this ->ch , CURLINFO_HEADER_SIZE );
299
352
300
353
if ($ response === false ){
301
354
++$ this ->nErrors ;
302
355
303
356
if ($ this ->nErrors <= $ this ->settings ['maxErrorRetryAttempts ' ]){
304
- return $ this ->transmit ();
357
+ return $ this ->prepareCH ()-> processCH ();
305
358
}
306
359
307
360
throw new QuickBaseError ($ errno , $ error );
@@ -327,6 +380,22 @@ final public function transmit(){
327
380
return $ this ;
328
381
}
329
382
383
+ final public function processOptions (){
384
+ if (isset ($ this ->options ['fields ' ])){
385
+ $ this ->options ['field ' ] = $ this ->options ['fields ' ];
386
+
387
+ unset($ this ->options ['fields ' ]);
388
+ }
389
+
390
+ foreach ($ this ->options as $ key => $ value ){
391
+ if (method_exists ('\QuickBase\QuickBaseOption ' , $ key )){
392
+ $ this ->options [$ key ] = QuickBaseOption::{$ key }($ value );
393
+ }
394
+ }
395
+
396
+ return $ this ;
397
+ }
398
+
330
399
/* Helpers */
331
400
final public static function arr2Obj (&$ arr , $ return = false ){
332
401
$ obj = new \stdClass ;
0 commit comments