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

IssueService   F

Complexity

Total Complexity 65

Size/Duplication

Total Lines 1105
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 295
dl 0
loc 1105
rs 3.2
c 0
b 0
f 0
wmc 65

41 Methods

Rating   Name   Duplication   Size   Complexity  
A getIssueFromJSON() 0 7 1
A addWorklog() 0 15 1
A getCreateMeta() 0 10 2
A getWatchers() 0 13 1
A changeAssignee() 0 13 1
A getAllPriorities() 0 9 1
A timeTracking() 0 18 1
A getTransition() 0 13 1
A getIssueSecuritySchemes() 0 11 1
A removeWatcher() 0 9 2
A notify() 0 20 4
A update() 0 18 1
A deleteIssue() 0 11 1
A createMultiple() 0 18 3
A getCustomFields() 0 11 1
A bulkInsert() 0 13 2
A findTransitonId() 0 18 3
A get() 0 15 4
A createOrUpdateRemoteIssueLink() 0 15 1
A search() 0 19 1
A addWatcher() 0 11 2
A removeRemoteIssueLink() 0 18 1
A getPriority() 0 11 1
A getEditMeta() 0 21 1
A updateComment() 0 14 1
A getAllIssueSecuritySchemes() 0 16 1
A getWorklog() 0 9 1
A getRemoteIssueLink() 0 11 1
A getComments() 0 12 1
A deleteComment() 0 9 1
A getComment() 0 12 1
A create() 0 14 1
A editWorklog() 0 15 1
A getWorklogById() 0 9 1
A getTimeTracking() 0 10 1
A addAttachments() 0 30 6
A addComment() 0 14 1
A transition() 0 17 2
A updateFixVersions() 0 24 3
A updateLabels() 0 24 3
A changeAssigneeByAccountId() 0 13 1

How to fix   Complexity   

Complex Class

