Completed
Push — master ( c0afb1...99eb0f )
by KwangSeob
04:02 queued 01:31
created

IssueService::addAttachments()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 6
eloc 21
c 4
b 0
f 0
nc 8
nop 2
dl 0
loc 35
rs 8.9617
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,
22
            new Issue()
23
        );
24
25
        return $issue;
26
    }
27
28
    /**
29
     *  get all project list.
30
     *
31
     * @param string|int $issueIdOrKey
32
     * @param array      $paramArray   Query Parameter key-value Array.
33
     * @param Issue      $issueObject
34
     *
35
     * @throws JiraException
36
     * @throws \JsonMapper_Exception
37
     *
38
     * @return Issue|object class
39
     */
40
    public function get($issueIdOrKey, $paramArray = [], $issueObject = null)
41
    {
42
        // for REST API V3
43
        if ($this->isRestApiV3()) {
44
            $issueObject = ($issueObject) ? $issueObject : new IssueV3();
45
        } else {
46
            $issueObject = ($issueObject) ? $issueObject : new Issue();
47
        }
48
49
        $ret = $this->exec($this->uri.'/'.$issueIdOrKey.$this->toHttpQueryParameter($paramArray), null);
50
51
        $this->log->info("Result=\n".$ret);
52
53
        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...
54
            json_decode($ret),
55
            $issueObject
56
        );
57
    }
58
59
    /**
60
     * create new issue.
61
     *
62
     * @param IssueField $issueField
63
     *
64
     * @throws JiraException
65
     * @throws \JsonMapper_Exception
66
     *
67
     * @return Issue|object created issue key
68
     */
69
    public function create($issueField)
70
    {
71
        $issue = new Issue();
72
73
        // serilize only not null field.
74
        $issue->fields = $issueField;
75
76
        $data = json_encode($issue);
77
78
        $this->log->info("Create Issue=\n".$data);
79
80
        $ret = $this->exec($this->uri, $data, 'POST');
81
82
        return $this->getIssueFromJSON(json_decode($ret));
83
    }
84
85
    /**
86
     * Create multiple issues using bulk insert.
87
     *
88
     * @param IssueField[] $issueFields Array of IssueField objects
89
     * @param int          $batchSize   Maximum number of issues to send in each request
90
     *
91
     * @throws JiraException
92
     * @throws \JsonMapper_Exception
93
     *
94
     * @return array Array of results, where each result represents one batch of insertions
95
     */
96
    public function createMultiple($issueFields, $batchSize = 50)
97
    {
98
        $issues = [];
99
100
        foreach ($issueFields as $issueField) {
101
            $issue = new Issue();
102
            $issue->fields = $issueField;
103
            $issues[] = $issue;
104
        }
105
106
        $batches = array_chunk($issues, $batchSize);
107
108
        $results = [];
109
        foreach ($batches as $batch) {
110
            $results = array_merge($results, $this->bulkInsert($batch));
111
        }
112
113
        return $results;
114
    }
115
116
    /**
117
     * Makes API call to bulk insert issues.
118
     *
119
     * @param Issue[] $issues Array of issue arrays that are sent to Jira one by one in single create
120
     *
121
     * @throws JiraException
122
     * @throws \JsonMapper_Exception
123
     *
124
     * @return Issue[] Result of API call to insert many issues
125
     */
126
    private function bulkInsert($issues)
127
    {
128
        $data = json_encode(['issueUpdates' => $issues]);
129
130
        $this->log->info("Create Issues=\n".$data);
131
        $results = $this->exec($this->uri.'/bulk', $data, 'POST');
132
133
        $issues = [];
134
        foreach (json_decode($results)->issues as $result) {
135
            $issues[] = $this->getIssueFromJSON($result);
136
        }
137
138
        return $issues;
139
    }
140
141
    /**
142
     * Add one or more file to an issue.
143
     *
144
     * @param string|int   $issueIdOrKey  Issue id or key
145
     * @param array|string $filePathArray attachment file path.
146
     *
147
     * @throws JiraException
148
     * @throws \JsonMapper_Exception
149
     *
150
     * @return Attachment[]
151
     */
152
    public function addAttachments($issueIdOrKey, $filePathArray)
153
    {
154
        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...
155
            $filePathArray = [$filePathArray];
156
        }
157
158
        $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

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