33namespace INTERMediator \FileMakerServer \RESTAPI \Supporting ;
44
55use Exception ;
6+ use CurlHandle ;
67
78/**
89 * Class CommunicationProvider is for internal use to communicate with FileMaker Server.
@@ -258,31 +259,27 @@ public function __construct(string $solution, string $user, string $password, ?
258259
259260 /**
260261 * @param array $params Array to build the API path. Ex: `["layouts" => null]` or `["sessions" => $this->accessToken]`.
261- * @param null| array $request The query parameters as `"key" => "value"`.
262+ * @param array|null $request The query parameters as `"key" => "value"`.
262263 * @param string $methodLower The method in lowercase. Ex: `"get"`, `"delete"`, etc.
263264 * @param bool $isSystem If the query is for the system (sessions, databases, etc) or for a database.
264- * @param false| string $directPath If we don't want to build the path with the other parameters, you can provide the direct path.
265+ * @param string|null|false $directPath If we don't want to build the path with the other parameters, you can provide the direct path.
265266 * @return string
266267 * @ignore
267268 */
268- public function getURL (array $ params , string | array | null $ request , string $ methodLower ,
269- bool $ isSystem = false , bool $ directPath = false ): string
269+ public function getURL (array $ params , ? array $ request , string $ methodLower ,
270+ bool $ isSystem = false , string | null | false $ directPath = null ): string
270271 {
271272 $ vStr = $ this ->vNum < 1 ? 'Latest ' : strval ($ this ->vNum );
272273 $ url = "$ this ->protocol :// $ this ->host : $ this ->port " ;
273- if ($ directPath ) {
274+ if (! empty ( $ directPath) ) {
274275 $ url .= $ directPath ;
275276 } else {
276277 $ url .= "/fmi/data/v $ vStr " . ((!$ isSystem ) ? "/databases/ $ this ->solution " : "" );
277278 }
278279 foreach ($ params as $ key => $ value ) {
279280 $ url .= "/ $ key " . (is_null ($ value ) ? "" : "/ $ value " );
280281 }
281- if (!is_string ($ request ) &&
282- in_array ($ methodLower , array ('get ' , 'delete ' )) &&
283- !is_null ($ request ) &&
284- (count ($ request ) > 0 )
285- ) {
282+ if (!empty ($ request ) && in_array ($ methodLower , array ('get ' , 'delete ' ))) {
286283 $ url .= '? ' ;
287284 foreach ($ request as $ key => $ value ) {
288285 if (key ($ request ) !== $ key ) {
@@ -293,7 +290,7 @@ public function getURL(array $params, string|array|null $request, string $method
293290 if ($ sortParam !== '[] ' ) {
294291 $ url .= '_ ' . $ key . '= ' . $ sortParam ;
295292 }
296- } else if ($ key === 'limit ' || $ key === 'offset ' ) {
293+ } elseif ($ key === 'limit ' || $ key === 'offset ' ) {
297294 $ url .= '_ ' . $ key . '= ' . (is_array ($ value ) ? json_encode ($ value ) : $ value );
298295 } else {
299296 // handling portal object name etc.
@@ -361,7 +358,7 @@ public function justifyRequest(?array $request): array
361358
362359 if (isset ($ result ['sort ' ])) {
363360 $ sort = [];
364- foreach ($ result ['sort ' ] as $ sortKey => $ sortCondition ) {
361+ foreach ($ result ['sort ' ] as $ sortCondition ) {
365362 if (isset ($ sortCondition [0 ])) {
366363 $ sortOrder = 'ascend ' ;
367364 if (isset ($ sortCondition [1 ])) {
@@ -490,14 +487,12 @@ public function getScriptNames(): null|array
490487
491488 /**
492489 * @throws Exception In case of any error, an exception arises.
490+ * @return bool
493491 * @ignore
494492 */
495- public function login ()
493+ public function login (): bool
496494 {
497- if ($ this ->keepAuth ) {
498- return true ;
499- }
500- if (!is_null ($ this ->accessToken )) {
495+ if ($ this ->keepAuth || !is_null ($ this ->accessToken )) {
501496 return true ;
502497 }
503498
@@ -509,7 +504,10 @@ public function login()
509504 ];
510505 } else {
511506 $ value = "Basic " . base64_encode ("{$ this ->user }: {$ this ->password }" );
512- $ headers = ["Content-Type " => "application/json " , "Authorization " => $ value ];
507+ $ headers = [
508+ "Content-Type " => "application/json " ,
509+ "Authorization " => $ value
510+ ];
513511 }
514512 $ params = ["sessions " => null ];
515513 $ request = [];
@@ -531,6 +529,7 @@ public function login()
531529 /**
532530 *
533531 * @throws Exception In case of any error, an exception arises.
532+ * @return void
534533 * @ignore
535534 */
536535 public function logout ()
@@ -564,16 +563,21 @@ private function getSupportingProviders()
564563 private function getOAuthIdentifier ($ provider )
565564 {
566565 try {
567- $ this ->callRestAPI ([], [
568- "trackingID " => rand (10000000 , 99999999 ),
569- "provider " => $ provider ,
570- "address " => "127.0.0.1 " ,
571- "X-FMS-OAuth-AuthType " => 2
572- ], 'GET ' , [], [
573- "X-FMS-Application-Type " => 9 ,
574- "X-FMS-Application-Version " => 15 ,
575- "X-FMS-Return-URL " => "http://127.0.0.1/ " ,
576- ], false , "/oauth/getoauthurl " );
566+ $ this ->callRestAPI (
567+ [], false , 'GET ' ,
568+ [
569+ "trackingID " => rand (10000000 , 99999999 ),
570+ "provider " => $ provider ,
571+ "address " => "127.0.0.1 " ,
572+ "X-FMS-OAuth-AuthType " => 2
573+ ],
574+ [
575+ "X-FMS-Application-Type " => 9 ,
576+ "X-FMS-Application-Version " => 15 ,
577+ "X-FMS-Return-URL " => "http://127.0.0.1/ " ,
578+ ],
579+ false , "/oauth/getoauthurl "
580+ );
577581 $ result = [];
578582 foreach ($ this ->responseBody as $ key => $ item ) {
579583
@@ -585,55 +589,38 @@ private function getOAuthIdentifier($provider)
585589 }
586590
587591 /**
588- * @param $params
589- * @param $layout
590- * @param boolean $isAddToken
592+ * @param array $params
593+ * @param bool $isAddToken
591594 * @param string $method
592- * @param array $request
593- * @param array $addHeader
594- * @param boolean $isSystem for Metadata
595+ * @param array|null $request
596+ * @param array|null $addHeader
597+ * @param bool $isSystem for Metadata
598+ * @param string|null|false $directPath
599+ * @return void
595600 * @throws Exception In case of any error, an exception arises.
596601 * @ignore
597602 */
598- public function callRestAPI ($ params , $ isAddToken , $ method = 'GET ' , $ request = null , $ addHeader = null , $ isSystem = false , $ directPath = false )
603+ public function callRestAPI (array $ params , bool $ isAddToken , string $ method = 'GET ' , $ request = null ,
604+ $ addHeader = null , $ isSystem = false , string |null |false $ directPath = null )
599605 {
600606 $ methodLower = strtolower ($ method );
601607 $ url = $ this ->getURL ($ params , $ request , $ methodLower , $ isSystem , $ directPath );
602608 $ header = $ this ->getHeaders ($ isAddToken , $ addHeader );
603609 $ jsonEncoding = true ;
604610 if (is_string ($ request )) {
605611 $ jsonEncoding = false ;
606- } else if ($ methodLower !== 'get ' && !is_null ($ request )) {
612+ } elseif ($ methodLower !== 'get ' && !is_null ($ request )) {
607613 $ request = $ this ->justifyRequest ($ request );
608614 }
609- $ ch = curl_init ();
610- curl_setopt ($ ch , CURLOPT_URL , $ url );
615+ $ ch = $ this ->_createCurlHandle ($ url );
611616 curl_setopt ($ ch , CURLOPT_VERBOSE , 0 );
612617 curl_setopt ($ ch , CURLOPT_HEADER , 1 );
613- curl_setopt ($ ch , CURLOPT_SSLVERSION , CURL_SSLVERSION_DEFAULT );
614618 curl_setopt ($ ch , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
615619 if ($ methodLower == 'post ' ) {
616620 curl_setopt ($ ch , CURLOPT_POST , 1 );
617621 } elseif (in_array ($ methodLower , ['put ' , 'patch ' , 'delete ' , 'get ' ], true )) {
618622 curl_setopt ($ ch , CURLOPT_CUSTOMREQUEST , strtoupper ($ methodLower ));
619623 }
620- if ($ this ->isCertValidating ) {
621- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
622- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 1 );
623- // Use the OS native certificate authorities, if possible.
624- // This fixes SSL validation errors if `php.ini` doesn't have
625- // [curl] `curl.cainfo` set properly of if this PEM file isn't
626- // up to date. Better rely on the OS certificate authorities, which
627- // is maintained automatically.
628- if (defined ('CURLSSLOPT_NATIVE_CA ' )
629- && version_compare (curl_version ()['version ' ], '7.71 ' , '>= ' )) {
630- curl_setopt ($ ch , CURLOPT_SSL_OPTIONS , CURLSSLOPT_NATIVE_CA );
631- }
632- } else {
633- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 0 );
634- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 0 );
635- }
636- curl_setopt ($ ch , CURLOPT_RETURNTRANSFER , 1 );
637624 curl_setopt ($ ch , CURLOPT_HTTPHEADER , $ header );
638625 if ($ methodLower != 'get ' ) {
639626 if ($ jsonEncoding ) {
@@ -648,9 +635,6 @@ public function callRestAPI($params, $isAddToken, $method = 'GET', $request = nu
648635 curl_setopt ($ ch , CURLOPT_POSTFIELDS , $ request );
649636 }
650637 }
651- if (!is_null ($ this ->timeout )) {
652- curl_setopt ($ ch , CURLOPT_TIMEOUT , $ this ->timeout );
653- }
654638 $ response = curl_exec ($ ch );
655639 $ this ->curlInfo = curl_getinfo ($ ch );
656640 $ this ->curlErrorNumber = curl_errno ($ ch );
@@ -699,55 +683,37 @@ public function callRestAPI($params, $isAddToken, $method = 'GET', $request = nu
699683 /**
700684 * Return the base64 encoded data in container field.
701685 * Thanks to 'base64bits' as https://github.com/msyk/FMDataAPI/issues/18.
702- * @param string $name The container field name.
703- * The table occurrence name of the portal can be the portal name, and also the object name of the portal.
704- * @param string $toName The table occurrence name of the portal as the prefix of the field name.
686+ * @param string $url
705687 * @return string The base64 encoded data in container field.
706688 * @ignore
707689 */
708- public function accessToContainer ($ url )
690+ public function accessToContainer (string $ url ): string
709691 {
710- $ cookieFile = tempnam (sys_get_temp_dir (), "CURLCOOKIE " ); //create a cookie file
692+ $ cookieFile = tempnam (sys_get_temp_dir (), "CURLCOOKIE " ); // Create a cookie file.
711693
712- $ ch = curl_init ($ url ); //visit the container URL to set the cookie
694+ // Visit the container URL to set the cookie.
695+ $ ch = $ this ->_createCurlHandle ($ url );
713696 curl_setopt ($ ch , CURLOPT_COOKIEJAR , $ cookieFile );
714- curl_setopt ($ ch , CURLOPT_RETURNTRANSFER , true );
715- if ($ this ->isCertValidating ) {
716- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
717- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 1 );
718- } else {
719- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 0 );
720- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 0 );
721- }
722- if (!is_null ($ this ->timeout )) {
723- curl_setopt ($ ch , CURLOPT_TIMEOUT , $ this ->timeout );
724- }
725697 curl_exec ($ ch );
726698 if (curl_errno ($ ch ) !== 0 ) {
727699 $ errMsg = curl_error ($ ch );
700+ curl_close ($ ch );
728701 throw new Exception ("Error in creating cookie file. {$ errMsg }" );
729702 }
703+ curl_close ($ ch );
730704
731- $ ch = curl_init ($ url ); //visit container URL again
705+ // Visit the container URL again.
706+ $ ch = $ this ->_createCurlHandle ($ url );
732707 curl_setopt ($ ch , CURLOPT_COOKIEFILE , $ cookieFile );
733- curl_setopt ($ ch , CURLOPT_RETURNTRANSFER , true );
734- if ($ this ->isCertValidating ) {
735- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
736- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 1 );
737- } else {
738- curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 0 );
739- curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 0 );
740- }
741- if (!is_null ($ this ->timeout )) {
742- curl_setopt ($ ch , CURLOPT_TIMEOUT , $ this ->timeout );
743- }
744708 $ output = curl_exec ($ ch );
745709 if (curl_errno ($ ch ) !== 0 ) {
746710 $ errMsg = curl_error ($ ch );
711+ curl_close ($ ch );
747712 throw new Exception ("Error in downloading content of file. {$ errMsg }" );
748713 }
714+ curl_close ($ ch );
749715
750- return base64_encode ($ output ); //process the image data as need it
716+ return base64_encode ($ output ); // Process the data as needed.
751717 }
752718
753719 /**
@@ -811,11 +777,11 @@ public function storeToProperties()
811777 * @return string
812778 * @ignore
813779 */
814- public function adjustSortDirection ($ direction )
780+ public function adjustSortDirection ($ direction ): string
815781 {
816782 if (strtoupper ($ direction ) == 'ASC ' ) {
817783 $ direction = 'ascend ' ;
818- } else if (strtoupper ($ direction ) == 'DESC ' ) {
784+ } elseif (strtoupper ($ direction ) == 'DESC ' ) {
819785 $ direction = 'descend ' ;
820786 }
821787
@@ -837,7 +803,7 @@ public function getCurlInfo($key)
837803 * @return string
838804 * @ignore
839805 */
840- public function debugOutput ($ isReturnValue = false )
806+ public function debugOutput (bool $ isReturnValue = false ): string
841807 {
842808 $ str = "<div style='background-color: #DDDDDD'>URL: " ;
843809 $ str .= $ this ->method . ' ' . htmlspecialchars ($ this ->url );
@@ -872,7 +838,7 @@ public function debugOutput($isReturnValue = false)
872838 * @return string
873839 * @ignore
874840 */
875- private function _buildSortParameters ($ value )
841+ private function _buildSortParameters (array $ value ): string
876842 {
877843 $ param = '[ ' ;
878844 foreach ($ value as $ sortCondition ) {
@@ -899,7 +865,7 @@ private function _buildSortParameters($value)
899865 * @return string
900866 * @ignore
901867 */
902- private function _json_urlencode ($ value )
868+ private function _json_urlencode (array $ value ): string
903869 {
904870 $ str = '[ ' ;
905871 if (count ($ value ) > 0 ) {
@@ -914,4 +880,52 @@ private function _json_urlencode($value)
914880
915881 return $ str ;
916882 }
883+
884+ /**
885+ * To create and configure cURL at a single place, avoiding code redundancy.
886+ * If later we need some specific settings for some cases, then add new
887+ * parameters to this function.
888+ *
889+ * @param string|null $url The URL you want to access.
890+ * @param bool $returnTransfer By default, sets CURLOPT_RETURNTRANSFER to `true`.
891+ * But it can be set to false if needed.
892+ * @return CurlHandle
893+ */
894+ private function _createCurlHandle (string |null $ url = null , bool $ returnTransfer = true ): CurlHandle
895+ {
896+ $ ch = curl_init ();
897+
898+ if (!is_null ($ url )) {
899+ curl_setopt ($ ch , CURLOPT_URL , $ url );
900+ }
901+
902+ if ($ returnTransfer ) {
903+ curl_setopt ($ ch , CURLOPT_RETURNTRANSFER , true );
904+ }
905+
906+ curl_setopt ($ ch , CURLOPT_SSLVERSION , CURL_SSLVERSION_DEFAULT );
907+
908+ if ($ this ->isCertValidating ) {
909+ curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
910+ curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 1 );
911+ // Use the OS native certificate authorities, if possible.
912+ // This fixes SSL validation errors if `php.ini` doesn't have
913+ // [curl] `curl.cainfo` set properly of if this PEM file isn't
914+ // up to date. Better rely on the OS certificate authorities, which
915+ // is maintained automatically.
916+ if (defined ('CURLSSLOPT_NATIVE_CA ' )
917+ && version_compare (curl_version ()['version ' ], '7.71 ' , '>= ' )) {
918+ curl_setopt ($ ch , CURLOPT_SSL_OPTIONS , CURLSSLOPT_NATIVE_CA );
919+ }
920+ } else {
921+ curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 0 );
922+ curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 0 );
923+ }
924+
925+ if (!is_null ($ this ->timeout )) {
926+ curl_setopt ($ ch , CURLOPT_TIMEOUT , $ this ->timeout );
927+ }
928+
929+ return $ ch ;
930+ }
917931}
0 commit comments