2929use chobie \Jira \Api \Authentication \AuthenticationInterface ;
3030use chobie \Jira \Api \Authentication \Basic ;
3131use chobie \Jira \Api \Exception ;
32+ use chobie \Jira \Api \UnauthorizedException ;
3233
3334class PHPClient implements ClientInterface
3435{
@@ -40,6 +41,13 @@ class PHPClient implements ClientInterface
4041 */
4142 protected $ httpsSupport = false ;
4243
44+ /**
45+ * Last error message.
46+ *
47+ * @var string
48+ */
49+ private $ _lastErrorMessage = '' ;
50+
4351 /**
4452 * Create a traditional php client.
4553 */
@@ -57,6 +65,8 @@ public function __construct()
5765 * Returns status of HTTP support.
5866 *
5967 * @return boolean
68+ *
69+ * @codeCoverageIgnore
6070 */
6171 protected function isHttpsSupported ()
6272 {
@@ -75,7 +85,12 @@ protected function isHttpsSupported()
7585 * @param boolean $debug Debug this request.
7686 *
7787 * @return array|string
78- * @throws \Exception When non-supported implementation of AuthenticationInterface is given.
88+ * @throws \InvalidArgumentException When non-supported implementation of AuthenticationInterface is given.
89+ * @throws \InvalidArgumentException When data is not an array and http method is GET.
90+ * @throws Exception When request failed due communication error.
91+ * @throws UnauthorizedException When request failed, because user can't be authorized properly.
92+ * @throws Exception When there was empty response instead of needed data.
93+ * @throws \InvalidArgumentException When "https" wrapper is not available, but http:// is requested.
7994 */
8095 public function sendRequest (
8196 $ method ,
@@ -87,7 +102,10 @@ public function sendRequest(
87102 $ debug = false
88103 ) {
89104 if ( !($ credential instanceof Basic) && !($ credential instanceof Anonymous) ) {
90- throw new \Exception (sprintf ('PHPClient does not support %s authentication. ' , get_class ($ credential )));
105+ throw new \InvalidArgumentException (sprintf (
106+ 'PHPClient does not support %s authentication. ' ,
107+ get_class ($ credential )
108+ ));
91109 }
92110
93111 $ header = array ();
@@ -96,18 +114,18 @@ public function sendRequest(
96114 $ header [] = 'Authorization: Basic ' . $ credential ->getCredential ();
97115 }
98116
117+ if ( !$ is_file ) {
118+ $ header [] = 'Content-Type: application/json;charset=UTF-8 ' ;
119+ }
120+
99121 $ context = array (
100122 'http ' => array (
101123 'method ' => $ method ,
102124 'header ' => implode ("\r\n" , $ header ),
103125 ),
104126 );
105127
106- if ( !$ is_file ) {
107- $ header [] = 'Content-Type: application/json;charset=UTF-8 ' ;
108- }
109-
110- if ( $ method == 'POST ' || $ method == 'PUT ' ) {
128+ if ( $ method == 'POST ' || $ method == 'PUT ' || $ method == 'DELETE ' ) {
111129 if ( $ is_file ) {
112130 $ filename = preg_replace ('/^@/ ' , '' , $ data ['file ' ]);
113131 $ boundary = '-------------------------- ' . microtime (true );
@@ -129,41 +147,84 @@ public function sendRequest(
129147 $ context ['http ' ]['header ' ] = implode ("\r\n" , $ header );
130148 $ context ['http ' ]['content ' ] = $ __data ;
131149 }
132- else {
150+ elseif ( $ method == 'GET ' ) {
151+ if ( !is_array ($ data ) ) {
152+ throw new \InvalidArgumentException ('Data must be an array. ' );
153+ }
154+
133155 $ url .= '? ' . http_build_query ($ data );
134156 }
135157
158+ // @codeCoverageIgnoreStart
136159 if ( strpos ($ endpoint , 'https:// ' ) === 0 && !$ this ->isHttpsSupported () ) {
137- throw new \Exception ('does not support https wrapper. please enable openssl extension ' );
160+ throw new \InvalidArgumentException ('does not support https wrapper. please enable openssl extension ' );
161+ }
162+ // @codeCoverageIgnoreEnd
163+
164+ list ($ http_code , $ response , $ error_message ) = $ this ->doSendRequest ($ endpoint . $ url , $ context );
165+
166+ // Check for 401 code before "$error_message" checking, because it's considered as an error.
167+ if ( $ http_code == 401 ) {
168+ throw new UnauthorizedException ('Unauthorized ' );
169+ }
170+
171+ if ( !empty ($ error_message ) ) {
172+ throw new Exception (
173+ sprintf ('Jira request failed: "%s" ' , $ error_message )
174+ );
175+ }
176+
177+ if ( $ response === '' && !in_array ($ http_code , array (201 , 204 )) ) {
178+ throw new Exception ('JIRA Rest server returns unexpected result. ' );
138179 }
139180
181+ // @codeCoverageIgnoreStart
182+ if ( is_null ($ response ) ) {
183+ throw new Exception ('JIRA Rest server returns unexpected result. ' );
184+ }
185+ // @codeCoverageIgnoreEnd
186+
187+ return $ response ;
188+ }
189+
190+ /**
191+ * Sends the request.
192+ *
193+ * @param string $url URL.
194+ * @param array $context Context.
195+ *
196+ * @return array
197+ */
198+ protected function doSendRequest ($ url , array $ context )
199+ {
200+ $ this ->_lastErrorMessage = '' ;
201+
140202 set_error_handler (array ($ this , 'errorHandler ' ));
141- $ data = file_get_contents (
142- $ endpoint . $ url ,
143- false ,
144- stream_context_create ($ context )
145- );
203+ $ response = file_get_contents ($ url , false , stream_context_create ($ context ));
146204 restore_error_handler ();
147205
148- if ( is_null ($ data ) ) {
149- throw new \Exception ('JIRA Rest server returns unexpected result. ' );
206+ if ( isset ($ http_response_header ) ) {
207+ preg_match ('#HTTP/\d+\.\d+ (\d+)# ' , $ http_response_header [0 ], $ matches );
208+ $ http_code = $ matches [1 ];
209+ }
210+ else {
211+ $ http_code = 0 ;
150212 }
151213
152- return $ data ;
214+ return array ( $ http_code , $ response , $ this -> _lastErrorMessage ) ;
153215 }
154216
155217 /**
156- * Throws exception on error.
218+ * Remembers last error.
157219 *
158220 * @param integer $errno Error number.
159221 * @param string $errstr Error message.
160222 *
161223 * @return void
162- * @throws \Exception Always.
163224 */
164225 public function errorHandler ($ errno , $ errstr )
165226 {
166- throw new \ Exception ( $ errstr) ;
227+ $ this -> _lastErrorMessage = $ errstr ;
167228 }
168229
169230}
0 commit comments