Passed
Push — master ( ff2040...6f6996 )
by KwangSeob
02:18
created

JiraClient::isRestApiV3()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace JiraRestApi;
4
5
use JiraRestApi\Configuration\ConfigurationInterface;
6
use JiraRestApi\Configuration\DotEnvConfiguration;
7
use Monolog\Handler\StreamHandler;
8
use Monolog\Logger as Logger;
9
use Psr\Log\LoggerInterface;
10
11
/**
12
 * Interact jira server with REST API.
13
 */
14
class JiraClient
15
{
16
    /**
17
     * Json Mapper.
18
     *
19
     * @var \JsonMapper
20
     */
21
    protected $json_mapper;
22
23
    /**
24
     * HTTP response code.
25
     *
26
     * @var string
27
     */
28
    protected $http_response;
29
30
    /**
31
     * JIRA REST API URI.
32
     *
33
     * @var string
34
     */
35
    private $api_uri = '/rest/api/2';
36
37
    /**
38
     * CURL instance.
39
     *
40
     * @var resource
41
     */
42
    protected $curl;
43
44
    /**
45
     * Monolog instance.
46
     *
47
     * @var \Monolog\Logger
48
     */
49
    protected $log;
50
51
    /**
52
     * Jira Rest API Configuration.
53
     *
54
     * @var ConfigurationInterface
55
     */
56
    protected $configuration;
57
58
    /**
59
     * Constructor.
60
     *
61
     * @param ConfigurationInterface $configuration
62
     * @param LoggerInterface        $logger
63
     * @param string                 $path
64
     *
65
     * @throws JiraException
66
     * @throws \Exception
67
     */
68
    public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './')
69
    {
70
        if ($configuration === null) {
71
            if (!file_exists($path.'.env')) {
72
                // If calling the getcwd() on laravel it will returning the 'public' directory.
73
                $path = '../';
74
            }
75
            $this->configuration = new DotEnvConfiguration($path);
76
        } else {
77
            $this->configuration = $configuration;
78
        }
79
80
        $this->json_mapper = new \JsonMapper();
81
82
        // Fix "\JiraRestApi\JsonMapperHelper::class" syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$'
83
        $this->json_mapper->undefinedPropertyHandler = [new \JiraRestApi\JsonMapperHelper(), 'setUndefinedProperty'];
84
85
        // Properties that are annotated with `@var \DateTimeInterface` should result in \DateTime objects being created.
86
        $this->json_mapper->classMap['\\'.\DateTimeInterface::class] = \DateTime::class;
87
88
        // create logger
89
        if ($this->configuration->getJiraLogEnabled()) {
90
            if ($logger) {
91
                $this->log = $logger;
0 ignored issues
show
Documentation Bug introduced by
$logger is of type Psr\Log\LoggerInterface, but the property $log was declared to be of type Monolog\Logger. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
92
            } else {
93
                $this->log = new Logger('JiraClient');
94
                $this->log->pushHandler(new StreamHandler(
95
                    $this->configuration->getJiraLogFile(),
96
                    $this->convertLogLevel($this->configuration->getJiraLogLevel())
97
                ));
98
            }
99
        } else {
100
            $this->log = new Logger('JiraClient');
101
            $this->log->pushHandler(new NoOperationMonologHandler());
102
        }
103
104
        $this->http_response = 200;
105
106
        if ($this->configuration->getUseV3RestApi()) {
107
            $this->setRestApiV3();
108
        }
109
110
        $this->curl = curl_init();
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_init() can also be of type false. However, the property $curl is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
111
    }
112
113
    /**
114
     * Convert log level.
115
     *
116
     * @param $log_level
117
     *
118
     * @return int
119
     */
120
    private function convertLogLevel($log_level)
121
    {
122
        $log_level = strtoupper($log_level);
123
124
        switch ($log_level) {
125
            case 'EMERGENCY':
126
                return Logger::EMERGENCY;
127
            case 'ALERT':
128
                return Logger::ALERT;
129
            case 'CRITICAL':
130
                return Logger::CRITICAL;
131
            case 'ERROR':
132
                return Logger::ERROR;
133
            case 'WARNING':
134
                return Logger::WARNING;
135
            case 'NOTICE':
136
                return Logger::NOTICE;
137
            case 'DEBUG':
138
                return Logger::DEBUG;
139
            case 'INFO':
140
                return Logger::INFO;
141
            default:
142
                return Logger::WARNING;
143
        }
144
    }
