11<?php namespace Gitlab \Api ;
22
33use Gitlab \Client ;
4+ use Gitlab \Exception \RuntimeException ;
45use Gitlab \HttpClient \Message \QueryStringBuilder ;
56use Gitlab \HttpClient \Message \ResponseMediator ;
67use Gitlab \Tests \HttpClient \Message \QueryStringBuilderTest ;
@@ -56,8 +57,8 @@ public function configure()
5657 * Performs a GET query and returns the response as a PSR-7 response object.
5758 *
5859 * @param string $path
59- * @param array $parameters
60- * @param array $requestHeaders
60+ * @param array<string,mixed> $parameters
61+ * @param array<string,string> $requestHeaders
6162 * @return ResponseInterface
6263 */
6364 protected function getAsResponse ($ path , array $ parameters = array (), $ requestHeaders = array ())
@@ -69,8 +70,8 @@ protected function getAsResponse($path, array $parameters = array(), $requestHea
6970
7071 /**
7172 * @param string $path
72- * @param array $parameters
73- * @param array $requestHeaders
73+ * @param array<string,mixed> $parameters
74+ * @param array<string,string> $requestHeaders
7475 * @return mixed
7576 */
7677 protected function get ($ path , array $ parameters = array (), $ requestHeaders = array ())
@@ -80,9 +81,9 @@ protected function get($path, array $parameters = array(), $requestHeaders = arr
8081
8182 /**
8283 * @param string $path
83- * @param array $parameters
84- * @param array $requestHeaders
85- * @param array $files
84+ * @param array<string,mixed> $parameters
85+ * @param array<string,string> $requestHeaders
86+ * @param array<string,string> $files
8687 * @return mixed
8788 */
8889 protected function post ($ path , array $ parameters = array (), $ requestHeaders = array (), array $ files = array ())
@@ -101,7 +102,7 @@ protected function post($path, array $parameters = array(), $requestHeaders = ar
101102 }
102103
103104 foreach ($ files as $ name => $ file ) {
104- $ builder ->addResource ($ name , fopen ($ file , 'r ' ), [
105+ $ builder ->addResource ($ name , self :: tryFopen ($ file , 'r ' ), [
105106 'headers ' => [
106107 'Content-Type ' => $ this ->guessContentType ($ file ),
107108 ],
@@ -120,8 +121,9 @@ protected function post($path, array $parameters = array(), $requestHeaders = ar
120121
121122 /**
122123 * @param string $path
123- * @param array $parameters
124- * @param array $requestHeaders
124+ * @param array<string,mixed> $parameters
125+ * @param array<string,string> $requestHeaders
126+ * @param array<string,string> $files
125127 * @return mixed
126128 */
127129 protected function put ($ path , array $ parameters = array (), $ requestHeaders = array (), array $ files = array ())
@@ -140,7 +142,7 @@ protected function put($path, array $parameters = array(), $requestHeaders = arr
140142 }
141143
142144 foreach ($ files as $ name => $ file ) {
143- $ builder ->addResource ($ name , fopen ($ file , 'r ' ), [
145+ $ builder ->addResource ($ name , self :: tryFopen ($ file , 'r ' ), [
144146 'headers ' => [
145147 'Content-Type ' => $ this ->guessContentType ($ file ),
146148 ],
@@ -159,8 +161,8 @@ protected function put($path, array $parameters = array(), $requestHeaders = arr
159161
160162 /**
161163 * @param string $path
162- * @param array $parameters
163- * @param array $requestHeaders
164+ * @param array<string,mixed> $parameters
165+ * @param array<string,string> $requestHeaders
164166 * @return mixed
165167 */
166168 protected function delete ($ path , array $ parameters = array (), $ requestHeaders = array ())
@@ -265,6 +267,44 @@ private function guessContentType($file)
265267 }
266268 $ finfo = new \finfo (FILEINFO_MIME_TYPE );
267269
268- return $ finfo ->file ($ file );
270+ return $ finfo ->file ($ file ) ?: 'application/octet-stream ' ;
271+ }
272+
273+ /**
274+ * Safely opens a PHP stream resource using a filename.
275+ *
276+ * When fopen fails, PHP normally raises a warning. This function adds an
277+ * error handler that checks for errors and throws an exception instead.
278+ *
279+ * @param string $filename File to open
280+ * @param string $mode Mode used to open the file
281+ *
282+ * @return resource
283+ *
284+ * @throws RuntimeException if the file cannot be opened
285+ *
286+ * @see https://github.com/guzzle/psr7/blob/1.6.1/src/functions.php#L287-L320
287+ */
288+ private static function tryFopen ($ filename , $ mode )
289+ {
290+ $ ex = null ;
291+ set_error_handler (function () use ($ filename , $ mode , &$ ex ) {
292+ $ ex = new RuntimeException (sprintf (
293+ 'Unable to open %s using mode %s: %s ' ,
294+ $ filename ,
295+ $ mode ,
296+ func_get_args ()[1 ]
297+ ));
298+ });
299+
300+ $ handle = fopen ($ filename , $ mode );
301+ restore_error_handler ();
302+
303+ if (null !== $ ex ) {
304+ throw $ ex ;
305+ }
306+
307+ /** @var resource */
308+ return $ handle ;
269309 }
270310}
0 commit comments