@@ -384,12 +384,12 @@ final class Curler implements IReadable, IWritable, ProvidesBuilder
384384 /**
385385 * @var \CurlHandle|resource|null
386386 */
387- private static $ Handle ;
387+ private $ Handle ;
388388
389389 /**
390390 * @var bool|null
391391 */
392- private static $ HandleIsReset ;
392+ private $ HandleIsReset ;
393393
394394 /**
395395 * @var int
@@ -406,6 +406,21 @@ final class Curler implements IReadable, IWritable, ProvidesBuilder
406406 */
407407 private static $ DefaultUserAgent ;
408408
409+ /**
410+ * @var \CurlHandle|resource|null
411+ */
412+ private static $ SharedHandle ;
413+
414+ /**
415+ * @var bool|null
416+ */
417+ private static $ SharedHandleIsReset ;
418+
419+ /**
420+ * @var int
421+ */
422+ private static $ HandleCount = 0 ;
423+
409424 /**
410425 * @param (callable(Curler): string[])|null $responseCacheKeyCallback
411426 * @param (callable(Curler): Curler)|null $responseCallback
@@ -588,29 +603,29 @@ public function responseContentTypeIs(string $mimeType): bool
588603
589604 protected function getEffectiveUrl (): ?string
590605 {
591- return self :: $ Handle
592- ? curl_getinfo (self :: $ Handle , CURLINFO_EFFECTIVE_URL )
606+ return $ this -> Handle
607+ ? curl_getinfo ($ this -> Handle , CURLINFO_EFFECTIVE_URL )
593608 : null ;
594609 }
595610
596611 protected function close (): void
597612 {
598- if (!self :: $ Handle ) {
613+ if (!$ this -> Handle ) {
599614 return ;
600615 }
601616
602617 if ($ this ->CookieKey && $ this ->ExecuteCount ) {
603- Cache::set ($ this ->CookieKey , curl_getinfo (self :: $ Handle , CURLINFO_COOKIELIST ));
618+ Cache::set ($ this ->CookieKey , curl_getinfo ($ this -> Handle , CURLINFO_COOKIELIST ));
604619 }
605620
606- curl_reset (self :: $ Handle );
607- self :: $ HandleIsReset = true ;
621+ curl_reset ($ this -> Handle );
622+ $ this -> HandleIsReset = true ;
608623 }
609624
610625 /**
611626 * @param mixed[]|null $query
612627 */
613- private function initialise (string $ method , ?array $ query , ?ICurlerPager $ pager = null ): void
628+ private function initialise (string $ method , ?array $ query , ?ICurlerPager $ pager = null , bool $ async = false ): void
614629 {
615630 $ this ->ExecuteCount = 0 ;
616631
@@ -619,69 +634,83 @@ private function initialise(string $method, ?array $query, ?ICurlerPager $pager
619634 }
620635 $ this ->QueryString = $ this ->getQueryString ($ query );
621636
622- if (self ::$ Handle ) {
623- if (!self ::$ HandleIsReset ) {
624- curl_reset (self ::$ Handle );
637+ if ($ async ) {
638+ if ($ this ->Handle && $ this ->Handle === self ::$ SharedHandle ) {
639+ $ handle = null ;
640+ $ handleIsReset = null ;
641+ $ this ->Handle = &$ handle ;
642+ $ this ->HandleIsReset = &$ handleIsReset ;
625643 }
626- self ::$ HandleIsReset = false ;
627- curl_setopt (self ::$ Handle , CURLOPT_URL , $ this ->BaseUrl . $ this ->QueryString );
628644 } else {
629- self ::$ Handle = curl_init ($ this ->BaseUrl . $ this ->QueryString );
645+ $ this ->maybeDiscardHandle ();
646+ $ this ->Handle = &self ::$ SharedHandle ;
647+ $ this ->HandleIsReset = &self ::$ SharedHandleIsReset ;
648+ }
649+
650+ if ($ this ->Handle ) {
651+ if (!$ this ->HandleIsReset ) {
652+ curl_reset ($ this ->Handle );
653+ }
654+ $ this ->HandleIsReset = false ;
655+ curl_setopt ($ this ->Handle , CURLOPT_URL , $ this ->BaseUrl . $ this ->QueryString );
656+ } else {
657+ $ this ->Handle = curl_init ($ this ->BaseUrl . $ this ->QueryString );
658+ self ::$ HandleCount ++;
630659 }
631660
632661 // Return the transfer as a string
633- curl_setopt (self :: $ Handle , CURLOPT_RETURNTRANSFER , true );
662+ curl_setopt ($ this -> Handle , CURLOPT_RETURNTRANSFER , true );
634663
635664 // Enable all supported encoding types (e.g. gzip, deflate) and set
636665 // Accept-Encoding header accordingly
637- curl_setopt (self :: $ Handle , CURLOPT_ENCODING , '' );
666+ curl_setopt ($ this -> Handle , CURLOPT_ENCODING , '' );
638667
639668 // Collect response headers
640669 curl_setopt (
641- self :: $ Handle ,
670+ $ this -> Handle ,
642671 CURLOPT_HEADERFUNCTION ,
643672 fn ($ curl , $ header ) => strlen ($ this ->processHeader ($ header ))
644673 );
645674
646675 if ($ this ->ConnectTimeout !== null ) {
647- curl_setopt (self :: $ Handle , CURLOPT_CONNECTTIMEOUT , $ this ->ConnectTimeout );
676+ curl_setopt ($ this -> Handle , CURLOPT_CONNECTTIMEOUT , $ this ->ConnectTimeout );
648677 }
649678
650679 if ($ this ->Timeout !== null ) {
651- curl_setopt (self :: $ Handle , CURLOPT_TIMEOUT , $ this ->Timeout );
680+ curl_setopt ($ this -> Handle , CURLOPT_TIMEOUT , $ this ->Timeout );
652681 }
653682
654683 if ($ this ->FollowRedirects ) {
655- curl_setopt (self :: $ Handle , CURLOPT_FOLLOWLOCATION , true );
684+ curl_setopt ($ this -> Handle , CURLOPT_FOLLOWLOCATION , true );
656685 if ($ this ->MaxRedirects !== null ) {
657- curl_setopt (self :: $ Handle , CURLOPT_MAXREDIRS , $ this ->MaxRedirects );
686+ curl_setopt ($ this -> Handle , CURLOPT_MAXREDIRS , $ this ->MaxRedirects );
658687 }
659688 }
660689
661690 if ($ this ->CookieKey = $ this ->getCookieKey ()) {
662691 // Enable cookies without loading them from a file
663- curl_setopt (self :: $ Handle , CURLOPT_COOKIEFILE , '' );
692+ curl_setopt ($ this -> Handle , CURLOPT_COOKIEFILE , '' );
664693
665694 foreach (Cache::get ($ this ->CookieKey ) ?: [] as $ cookie ) {
666- curl_setopt (self :: $ Handle , CURLOPT_COOKIELIST , $ cookie );
695+ curl_setopt ($ this -> Handle , CURLOPT_COOKIELIST , $ cookie );
667696 }
668697 }
669698
670699 // In debug mode, collect request headers
671700 if (Env::debug ()) {
672- curl_setopt (self :: $ Handle , CURLINFO_HEADER_OUT , true );
701+ curl_setopt ($ this -> Handle , CURLINFO_HEADER_OUT , true );
673702 }
674703
675704 switch ($ method ) {
676705 case HttpRequestMethod::GET :
677706 break ;
678707
679708 case HttpRequestMethod::HEAD :
680- curl_setopt (self :: $ Handle , CURLOPT_NOBODY , true );
709+ curl_setopt ($ this -> Handle , CURLOPT_NOBODY , true );
681710 break ;
682711
683712 case HttpRequestMethod::POST :
684- curl_setopt (self :: $ Handle , CURLOPT_POST , true );
713+ curl_setopt ($ this -> Handle , CURLOPT_POST , true );
685714 break ;
686715
687716 case HttpRequestMethod::PUT :
@@ -690,7 +719,7 @@ private function initialise(string $method, ?array $query, ?ICurlerPager $pager
690719 case HttpRequestMethod::CONNECT :
691720 case HttpRequestMethod::OPTIONS :
692721 case HttpRequestMethod::TRACE :
693- curl_setopt (self :: $ Handle , CURLOPT_CUSTOMREQUEST , $ method );
722+ curl_setopt ($ this -> Handle , CURLOPT_CUSTOMREQUEST , $ method );
694723 break ;
695724
696725 default :
@@ -782,7 +811,7 @@ private function clearResponse(): void
782811 private function applyData ($ data ): void
783812 {
784813 curl_setopt (
785- self :: $ Handle ,
814+ $ this -> Handle ,
786815 CURLOPT_POSTFIELDS ,
787816 ($ this ->Body = $ this ->prepareData ($ data ))
788817 );
@@ -912,7 +941,7 @@ protected function execute(bool $close = true, int $depth = 0): string
912941
913942 $ this ->ExecuteCount ++;
914943
915- curl_setopt (self :: $ Handle , CURLOPT_HTTPHEADER , $ this ->Headers ->getHeaders ());
944+ curl_setopt ($ this -> Handle , CURLOPT_HTTPHEADER , $ this ->Headers ->getHeaders ());
916945
917946 $ attempt = 0 ;
918947 while ($ attempt ++ < 2 ) {
@@ -929,11 +958,11 @@ protected function execute(bool $close = true, int $depth = 0): string
929958 }
930959
931960 // Execute the request
932- $ result = curl_exec (self :: $ Handle );
933- $ this ->CurlInfo = curl_getinfo (self :: $ Handle );
961+ $ result = curl_exec ($ this -> Handle );
962+ $ this ->CurlInfo = curl_getinfo ($ this -> Handle );
934963
935964 if ($ result === false ) {
936- $ error = curl_errno (self :: $ Handle );
965+ $ error = curl_errno ($ this -> Handle );
937966 throw new CurlerCurlErrorException ($ error , $ this );
938967 }
939968
@@ -1183,7 +1212,7 @@ private function process(string $method, ?array $query, $data = null, ?string $m
11831212 if (is_array ($ data ) || is_object ($ data )) {
11841213 $ this ->applyData ($ data );
11851214 } elseif (is_string ($ data ) && $ mimeType ) {
1186- curl_setopt (self :: $ Handle , CURLOPT_POSTFIELDS , $ data );
1215+ curl_setopt ($ this -> Handle , CURLOPT_POSTFIELDS , $ data );
11871216 $ this ->setContentType ($ mimeType );
11881217 }
11891218
@@ -1224,7 +1253,7 @@ private function paginate(string $method, ?array $query, $data = null): Generato
12241253 $ data = $ this ->Pager ->prepareData ($ data );
12251254 }
12261255
1227- $ this ->initialise ($ method , $ query , $ this ->Pager );
1256+ $ this ->initialise ($ method , $ query , $ this ->Pager , true );
12281257
12291258 do {
12301259 if ($ data !== null ) {
@@ -1251,7 +1280,7 @@ private function paginate(string $method, ?array $query, $data = null): Generato
12511280 }
12521281 [$ url , $ data , $ headers ] =
12531282 [$ page ->nextUrl (), $ page ->nextData (), $ page ->nextHeaders ()];
1254- curl_setopt (self :: $ Handle , CURLOPT_URL , $ url );
1283+ curl_setopt ($ this -> Handle , CURLOPT_URL , $ url );
12551284 if ($ headers !== null ) {
12561285 $ this ->Headers = $ headers ;
12571286 }
@@ -1361,7 +1390,7 @@ public function getAllLinked(?array $query = null): array
13611390
13621391 do {
13631392 if ($ nextUrl ) {
1364- curl_setopt (self :: $ Handle , CURLOPT_URL , $ nextUrl );
1393+ curl_setopt ($ this -> Handle , CURLOPT_URL , $ nextUrl );
13651394 $ this ->clearResponse ();
13661395 $ nextUrl = null ;
13671396 }
@@ -1395,7 +1424,7 @@ public function getAllLinkedByEntity($entityName, ?array $query = null): array
13951424
13961425 do {
13971426 if ($ nextUrl ) {
1398- curl_setopt (self :: $ Handle , CURLOPT_URL , $ nextUrl );
1427+ curl_setopt ($ this -> Handle , CURLOPT_URL , $ nextUrl );
13991428 $ this ->clearResponse ();
14001429 }
14011430
@@ -1545,4 +1574,16 @@ public static function getBuilder(): string
15451574 {
15461575 return CurlerBuilder::class;
15471576 }
1577+
1578+ public function __destruct ()
1579+ {
1580+ $ this ->maybeDiscardHandle ();
1581+ }
1582+
1583+ private function maybeDiscardHandle (): void
1584+ {
1585+ if ($ this ->Handle && $ this ->Handle !== self ::$ SharedHandle ) {
1586+ self ::$ HandleCount --;
1587+ }
1588+ }
15481589}
0 commit comments