Complex classes like IssueService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use IssueService, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace JiraRestApi\Issue;
4
5
use JiraRestApi\JiraException;
6
7
class IssueService extends \JiraRestApi\JiraClient
8
{
9
    private $uri = '/issue';
10
11
    /**
12
     * @param $json
13
     *
14
     * @throws \JsonMapper_Exception
15
     *
16
     * @return Issue|object
17
     */
18
    public function getIssueFromJSON($json)
19
    {
20
        $issue = $this->json_mapper->map(
21
            $json, new Issue()
22
        );
23
24
        return $issue;
25
    }
26
27
    /**
28
     *  get all project list.
29
     *
30
     * @param string|int $issueIdOrKey
31
     * @param array      $paramArray   Query Parameter key-value Array.
32
     * @param Issue      $issueObject
33
     *
34
     * @throws JiraException
35
     * @throws \JsonMapper_Exception
36
     *
37
     * @return Issue|object class
38
     */
39
    public function get($issueIdOrKey, $paramArray = [], $issueObject = null)
40
    {
41
        // for REST API V3
42
        if ($this->isRestApiV3()) {
43
            $issueObject = ($issueObject) ? $issueObject : new IssueV3();
44
        } else {
45
            $issueObject = ($issueObject) ? $issueObject : new Issue();
46
        }
47
48
        $ret = $this->exec($this->uri.'/'.$issueIdOrKey.$this->toHttpQueryParameter($paramArray), null);
49
50
        $this->log->info("Result=\n".$ret);
51
52
        return $issue = $this->json_mapper->map(
0 ignored issues
show
Unused Code introduced by
The assignment to $issue is dead and can be removed.
Loading history...
53
            json_decode($ret), $issueObject
54
        );
55
    }
56
57
    /**
58
     * create new issue.
59
     *
60
     * @param IssueField $issueField
61
     *
62
     * @throws JiraException
63
     * @throws \JsonMapper_Exception
64
     *
65
     * @return Issue|object created issue key
66
     */
67
    public function create($issueField)
68
    {
69
        $issue = new Issue();
70
71
        // serilize only not null field.
72
        $issue->fields = $issueField;
73
74
        $data = json_encode($issue);
75
76
        $this->log->info("Create Issue=\n".$data);
77
78
        $ret = $this->exec($this->uri, $data, 'POST');
79
80
        return $this->getIssueFromJSON(json_decode($ret));
81
    }
82
83
    /**
84
     * Create multiple issues using bulk insert.
85
     *
86
     * @param IssueField[] $issueFields Array of IssueField objects
87
     * @param int          $batchSize   Maximum number of issues to send in each request
88
     *
89
     * @throws JiraException
90
     * @throws \JsonMapper_Exception
91
     *
92
     * @return array Array of results, where each result represents one batch of insertions
93
     */
94
    public function createMultiple($issueFields, $batchSize = 50)
95
    {
96
        $issues = [];
97
98
        foreach ($issueFields as $issueField) {
99
            $issue = new Issue();
100
            $issue->fields = $issueField;
101
            $issues[] = $issue;
102
        }
103
104
        $batches = array_chunk($issues, $batchSize);
105
106
        $results = [];
107
        foreach ($batches as $batch) {
108
            $results = array_merge($results, $this->bulkInsert($batch));
109
        }
110
111
        return $results;
112
    }
113
114
    /**
115
     * Makes API call to bulk insert issues.
116
     *
117
     * @param Issue[] $issues Array of issue arrays that are sent to Jira one by one in single create
118
     *
119
     * @throws JiraException
120
     * @throws \JsonMapper_Exception
121
     *
122
     * @return Issue[] Result of API call to insert many issues
123
     */
124
    private function bulkInsert($issues)
125
    {
126
        $data = json_encode(['issueUpdates' => $issues]);
127
128
        $this->log->info("Create Issues=\n".$data);
129
        $results = $this->exec($this->uri.'/bulk', $data, 'POST');
130
131
        $issues = [];
132
        foreach (json_decode($results)->issues as $result) {
133
            $issues[] = $this->getIssueFromJSON($result);
134
        }
135
136
        return $issues;
137
    }
138
139
    /**
140
     * Add one or more file to an issue.
141
     *
142
     * @param string|int   $issueIdOrKey  Issue id or key
143
     * @param array|string $filePathArray attachment file path.
144
     *
145
     * @throws JiraException
146
     * @throws \JsonMapper_Exception
147
     *
148
     * @return Attachment[]
149
     */
150
    public function addAttachments($issueIdOrKey, $filePathArray)
151
    {
152
        if (is_array($filePathArray) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
153
            $filePathArray = [$filePathArray];
154
        }
155
156
        $results = $this->upload($this->uri."/$issueIdOrKey/attachments", $filePathArray);
0 ignored issues
show
Bug introduced by
It seems like $filePathArray can also be of type string; however, parameter $filePathArray of JiraRestApi\JiraClient::upload() does only seem to accept array, 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

156
        $results = $this->upload($this->uri."/$issueIdOrKey/attachments", /** @scrutinizer ignore-type */ $filePathArray);
Loading history...
157
158
        $this->log->info('addAttachments result='.var_export($results, true));
159
160
        $attachArr = [];
161
        foreach ($results as $ret) {
162
            $ret = json_decode($ret);
163
            if (is_array($ret)) {
164
                $tmpArr = $this->json_mapper->mapArray(
165
                    $ret, new \ArrayObject(), '\JiraRestApi\Issue\Attachment'
166
                );
167
168
                foreach ($tmpArr as $t) {
169
                    array_push($attachArr, $t);
170
                }
171
            } elseif (is_object($ret)) {
172
                array_push($attachArr, $this->json_mapper->map(
173
                    $ret, new Attachment()
174
                    )
175
                );
176
            }
177
        }
178
179
        return $attachArr;
180
    }
181
182
    /**
183
     * update issue.
184
     *
185
     * @param string|int $issueIdOrKey Issue Key
186
     * @param IssueField $issueField   object of Issue class
187
     * @param array      $paramArray   Query Parameter key-value Array.
188
     *
189
     * @throws JiraException
190
     *
191
     * @return string created issue key
192
     */
193
    public function update($issueIdOrKey, $issueField, $paramArray = [])
194
    {
195
        $issue = new Issue();
196
197
        // serilize only not null field.
198
        $issue->fields = $issueField;
199
200
        //$issue = $this->filterNullVariable((array)$issue);
201
202
        $data = json_encode($issue);
203
204
        $this->log->info("Update Issue=\n".$data);
205
206
        $queryParam = '?'.http_build_query($paramArray);
207
208
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, $data, 'PUT');
209
210
        return $ret;
211
    }
212
213
    /**
214
     * Adds a new comment to an issue.
215
     *
216
     * @param string|int $issueIdOrKey Issue id or key
217
     * @param string     $comment
218
     *
219
     * @throws JiraException
220
     * @throws \JsonMapper_Exception
221
     *
222
     * @return Comment|object Comment class
223
     */
224
    public function addComment($issueIdOrKey, $comment)
225
    {
226
        $this->log->info("addComment=\n");
227
228
        $data = json_encode($comment);
229
230
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment", $data);
231
232
        $this->log->debug('add comment result='.var_export($ret, true));
233
        $comment = $this->json_mapper->map(
234
           json_decode($ret), new Comment()
235
        );
236
237
        return $comment;
238
    }