145
146
    /**
147
     * Serilize only not null field.
148
     *
149
     * @param array $haystack
150
     *
151
     * @return array
152
     */
153
    protected function filterNullVariable($haystack)
154
    {
155
        foreach ($haystack as $key => $value) {
156
            if (is_array($value)) {
157
                $haystack[$key] = $this->filterNullVariable($haystack[$key]);
158
            } elseif (is_object($value)) {
159
                $haystack[$key] = $this->filterNullVariable(get_class_vars(get_class($value)));
160
            }
161
162
            if (is_null($haystack[$key]) || empty($haystack[$key])) {
163
                unset($haystack[$key]);
164
            }
165
        }
166
167
        return $haystack;
168
    }
169
170
    /**
171
     * Execute REST request.
172
     *
173
     * @param string $context        Rest API context (ex.:issue, search, etc..)
174
     * @param string $post_data
175
     * @param string $custom_request [PUT|DELETE]
176
     * @param string $cookieFile     cookie file
177
     *
178
     * @throws JiraException
179
     *
180
     * @return string
181
     */
182
    public function exec($context, $post_data = null, $custom_request = null, $cookieFile = null)
183
    {
184
        $url = $this->createUrlByContext($context);
185
186
        if (is_string($post_data)) {
187
            $this->log->info("Curl $custom_request: $url JsonData=".$post_data);
188
        } elseif (is_array($post_data)) {
0 ignored issues
show
introduced by
The condition is_array($post_data) is always false.
Loading history...
189
            $this->log->info("Curl $custom_request: $url JsonData=".json_encode($post_data, JSON_UNESCAPED_UNICODE));
190
        }
191
192
        curl_reset($this->curl);
193
        $ch = $this->curl;
194
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
195
        curl_setopt($ch, CURLOPT_URL, $url);
196
197
        // post_data
198
        if (!is_null($post_data)) {
199
            // PUT REQUEST
200
            if (!is_null($custom_request) && $custom_request == 'PUT') {
201
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
202
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
203
            }
204
            if (!is_null($custom_request) && $custom_request == 'DELETE') {
205
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
206
            } else {
207
                curl_setopt($ch, CURLOPT_POST, true);
208
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
209
            }
210
        } else {
211
            if (!is_null($custom_request) && $custom_request == 'DELETE') {
212
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
213
            }
214
        }
215
216
        $this->authorization($ch, $cookieFile);
217
218
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
219
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
220
        curl_setopt($ch, CURLOPT_USERAGENT, $this->getConfiguration()->getCurlOptUserAgent());
221
222
        // curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set
223
        if (!function_exists('ini_get') || !ini_get('open_basedir')) {
224
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
225
        }
226
227
        curl_setopt($ch, CURLOPT_ENCODING, '');
228
        curl_setopt($ch, CURLOPT_HTTPHEADER,
229
            ['Accept: */*', 'Content-Type: application/json', 'X-Atlassian-Token: no-check']);
230
231
        curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
232
233
        // Add proxy settings to the curl.
234
        $this->proxyConfigCurlHandle($ch);
235
236
        $this->log->debug('Curl exec='.$url);
237
        $response = curl_exec($ch);
238
239
        // if request failed or have no result.
240
        if (!$response) {
241
            $this->http_response = curl_getinfo($ch, CURLINFO_HTTP_CODE);
242
            $body = curl_error($ch);
243
244
            /*
245
             * 201: The request has been fulfilled, resulting in the creation of a new resource.
246
             * 204: The server successfully processed the request, but is not returning any content.
247
             */
248
            if ($this->http_response === 204 || $this->http_response === 201 || $this->http_response === 200) {
249
                return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type string.
Loading history...
250
            }
251
252
            // HostNotFound, No route to Host, etc Network error
253
            $msg = sprintf('CURL Error: http response=%d, %s', $this->http_response, $body);
254
255
            $this->log->error($msg);
256
257
            throw new JiraException($msg);
258
        } else {
259
            // if request was ok, parsing http response code.
260
            $this->http_response = curl_getinfo($ch, CURLINFO_HTTP_CODE);
261
262
            // don't check 301, 302 because setting CURLOPT_FOLLOWLOCATION
263
            if ($this->http_response != 200 && $this->http_response != 201) {
264
                throw new JiraException('CURL HTTP Request Failed: Status Code : '
265
                    .$this->http_response.', URL:'.$url
266
                    ."\nError Message : ".$response, $this->http_response);
0 ignored issues
show
Bug introduced by
Are you sure $response of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

266
                    ."\nError Message : "./** @scrutinizer ignore-type */ $response, $this->http_response);
Loading history...
267
            }
268
        }
