@@ -49,42 +49,95 @@ class QuickBase {
4949 'responseAsObject ' => false
5050 );
5151
52- public $ ch ;
52+ public $ mch ;
53+ public $ chs ;
5354
5455 public function __construct ($ options = array ()){
5556 $ this ->settings = array_replace_recursive ($ this ->defaults , $ options );
5657
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 ();
6360
6461 return $ this ;
6562 }
6663
6764 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 );
6970 }
7071
72+ // final public function api($actions = array()){
7173 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 ]);
85123 }
86124
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 ;
88141 }
89142
90143}
@@ -223,7 +276,9 @@ final public function checkForAndHandleError(){
223276
224277 return $ this
225278 ->constructPayload ()
226- ->transmit ();
279+ ->prepareCH ()
280+ ->processCH ()
281+ ->checkForAndHandleError ();
227282 }catch (Exception $ newTicketErr ){
228283 ++$ this ->nErrors ;
229284
@@ -241,24 +296,16 @@ final public function checkForAndHandleError(){
241296 return $ this ;
242297 }
243298
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 );
255302 }
256303
257304 return $ this ;
258305 }
259306
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 (
262309 $ this ->settings ['useSSL ' ] ? 'https:// ' : 'http:// ' ,
263310 $ this ->settings ['realm ' ],
264311 '. ' ,
@@ -270,11 +317,11 @@ final public function transmit(){
270317 $ this ->settings ['flags ' ]['useXML ' ] ? '' : $ this ->payload
271318 )));
272319
273- curl_setopt ($ this -> parent -> ch , CURLOPT_PORT , $ this ->settings ['useSSL ' ] ? 443 : 80 );
320+ curl_setopt ($ ch , CURLOPT_PORT , $ this ->settings ['useSSL ' ] ? 443 : 80 );
274321
275322 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 (
278325 'POST /db/ ' .(isset ($ this ->options ['dbid ' ]) ? $ this ->options ['dbid ' ] : 'main ' ).' HTTP/1.0 ' ,
279326 'Content-Type: text/xml; ' ,
280327 'Accept: text/xml ' ,
@@ -283,25 +330,31 @@ final public function transmit(){
283330 'Content-Length: ' .strlen ($ this ->payload ),
284331 'QUICKBASE-ACTION: ' .$ this ->action
285332 ));
286- curl_setopt ($ this -> parent -> ch , CURLOPT_POSTFIELDS , $ this ->payload );
333+ curl_setopt ($ ch , CURLOPT_POSTFIELDS , $ this ->payload );
287334 }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 );
291338 }
292339
293- $ response = curl_exec ( $ this -> parent -> ch ) ;
340+ $ this -> ch = $ ch ;
294341
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 );
297350
298- $ headerSize = curl_getinfo ($ this ->parent -> ch , CURLINFO_HEADER_SIZE );
351+ $ headerSize = curl_getinfo ($ this ->ch , CURLINFO_HEADER_SIZE );
299352
300353 if ($ response === false ){
301354 ++$ this ->nErrors ;
302355
303356 if ($ this ->nErrors <= $ this ->settings ['maxErrorRetryAttempts ' ]){
304- return $ this ->transmit ();
357+ return $ this ->prepareCH ()-> processCH ();
305358 }
306359
307360 throw new QuickBaseError ($ errno , $ error );
@@ -327,6 +380,22 @@ final public function transmit(){
327380 return $ this ;
328381 }
329382
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+
330399 /* Helpers */
331400 final public static function arr2Obj (&$ arr , $ return = false ){
332401 $ obj = new \stdClass ;
0 commit comments