239
240
    /**
241
     * Update a comment in issue.
242
     *
243
     * @param string|int $issueIdOrKey Issue id or key
244
     * @param string|int $id           Comment id
245
     * @param string     $comment
246
     *
247
     * @throws JiraException
248
     * @throws \JsonMapper_Exception
249
     *
250
     * @return Comment|object Comment class
251
     */
252
    public function updateComment($issueIdOrKey, $id, $comment)
253
    {
254
        $this->log->info("updateComment=\n");
255
256
        $data = json_encode($comment);
257
258
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id", $data, 'PUT');
259
260
        $this->log->debug('update comment result='.var_export($ret, true));
261
        $comment = $this->json_mapper->map(
262
            json_decode($ret), new Comment()
263
        );
264
265
        return $comment;
266
    }
267
268
    /**
269
     * Get a comment on an issue.
270
     *
271
     * @param string|int $issueIdOrKey Issue id or key
272
     * @param string|int $id           Comment id
273
     *
274
     * @throws JiraException
275
     * @throws \JsonMapper_Exception
276
     *
277
     * @return Comment|object Comment class
278
     */
279
    public function getComment($issueIdOrKey, $id)
280
    {
281
        $this->log->info("getComment=\n");
282
283
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id");
284
285
        $this->log->debug('get comment result='.var_export($ret, true));
286
        $comment = $this->json_mapper->map(
287
                json_decode($ret), new Comment()
288
                );
289
290
        return $comment;
291
    }
292
293
    /**
294
     * Get all comments on an issue.
295
     *
296
     * @param string|int $issueIdOrKey Issue id or key
297
     *
298
     * @throws JiraException
299
     * @throws \JsonMapper_Exception
300
     *
301
     * @return Comment|object Comment class
302
     */
303
    public function getComments($issueIdOrKey)
304
    {
305
        $this->log->info("getComments=\n");
306
307
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment");
308
309
        $this->log->debug('get comments result='.var_export($ret, true));
310
        $comment = $this->json_mapper->map(
311
                json_decode($ret), new Comment()
312
                );
313
314
        return $comment;
315
    }
316
317
    /**
318
     * Delete a comment on an issue.
319
     *
320
     * @param string|int $issueIdOrKey Issue id or key
321
     * @param string|int $id           Comment id
322
     *
323
     * @throws JiraException
324
     *
325
     * @return string|bool
326
     */
327
    public function deleteComment($issueIdOrKey, $id)
328
    {
329
        $this->log->info("deleteComment=\n");
330
331
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id", '', 'DELETE');
332
333
        $this->log->info('delete comment '.$issueIdOrKey.' '.$id.' result='.var_export($ret, true));
334
335
        return $ret;
336
    }
337
338
    /**
339
     * Change a issue assignee.
340
     *
341
     * @param string|int  $issueIdOrKey
342
     * @param string|null $assigneeName Assigns an issue to a user.
343
     *                                  If the assigneeName is "-1" automatic assignee is used.
344
     *                                  A null name will remove the assignee.
345
     *
346
     * @throws JiraException
347
     *
348
     * @return string|bool
349
     */
350
    public function changeAssignee($issueIdOrKey, $assigneeName)
351
    {
352
        $this->log->info("changeAssignee=\n");
353
354
        $ar = ['name' => $assigneeName];
355
356
        $data = json_encode($ar);
357
358
        $ret = $this->exec($this->uri."/$issueIdOrKey/assignee", $data, 'PUT');
359
360
        $this->log->info('change assignee of '.$issueIdOrKey.' to '.$assigneeName.' result='.var_export($ret, true));
361
362
        return $ret;
363
    }
364
365
    /**
366
     * Change a issue assignee for REST API V3.
367
     *
368
     * @param string|int  $issueIdOrKey
369
     * @param string|null $accountId    Assigns an issue to a user.
370
     *
371
     * @throws JiraException
372
     *
373
     * @return string
374
     */
375
    public function changeAssigneeByAccountId($issueIdOrKey, $accountId)
376
    {
377
        $this->log->info("changeAssigneeByAccountId=\n");
378
379
        $ar = ['accountId' => $accountId];
380
381
        $data = json_encode($ar);
382
383
        $ret = $this->exec($this->uri."/$issueIdOrKey/assignee", $data, 'PUT');
384
385
        $this->log->info('change assignee of '.$issueIdOrKey.' to '.$accountId.' result='.var_export($ret, true));
386
387
        return $ret;
388
    }
389
390
    /**
391
     * Delete a issue.
392
     *
393
     * @param string|int $issueIdOrKey Issue id or key
394
     * @param array      $paramArray   Query Parameter key-value Array.
395
     *
396
     * @throws JiraException
397
     *
398
     * @return string|bool
399
     */