269
270
        return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response also could return the type true which is incompatible with the documented return type string.
Loading history...
271
    }
272
273
    /**
274
     * Create upload handle.
275
     *
276
     * @param string $url         Request URL
277
     * @param string $upload_file Filename
278
     *
279
     * @return resource
280
     */
281
    private function createUploadHandle($url, $upload_file, $ch)
282
    {
283
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
284
        curl_setopt($ch, CURLOPT_URL, $url);
285
286
        // send file
287
        curl_setopt($ch, CURLOPT_POST, true);
288
289
        if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 5) {
290
            $attachments = realpath($upload_file);
291
            $filename = basename($upload_file);
292
293
            curl_setopt($ch, CURLOPT_POSTFIELDS,
294
                ['file' => '@'.$attachments.';filename='.$filename]);
295
296
            $this->log->debug('using legacy file upload');
297
        } else {
298
            // CURLFile require PHP > 5.5
299
            $attachments = new \CURLFile(realpath($upload_file));
300
            $attachments->setPostFilename(basename($upload_file));
301
302
            curl_setopt($ch, CURLOPT_POSTFIELDS,
303
                ['file' => $attachments]);
304
305
            $this->log->debug('using CURLFile='.var_export($attachments, true));
306
        }
307
308
        $this->authorization($ch);
309
310
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
311
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
312
313
        $this->proxyConfigCurlHandle($ch);
314
315
        // curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); cannot be activated when an open_basedir is set
316
        if (!function_exists('ini_get') || !ini_get('open_basedir')) {
317
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
318
        }
319
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
320
            'Accept: */*',
321
            'Content-Type: multipart/form-data',
322
            'X-Atlassian-Token: nocheck',
323
        ]);
324
325
        curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
326
327
        $this->log->debug('Curl exec='.$url);
328
329
        return $ch;
330
    }
331
332
    /**
333
     * File upload.
334
     *
335
     * @param string $context       url context
336
     * @param array  $filePathArray upload file path.
337
     *
338
     * @throws JiraException
339
     *
340
     * @return array
341
     */
342
    public function upload($context, $filePathArray)
343
    {
344
        $url = $this->createUrlByContext($context);
345
346
        $results = [];
347
348
        $ch = curl_init();
349
350
        $this->multi = NULL;
0 ignored issues
show
Bug Best Practice introduced by
The property multi does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
351
352
        $idx = 0;
353
        foreach ($filePathArray as $file) {
354
            $this->createUploadHandle($url, $file, $ch);
355
356
            $response = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

356
            $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
357
358
            // if request failed or have no result.
359
            if (!$response) {
360
                $http_response = curl_getinfo($ch, CURLINFO_HTTP_CODE);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_getinfo() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

360
                $http_response = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_HTTP_CODE);
Loading history...
361
                $body = curl_error($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_error() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

361
                $body = curl_error(/** @scrutinizer ignore-type */ $ch);
Loading history...
362
363
                if ($http_response === 204 || $http_response === 201 || $http_response === 200) {
364
                    $results[$idx] = $response;
365
                } else {
366
                    $msg = sprintf('CURL Error: http response=%d, %s', $http_response, $body);
367
                    $this->log->error($msg);
368
369
                    curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

369
                    curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
370
371
                    throw new JiraException($msg);
372
                }
373
            } else {
374
                $results[$idx] = $response;
375
            }
376
        }
377
378
        curl_close($ch);
379
380
        return $results;
381
    }