400
    public function deleteIssue($issueIdOrKey, $paramArray = [])
401
    {
402
        $this->log->info("deleteIssue=\n");
403
404
        $queryParam = '?'.http_build_query($paramArray);
405
406
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, '', 'DELETE');
407
408
        $this->log->info('delete issue '.$issueIdOrKey.' result='.var_export($ret, true));
409
410
        return $ret;
411
    }
412
413
    /**
414
     * Get a list of the transitions possible for this issue by the current user, along with fields that are required and their types.
415
     *
416
     * @param string|int $issueIdOrKey Issue id or key
417
     *
418
     * @throws JiraException
419
     *
420
     * @return Transition[] array of Transition class
421
     */
422
    public function getTransition($issueIdOrKey)
423
    {
424
        $ret = $this->exec($this->uri."/$issueIdOrKey/transitions");
425
426
        $this->log->debug('getTransitions result='.var_export($ret, true));
427
428
        $data = json_encode(json_decode($ret)->transitions);
429
430
        $transitions = $this->json_mapper->mapArray(
431
           json_decode($data), new \ArrayObject(), '\JiraRestApi\Issue\Transition'
432
        );
433
434
        return $transitions;
435
    }
436
437
    /**
438
     * find transition id by transition's to field name(aka 'Resolved').
439
     *
440
     * @param string|int $issueIdOrKey
441
     * @param string     $transitionToName
442
     *
443
     * @throws JiraException
444
     *
445
     * @return string
446
     */
447
    public function findTransitonId($issueIdOrKey, $transitionToName)
448
    {
449
        $this->log->debug('findTransitonId=');
450
451
        $ret = $this->getTransition($issueIdOrKey);
452
453
        foreach ($ret as $trans) {
454
            $toName = $trans->to->name;
455
456
            $this->log->debug('getTransitions result='.var_export($ret, true));
457
458
            if (strcmp($toName, $transitionToName) == 0) {
459
                return $trans->id;
460
            }
461
        }
462
463
        // transition keyword not found
464
        throw new JiraException("Transition name '$transitionToName' not found on JIRA Server.");
465
    }
466
467
    /**
468
     * Perform a transition on an issue.
469
     *
470
     * @param string|int $issueIdOrKey Issue id or key
471
     * @param Transition $transition
472
     *
473
     * @throws JiraException
474
     *
475
     * @return string|null nothing - if transition was successful return http 204(no contents)
476
     */
477
    public function transition($issueIdOrKey, $transition)
478
    {
479
        $this->log->debug('transition='.var_export($transition, true));
480
481
        if (!isset($transition->transition['id'])) {
482
            $transition->transition['id'] = $this->findTransitonId($issueIdOrKey, $transition->transition['name']);
483
        }
484
485
        $data = json_encode($transition);
486
487
        $this->log->debug("transition req=$data\n");
488
489
        $ret = $this->exec($this->uri."/$issueIdOrKey/transitions", $data, 'POST');
490
491
        $this->log->debug('getTransitions result='.var_export($ret, true));
492
493
        return $ret;
494
    }
495
496
    /**
497
     * Search issues.
498
     *
499
     * @param string $jql
500
     * @param int    $startAt
501
     * @param int    $maxResults
502
     * @param array  $fields
503
     * @param array  $expand
504
     * @param bool   $validateQuery
505
     *
506
     * @throws JiraException
507
     * @throws \JsonMapper_Exception
508
     *
509
     * @return IssueSearchResult|object
510
     */
511
    public function search($jql, $startAt = 0, $maxResults = 15, $fields = [], $expand = [], $validateQuery = true)
512
    {
513
        $data = json_encode([
514
            'jql'           => $jql,
515
            'startAt'       => $startAt,
516
            'maxResults'    => $maxResults,
517
            'fields'        => $fields,
518
            'expand'        => $expand,
519
            'validateQuery' => $validateQuery,
520
        ]);
521
522
        $ret = $this->exec('search', $data, 'POST');
523
        $json = json_decode($ret);
524
525
        $result = $this->json_mapper->map(
526
            $json, new IssueSearchResult()
527
        );
528
529
        return $result;
530
    }
531
532
    /**
533
     * get TimeTracking info.
534
     *
535
     * @param string|int $issueIdOrKey
536
     *
537
     * @throws JiraException
538
     * @throws \JsonMapper_Exception
539
     *
540
     * @return TimeTracking
541
     */
542
    public function getTimeTracking($issueIdOrKey)
543
    {
544
        $ret = $this->exec($this->uri."/$issueIdOrKey", null);
545
        $this->log->debug("getTimeTracking res=$ret\n");
546
547
        $issue = $this->json_mapper->map(
548
             json_decode($ret), new Issue()
549
        );
550
551
        return $issue->fields->timeTracking;
552
    }
553
554
    /**
555
     * TimeTracking issues.
556
     *
557
     * @param string|int   $issueIdOrKey Issue id or key
558
     * @param TimeTracking $timeTracking
559
     *
560
     * @throws JiraException
561
     *
562
     * @return string
563
     */
564
    public function timeTracking($issueIdOrKey, $timeTracking)
565
    {
566
        $array = [
567
            'update' => [
568
                'timetracking' => [
569
                    ['edit' => $timeTracking],
570
                ],
571
            ],
572
        ];
573
574
        $data = json_encode($array);
575
576
        $this->log->debug("TimeTracking req=$data\n");
577
578
        // if success, just return HTTP 201.
579
        $ret = $this->exec($this->uri."/$issueIdOrKey", $data, 'PUT');
580
581
        return $ret;
582
    }
583
584
    /**
585
     * get getWorklog.
586
     *
587
     * @param string|int $issueIdOrKey
588
     *
589
     * @throws JiraException
590
     * @throws \JsonMapper_Exception
591
     *
592
     * @return PaginatedWorklog|object
593
     */
594
    public function getWorklog($issueIdOrKey)
595
    {
596
        $ret = $this->exec($this->uri."/$issueIdOrKey/worklog");
597
        $this->log->debug("getWorklog res=$ret\n");
598
        $worklog = $this->json_mapper->map(
599
            json_decode($ret), new PaginatedWorklog()
600
        );
601
602
        return $worklog;
603
    }
604
605
    /**
606
     * get getWorklog by Id.
607
     *
608
     * @param string|int $issueIdOrKey
609
     * @param int        $workLogId
610
     *
611
     * @throws JiraException
612
     * @throws \JsonMapper_Exception
613
     *
614
     * @return Worklog|object PaginatedWorklog object
615
     */
616
    public function getWorklogById($issueIdOrKey, $workLogId)
617
    {
618
        $ret = $this->exec($this->uri."/$issueIdOrKey/worklog/$workLogId");
619
        $this->log->debug("getWorklogById res=$ret\n");
620
        $worklog = $this->json_mapper->map(
621
            json_decode($ret), new Worklog()
622
        );
623
624
        return $worklog;
625
    }
626
627
    /**
628
     * add work log to issue.
629
     *
630
     * @param string|int     $issueIdOrKey
631
     * @param Worklog|object $worklog
632
     *
633
     * @throws JiraException
634
     * @throws \JsonMapper_Exception
635
     *
636
     * @return Worklog|object Worklog Object
637
     */
638
    public function addWorklog($issueIdOrKey, $worklog)
639
    {
640
        $this->log->info("addWorklog=\n");
641
642
        $data = json_encode($worklog);
643
        $url = $this->uri."/$issueIdOrKey/worklog";
644
        $type = 'POST';
645
646
        $ret = $this->exec($url, $data, $type);
647
648
        $ret_worklog = $this->json_mapper->map(
649
           json_decode($ret), new Worklog()
650
        );
651
652
        return $ret_worklog;
653
    }
654
655
    /**
656
     * edit the worklog.
657
     *
658
     * @param string|int     $issueIdOrKey
659
     * @param Worklog|object $worklog
660
     * @param string|int     $worklogId
661
     *
662
     * @throws JiraException
663
     * @throws \JsonMapper_Exception
664
     *
665
     * @return Worklog|object
666
     */
667
    public function editWorklog($issueIdOrKey, $worklog, $worklogId)
668
    {
669
        $this->log->info("editWorklog=\n");
670
671
        $data = json_encode($worklog);
672
        $url = $this->uri."/$issueIdOrKey/worklog/$worklogId";
673
        $type = 'PUT';
674
675
        $ret = $this->exec($url, $data, $type);
676
677
        $ret_worklog = $this->json_mapper->map(
678
            json_decode($ret), new Worklog()
679
        );
680
681
        return $ret_worklog;
682
    }
683
684
    /**
685
     * Get all priorities.
686
     *
687
     * @throws JiraException
688
     *
689
     * @return Priority[] array of priority class
690
     */
691
    public function getAllPriorities()
692
    {
693
        $ret = $this->exec('priority', null);
694
695
        $priorities = $this->json_mapper->mapArray(
696
             json_decode($ret, false), new \ArrayObject(), '\JiraRestApi\Issue\Priority'
697
        );
698
699
        return $priorities;
700
    }