382
383
    /**
384
     * @param array $chArr
385
     * @param $mh
386
     * @param $body
387
     * @param $result_code
388
     *
389
     * @throws \JiraRestApi\JiraException
390
     */
391
    protected function closeCURLHandle(array $chArr, $mh, $body, $result_code)
392
    {
393
        foreach ($chArr as $ch) {
394
            $this->log->debug('CURL Close handle..');
395
            curl_multi_remove_handle($mh, $ch);
396
        }
397
        $this->log->debug('CURL Multi Close handle..');
398
        curl_multi_close($mh);
399
        if ($result_code != 200) {
400
            // @TODO $body might have not been defined
401
            throw new JiraException('CURL Error: = '.$body, $result_code);
402
        }
403
    }
404
405
    /**
406
     * Get URL by context.
407
     *
408
     * @param string $context
409
     *
410
     * @return string
411
     */
412
    protected function createUrlByContext($context)
413
    {
414
        $host = $this->getConfiguration()->getJiraHost();
415
416
        return $host.$this->api_uri.'/'.preg_replace('/\//', '', $context, 1);
417
    }
418
419
    /**
420
     * Add authorize to curl request.
421
     *
422
     * @param resource $ch
423
     */
424
    protected function authorization($ch, $cookieFile = null)
425
    {
426
        // use cookie
427
        if ($this->getConfiguration()->isCookieAuthorizationEnabled()) {
428
            if ($cookieFile === null) {
429
                $cookieFile = $this->getConfiguration()->getCookieFile();
430
            }
431
432
            curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
433
            curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
434
435
            $this->log->debug('Using cookie..');
436
        }
437
438
        // if cookie file not exist, using id/pwd login
439
        if (!file_exists($cookieFile)) {
440
            $username = $this->getConfiguration()->getJiraUser();
441
            $password = $this->getConfiguration()->getJiraPassword();
442
            curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
443
        }
444
    }
445
446
    /**
447
     * Jira Rest API Configuration.
448
     *
449
     * @return ConfigurationInterface
450
     */
451
    public function getConfiguration()
452
    {
453
        return $this->configuration;
454
    }
455
456
    /**
457
     * Set a custom Jira API URI for the request.
458
     *
459
     * @param string $api_uri
460
     */
461
    public function setAPIUri($api_uri)
462
    {
463
        $this->api_uri = $api_uri;
464
    }
465
466
    /**
467
     * convert to query array to http query parameter.
468
     *
469
     * @param $paramArray
470
     *
471
     * @return string
472
     */
473
    public function toHttpQueryParameter($paramArray)
474
    {
475
        $queryParam = '?';
476
477
        foreach ($paramArray as $key => $value) {
478
            $v = null;
479
480
            // some param field(Ex: expand) type is array.
481
            if (is_array($value)) {
482
                $v = implode(',', $value);
483
            } else {
484
                $v = $value;
485
            }
486
487
            $queryParam .= $key.'='.$v.'&';
488
        }
489
490
        return $queryParam;
491
    }
492
493
    /**
494
     * download and save into outDir.
495
     *
496
     * @param $url full url
0 ignored issues
show
Bug introduced by
The type JiraRestApi\full was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
497
     * @param $outDir save dir
498
     * @param $file save filename
0 ignored issues
show
Bug introduced by
The type JiraRestApi\save was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
499
     * @param $cookieFile cookie filename
0 ignored issues
show
Bug introduced by
The type JiraRestApi\cookie was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
500
     *
501
     * @throws JiraException
502
     *
503
     * @return bool|mixed
504
     */
505
    public function download($url, $outDir, $file, $cookieFile = null)