701
702
    /**
703
     * Get priority by id.
704
     * throws  HTTPException if the priority is not found, or the calling user does not have permission or view it.
705
     *
706
     * @param string|int $priorityId Id of priority.
707
     *
708
     * @throws JiraException
709
     * @throws \JsonMapper_Exception
710
     *
711
     * @return Priority|object priority
712
     */
713
    public function getPriority($priorityId)
714
    {
715
        $ret = $this->exec("priority/$priorityId", null);
716
717
        $this->log->info('Result='.$ret);
718
719
        $prio = $this->json_mapper->map(
720
             json_decode($ret), new Priority()
721
        );
722
723
        return $prio;
724
    }
725
726
    /**
727
     * Get priority by id.
728
     * throws HTTPException if the priority is not found, or the calling user does not have permission or view it.
729
     *
730
     * @param string|int $priorityId Id of priority.
731
     *
732
     * @throws JiraException
733
     * @throws \JsonMapper_Exception
734
     *
735
     * @return Priority|object priority
736
     */
737
    public function getCustomFields($priorityId)
738
    {
739
        $ret = $this->exec("priority/$priorityId", null);
740
741
        $this->log->info('Result='.$ret);
742
743
        $prio = $this->json_mapper->map(
744
            json_decode($ret), new Priority()
745
        );
746
747
        return $prio;
748
    }
749
750
    /**
751
     * get watchers.
752
     *
753
     * @param $issueIdOrKey
754
     *
755
     * @throws JiraException
756
     *
757
     * @return Reporter[]
758
     */
759
    public function getWatchers($issueIdOrKey)
760
    {
761
        $this->log->info("getWatchers=\n");
762
763
        $url = $this->uri."/$issueIdOrKey/watchers";
764
765
        $ret = $this->exec($url, null);
766
767
        $watchers = $this->json_mapper->mapArray(
768
            json_decode($ret, false)->watchers, new \ArrayObject(), '\JiraRestApi\Issue\Reporter'
769
        );
770
771
        return $watchers;
772
    }
773
774
    /**
775
     * add watcher to issue.
776
     *
777
     * @param string|int $issueIdOrKey
778
     * @param string     $watcher      watcher id
779
     *
780
     * @throws JiraException
781
     *
782
     * @return bool
783
     */
784
    public function addWatcher($issueIdOrKey, $watcher)
785
    {
786
        $this->log->info("addWatcher=\n");
787
788
        $data = json_encode($watcher);
789
        $url = $this->uri."/$issueIdOrKey/watchers";
790
        $type = 'POST';
791
792
        $this->exec($url, $data, $type);
793
794
        return $this->http_response == 204 ? true : false;
795
    }
796
797
    /**
798
     * remove watcher from issue.
799
     *
800
     * @param string|int $issueIdOrKey
801
     * @param string     $watcher      watcher id
802
     *
803
     * @throws JiraException
804
     *
805
     * @return bool
806
     */
807
    public function removeWatcher($issueIdOrKey, $watcher)
808
    {
809
        $this->log->addInfo("removeWatcher=\n");
810
811
        $ret = $this->exec($this->uri."/$issueIdOrKey/watchers/?username=$watcher", '', 'DELETE');
812
813
        $this->log->addInfo('remove watcher '.$issueIdOrKey.' result='.var_export($ret, true));
814
815
        return $this->http_response == 204 ? true : false;
816
    }
817
818
    /**
819
     * Get the meta data for creating issues.
820
     *
821
     * @param array $paramArray Possible keys for $paramArray: 'projectIds', 'projectKeys', 'issuetypeIds', 'issuetypeNames'.
822
     * @param bool  $expand     Retrieve all issue fields and values
823
     *
824
     * @throws JiraException
825
     *
826
     * @return object array of meta data for creating issues.
827
     */
828
    public function getCreateMeta($paramArray = [], $expand = true)
829
    {
830
        $paramArray['expand'] = ($expand) ? 'projects.issuetypes.fields' : null;
831
        $paramArray = array_filter($paramArray);
832
833
        $queryParam = '?'.http_build_query($paramArray);
834
835
        $ret = $this->exec($this->uri.'/createmeta'.$queryParam, null);
836
837
        return json_decode($ret);
838
    }
839
840
    /**
841
     * returns the metadata(include custom field) for an issue.
842
     *
843
     * @param string $idOrKey                issue id or key
844
     * @param bool   $overrideEditableFlag   Allows retrieving edit metadata for fields in non-editable status
845
     * @param bool   $overrideScreenSecurity Allows retrieving edit metadata for the fields hidden on Edit screen.
846
     *
847
     * @throws JiraException
848
     *
849
     * @return array of custom fields
850
     *
851
     * @see https://confluence.atlassian.com/jirakb/how-to-retrieve-available-options-for-a-multi-select-customfield-via-jira-rest-api-815566715.html How to retrieve available options for a multi-select customfield via JIRA REST API
852
     * @see https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-editmeta-get
853
     */
854
    public function getEditMeta($idOrKey, $overrideEditableFlag = false, $overrideScreenSecurity = false)
855
    {
856
        $queryParam = '?'.http_build_query([
857
            'overrideEditableFlag'   => $overrideEditableFlag,
858
            'overrideScreenSecurity' => $overrideScreenSecurity,
859
            ]);
860
861
        $uri = sprintf('%s/%s/editmeta', $this->uri, $idOrKey).$queryParam;
862
863
        $ret = $this->exec($uri, null);
864
865
        $metas = json_decode($ret, true);
866
867
        // extract only custom field(startWith customefield_XXXXX)
868
        $cfs = array_filter($metas['fields'], function ($key) {
869
            $pos = strpos($key, 'customfield');
870
871
            return $pos !== false;
872
        }, ARRAY_FILTER_USE_KEY);
873
874
        return $cfs;
875
    }
876
877
    /**
878
     * Sends a notification (email) to the list or recipients defined in the request.
879
     *
880
     * @param string|int $issueIdOrKey Issue id Or Key
881
     * @param Notify     $notify
882
     *
883
     * @throws JiraException
884
     *
885
     * @see https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-notify
886
     */
887
    public function notify($issueIdOrKey, $notify)
888
    {
889
        $full_uri = $this->uri."/$issueIdOrKey/notify";
890
891
        // set self value
892
        foreach ($notify->to['groups'] as &$g) {
893
            $g['self'] = $this->getConfiguration()->getJiraHost().'/rest/api/2/group?groupname='.$g['name'];
894
        }
895
        foreach ($notify->restrict['groups'] as &$g) {
896
            $g['self'] = $this->getConfiguration()->getJiraHost().'/rest/api/2/group?groupname='.$g['name'];
897
        }
898
899
        $data = json_encode($notify, JSON_UNESCAPED_SLASHES);
900
901
        $this->log->debug("notify=$data\n");
902
903
        $ret = $this->exec($full_uri, $data, 'POST');
904
905
        if ($ret !== true) {
0 ignored issues
show
introduced by
The condition $ret !== true is always true.
Loading history...
906
            throw new JiraException('notify failed: response code='.$ret);
907
        }
908
    }
909
910
    /**
911
     * Get a remote issue links on the issue.
912
     *
913
     * @param string|int $issueIdOrKey Issue id Or Key
914
     *
915
     * @throws JiraException
916
     *
917
     * @return array array os RemoteIssueLink class
918
     *
919
     * @see https://developer.atlassian.com/server/jira/platform/jira-rest-api-for-remote-issue-links/
920
     * @see https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-getRemoteIssueLinks
921
     */
922
    public function getRemoteIssueLink($issueIdOrKey)
923
    {
924
        $full_uri = $this->uri."/$issueIdOrKey/remotelink";
925
926
        $ret = $this->exec($full_uri, null);
927
928
        $rils = $this->json_mapper->mapArray(
929
            json_decode($ret, false), new \ArrayObject(), RemoteIssueLink::class
930
        );
931
932
        return $rils;
933
    }
934
935
    /**
936
     * @param string|int      $issueIdOrKey
937
     * @param RemoteIssueLink $ril
938
     *
939
     * @throws JiraException
940
     * @throws \JsonMapper_Exception
941
     *
942
     * @return object
943
     */
944
    public function createOrUpdateRemoteIssueLink($issueIdOrKey, RemoteIssueLink $ril)
945
    {
946
        $full_uri = $this->uri."/$issueIdOrKey/remotelink";
947
948
        $data = json_encode($ril, JSON_UNESCAPED_SLASHES);
949
950
        $this->log->debug("create remoteIssueLink=$data\n");
951
952
        $ret = $this->exec($full_uri, $data, 'POST');
953
954
        $res = $this->json_mapper->map(
955
            json_decode($ret), new RemoteIssueLink()
956
        );
957
958
        return $res;
959
    }
960
961
    /**
962
     * @param string|int $issueIdOrKey
963
     * @param string|int $globalId
964
     *
965
     * @throws JiraException
966
     *
967
     * @return string|bool
968
     */
969
    public function removeRemoteIssueLink($issueIdOrKey, $globalId)