506
    {
507
        $file = fopen($outDir.DIRECTORY_SEPARATOR.$file, 'w');
508
509
        curl_reset($this->curl);
510
        $ch = $this->curl;
511
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
512
        curl_setopt($ch, CURLOPT_URL, $url);
513
514
        // output to file handle
515
        curl_setopt($ch, CURLOPT_FILE, $file);
516
517
        $this->authorization($ch, $cookieFile);
518
519
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
520
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
521
        $this->proxyConfigCurlHandle($ch);
522
523
        // curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set
524
        if (!function_exists('ini_get') || !ini_get('open_basedir')) {
525
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
526
        }
527
528
        curl_setopt($ch, CURLOPT_HTTPHEADER,
529
            ['Accept: */*', 'Content-Type: application/json', 'X-Atlassian-Token: no-check']);
530
531
        curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
532
533
        if ($this->isRestApiV3()) {
534
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-atlassian-force-account-id: true']);
535
        }
536
537
        $this->log->debug('Curl exec='.$url);
538
        $response = curl_exec($ch);
539
540
        // if request failed.
541
        if (!$response) {
542
            $this->http_response = curl_getinfo($ch, CURLINFO_HTTP_CODE);
543
            $body = curl_error($ch);
544
            fclose($file);
0 ignored issues
show
Bug introduced by
It seems like $file can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

544
            fclose(/** @scrutinizer ignore-type */ $file);
Loading history...
545
546
            /*
547
             * 201: The request has been fulfilled, resulting in the creation of a new resource.
548
             * 204: The server successfully processed the request, but is not returning any content.
549
             */
550
            if ($this->http_response === 204 || $this->http_response === 201) {
551
                return true;
552
            }
553
554
            // HostNotFound, No route to Host, etc Network error
555
            $msg = sprintf('CURL Error: http response=%d, %s', $this->http_response, $body);
556
557
            $this->log->error($msg);
558
559
            throw new JiraException($msg);
560
        } else {
561
            // if request was ok, parsing http response code.
562
            $this->http_response = curl_getinfo($ch, CURLINFO_HTTP_CODE);
563
            fclose($file);
564
565
            // don't check 301, 302 because setting CURLOPT_FOLLOWLOCATION
566
            if ($this->http_response != 200 && $this->http_response != 201) {
567
                throw new JiraException('CURL HTTP Request Failed: Status Code : '
568
                    .$this->http_response.', URL:'.$url
569
                    ."\nError Message : ".$response, $this->http_response);
0 ignored issues
show
Bug introduced by
Are you sure $response of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

569
                    ."\nError Message : "./** @scrutinizer ignore-type */ $response, $this->http_response);
Loading history...
570
            }
571
        }
572
573
        return $response;
574
    }
575
576
    /**
577
     * setting cookie file path.
578
     *
579
     * @param $cookieFile
580
     *
581
     * @return $this
582
     */
583
    public function setCookieFile($cookieFile)
584
    {
585
        $this->cookieFile = $cookieFile;
0 ignored issues
show
Bug Best Practice introduced by
The property cookieFile does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
586
587
        return $this;
588
    }
589
590
    /**
591
     * Config a curl handle with proxy configuration (if set) from ConfigurationInterface.
592
     *
593
     * @param $ch
594
     */
595
    private function proxyConfigCurlHandle($ch)
596
    {
597
        // Add proxy settings to the curl.
598
        if ($this->getConfiguration()->getProxyServer()) {
599
            curl_setopt($ch, CURLOPT_PROXY, $this->getConfiguration()->getProxyServer());
600
            curl_setopt($ch, CURLOPT_PROXYPORT, $this->getConfiguration()->getProxyPort());
601
602
            $username = $this->getConfiguration()->getProxyUser();
603
            $password = $this->getConfiguration()->getProxyPassword();
604
            curl_setopt($ch, CURLOPT_PROXYUSERPWD, "$username:$password");
605
        }
606
    }
607
608
    /**
609
     * setting REST API url to V3.
610
     *
611
     * @return $this
612
     */
613
    public function setRestApiV3()
614
    {
615
        $this->api_uri = '/rest/api/3';
616
617
        return $this;
618
    }
619
620
    /**
621
     * check whether current API is v3.
622
     *
623
     * @return bool
624
     */
625
    public function isRestApiV3()
626
    {
627
        return $this->configuration->getUseV3RestApi();
628
    }
629
}
630