970
    {
971
        $query = http_build_query(['globalId' => $globalId]);
972
973
        $full_uri = sprintf('%s/%s/remotelink?%s', $this->uri, $issueIdOrKey, $query);
974
975
        $ret = $this->exec($full_uri, '', 'DELETE');
976
977
        $this->log->info(
978
            sprintf(
979
                'delete remote issue link for issue "%s" with globalId "%s". Result=%s',
980
                $issueIdOrKey,
981
                $globalId,
982
                var_export($ret, true)
983
            )
984
        );
985
986
        return $ret;
987
    }
988
989
    /**
990
     * get all issue security schemes.
991
     *
992
     * @throws JiraException
993
     * @throws \JsonMapper_Exception
994
     *
995
     * @return SecurityScheme[] array of SecurityScheme class
996
     */
997
    public function getAllIssueSecuritySchemes()
998
    {
999
        $url = '/issuesecurityschemes';
1000
1001
        $ret = $this->exec($url);
1002
1003
        $data = json_decode($ret, true);
1004
1005
        // extract schem field
1006
        $schemes = json_decode(json_encode($data['issueSecuritySchemes']), false);
1007
1008
        $res = $this->json_mapper->mapArray(
1009
            $schemes, new \ArrayObject(), '\JiraRestApi\Issue\SecurityScheme'
1010
        );
1011
1012
        return $res;
1013
    }
1014
1015
    /**
1016
     *  get issue security scheme.
1017
     *
1018
     * @param int $securityId security scheme id
1019
     *
1020
     * @throws JiraException
1021
     * @throws \JsonMapper_Exception
1022
     *
1023
     * @return SecurityScheme SecurityScheme
1024
     */
1025
    public function getIssueSecuritySchemes($securityId)
1026
    {
1027
        $url = '/issuesecurityschemes/'.$securityId;
1028
1029
        $ret = $this->exec($url);
1030
1031
        $res = $this->json_mapper->map(
1032
            json_decode($ret), new SecurityScheme()
1033
        );
1034
1035
        return $res;
1036
    }
1037
1038
    /**
1039
     * convenient wrapper function for add or remove labels.
1040
     *
1041
     * @param string|int $issueIdOrKey
1042
     * @param array|null $addLablesParam
1043
     * @param array|null $removeLabelsParam
1044
     * @param bool       $notifyUsers
1045
     *
1046
     * @throws JiraException
1047
     *
1048
     * @return Issue|object class
1049
     */
1050
    public function updateLabels($issueIdOrKey, $addLablesParam, $removeLabelsParam, $notifyUsers = true)
1051
    {
1052
        $labels = [];
1053
        foreach ($addLablesParam as $a) {
1054
            array_push($labels, ['add' => $a]);
1055
        }
1056
1057
        foreach ($removeLabelsParam as $r) {
1058
            array_push($labels, ['remove' => $r]);
1059
        }
1060
1061
        $postData = json_encode([
1062
            'update' => [
1063
                'labels' => $labels,
1064
            ],
1065
        ], JSON_UNESCAPED_UNICODE);
1066
1067
        $this->log->info("Update labels=\n".$postData);
1068
1069
        $queryParam = '?'.http_build_query(['notifyUsers' => $notifyUsers]);
1070
1071
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, $postData, 'PUT');
1072
1073
        return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type string which is incompatible with the documented return type JiraRestApi\Issue\Issue|object.
Loading history...
1074
    }
1075
1076
    /**
1077
     * convenient wrapper function for add or remove fix versions.
1078
     *
1079
     * @param string|int $issueIdOrKey
1080
     * @param array|null $addFixVersionsParam
1081
     * @param array|null $removeFixVersionsParam
1082
     * @param bool       $notifyUsers
1083
     *
1084
     * @throws JiraException
1085
     *
1086
     * @return Issue|object class
1087
     */
1088
    public function updateFixVersions($issueIdOrKey, $addFixVersionsParam, $removeFixVersionsParam, $notifyUsers = true)
1089
    {
1090
        $fixVersions = [];
1091
        foreach ($addFixVersionsParam as $a) {
1092
            array_push($fixVersions, ['add' => ['name' => $a]]);
1093
        }
1094
1095
        foreach ($removeFixVersionsParam as $r) {
1096
            array_push($fixVersions, ['remove' => ['name' => $r]]);
1097
        }
1098
1099
        $postData = json_encode([
1100
            'update' => [
1101
                'fixVersions' => $fixVersions,
1102
            ],
1103
        ], JSON_UNESCAPED_UNICODE);
1104
1105
        $this->log->info("Update fixVersions=\n".$postData);
1106
1107
        $queryParam = '?'.http_build_query(['notifyUsers' => $notifyUsers]);
1108
1109
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, $postData, 'PUT');
1110
1111
        return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type string which is incompatible with the documented return type JiraRestApi\Issue\Issue|object.
Loading history...
1112
    }
1113
}
1114