Completed
Push — master ( 7e0d41...3d77dd )
by KwangSeob
17s queued 11s
created

IssueService::removeRemoteIssueLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 2
dl 0
loc 18
rs 9.9332
c 0
b 0
f 0
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 Comment    $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
        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...
229
            throw new JiraException('comment param must instance of Comment and have to body text.!');
230
        }
231
232
        $data = json_encode($comment);
233
234
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment", $data);
235
236
        $this->log->debug('add comment result='.var_export($ret, true));
237
        $comment = $this->json_mapper->map(
238
           json_decode($ret), new Comment()
239
        );
240
241
        return $comment;
242
    }
243
244
    /**
245
     * Update a comment in issue.
246
     *
247
     * @param string|int $issueIdOrKey Issue id or key
248
     * @param string|int $id           Comment id
249
     * @param Comment    $comment
250
     *
251
     * @throws JiraException
252
     * @throws \JsonMapper_Exception
253
     *
254
     * @return Comment|object Comment class
255
     */
256
    public function updateComment($issueIdOrKey, $id, $comment)
257
    {
258
        $this->log->info("updateComment=\n");
259
260
        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...
261
            throw new JiraException('comment param must instance of Comment and have to body text.!');
262
        }
263
264
        $data = json_encode($comment);
265
266
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id", $data, 'PUT');
267
268
        $this->log->debug('update comment result='.var_export($ret, true));
269
        $comment = $this->json_mapper->map(
270
            json_decode($ret), new Comment()
271
        );
272
273
        return $comment;
274
    }
275
276
    /**
277
     * Get a comment on an issue.
278
     *
279
     * @param string|int $issueIdOrKey Issue id or key
280
     * @param string|int $id           Comment id
281
     *
282
     * @throws JiraException
283
     * @throws \JsonMapper_Exception
284
     *
285
     * @return Comment|object Comment class
286
     */
287
    public function getComment($issueIdOrKey, $id)
288
    {
289
        $this->log->info("getComment=\n");
290
291
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id");
292
293
        $this->log->debug('get comment result='.var_export($ret, true));
294
        $comment = $this->json_mapper->map(
295
                json_decode($ret), new Comment()
296
                );
297
298
        return $comment;
299
    }
300
301
    /**
302
     * Get all comments on an issue.
303
     *
304
     * @param string|int $issueIdOrKey Issue id or key
305
     *
306
     * @throws JiraException
307
     * @throws \JsonMapper_Exception
308
     *
309
     * @return Comment|object Comment class
310
     */
311
    public function getComments($issueIdOrKey)
312
    {
313
        $this->log->info("getComments=\n");
314
315
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment");
316
317
        $this->log->debug('get comments result='.var_export($ret, true));
318
        $comment = $this->json_mapper->map(
319
                json_decode($ret), new Comment()
320
                );
321
322
        return $comment;
323
    }
324
325
    /**
326
     * Delete a comment on an issue.
327
     *
328
     * @param string|int $issueIdOrKey Issue id or key
329
     * @param string|int $id           Comment id
330
     *
331
     * @throws JiraException
332
     *
333
     * @return string|bool
334
     */
335
    public function deleteComment($issueIdOrKey, $id)
336
    {
337
        $this->log->info("deleteComment=\n");
338
339
        $ret = $this->exec($this->uri."/$issueIdOrKey/comment/$id", '', 'DELETE');
340
341
        $this->log->info('delete comment '.$issueIdOrKey.' '.$id.' result='.var_export($ret, true));
342
343
        return $ret;
344
    }
345
346
    /**
347
     * Change a issue assignee.
348
     *
349
     * @param string|int  $issueIdOrKey
350
     * @param string|null $assigneeName Assigns an issue to a user.
351
     *                                  If the assigneeName is "-1" automatic assignee is used.
352
     *                                  A null name will remove the assignee.
353
     *
354
     * @throws JiraException
355
     *
356
     * @return string|bool
357
     */
358
    public function changeAssignee($issueIdOrKey, $assigneeName)
359
    {
360
        $this->log->info("changeAssignee=\n");
361
362
        $ar = ['name' => $assigneeName];
363
364
        $data = json_encode($ar);
365
366
        $ret = $this->exec($this->uri."/$issueIdOrKey/assignee", $data, 'PUT');
367
368
        $this->log->info('change assignee of '.$issueIdOrKey.' to '.$assigneeName.' result='.var_export($ret, true));
369
370
        return $ret;
371
    }
372
373
    /**
374
     * Change a issue assignee for REST API V3.
375
     *
376
     * @param string|int  $issueIdOrKey
377
     * @param string|null $accountId    Assigns an issue to a user.
378
     *
379
     * @throws JiraException
380
     *
381
     * @return string
382
     */
383
    public function changeAssigneeByAccountId($issueIdOrKey, $accountId)
384
    {
385
        $this->log->info("changeAssigneeByAccountId=\n");
386
387
        $ar = ['accountId' => $accountId];
388
389
        $data = json_encode($ar);
390
391
        $ret = $this->exec($this->uri."/$issueIdOrKey/assignee", $data, 'PUT');
392
393
        $this->log->info('change assignee of '.$issueIdOrKey.' to '.$accountId.' result='.var_export($ret, true));
394
395
        return $ret;
396
    }
397
398
    /**
399
     * Delete a issue.
400
     *
401
     * @param string|int $issueIdOrKey Issue id or key
402
     * @param array      $paramArray   Query Parameter key-value Array.
403
     *
404
     * @throws JiraException
405
     *
406
     * @return string|bool
407
     */
408
    public function deleteIssue($issueIdOrKey, $paramArray = [])
409
    {
410
        $this->log->info("deleteIssue=\n");
411
412
        $queryParam = '?'.http_build_query($paramArray);
413
414
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, '', 'DELETE');
415
416
        $this->log->info('delete issue '.$issueIdOrKey.' result='.var_export($ret, true));
417
418
        return $ret;
419
    }
420
421
    /**
422
     * Get a list of the transitions possible for this issue by the current user, along with fields that are required and their types.
423
     *
424
     * @param string|int $issueIdOrKey Issue id or key
425
     * @param array      $paramArray   Query Parameter key-value Array.
426
     *
427
     * @throws JiraException
428
     *
429
     * @return Transition[] array of Transition class
430
     */
431
    public function getTransition($issueIdOrKey, $paramArray = [])
432
    {
433
        $queryParam = '?'.http_build_query($paramArray);
434
435
        $ret = $this->exec($this->uri."/$issueIdOrKey/transitions".$queryParam);
436
437
        $this->log->debug('getTransitions result='.var_export($ret, true));
438
439
        $data = json_encode(json_decode($ret)->transitions);
440
441
        $transitions = $this->json_mapper->mapArray(
442
           json_decode($data), new \ArrayObject(), '\JiraRestApi\Issue\Transition'
443
        );
444
445
        return $transitions;
446
    }
447
448
    /**
449
     * find transition id by transition's to field name(aka 'Resolved').
450
     *
451
     * @param string|int $issueIdOrKey
452
     * @param string     $transitionToName
453
     *
454
     * @throws JiraException
455
     *
456
     * @return string
457
     */
458
    public function findTransitonId($issueIdOrKey, $transitionToName)
459
    {
460
        $this->log->debug('findTransitonId=');
461
462
        $ret = $this->getTransition($issueIdOrKey);
463
464
        foreach ($ret as $trans) {
465
            $toName = $trans->to->name;
466
467
            $this->log->debug('getTransitions result='.var_export($ret, true));
468
469
            if (strcmp($toName, $transitionToName) == 0) {
470
                return $trans->id;
471
            }
472
        }
473
474
        // transition keyword not found
475
        throw new JiraException("Transition name '$transitionToName' not found on JIRA Server.");
476
    }
477
478
    /**
479
     * Perform a transition on an issue.
480
     *
481
     * @param string|int $issueIdOrKey Issue id or key
482
     * @param Transition $transition
483
     *
484
     * @throws JiraException
485
     *
486
     * @return string|null nothing - if transition was successful return http 204(no contents)
487
     */
488
    public function transition($issueIdOrKey, $transition)
489
    {
490
        $this->log->debug('transition='.var_export($transition, true));
491
492
        if (!isset($transition->transition['id'])) {
493
            $transition->transition['id'] = $this->findTransitonId($issueIdOrKey, $transition->transition['name']);
494
        }
495
496
        $data = json_encode($transition);
497
498
        $this->log->debug("transition req=$data\n");
499
500
        $ret = $this->exec($this->uri."/$issueIdOrKey/transitions", $data, 'POST');
501
502
        $this->log->debug('getTransitions result='.var_export($ret, true));
503
504
        return $ret;
505
    }
506
507
    /**
508
     * Search issues.
509
     *
510
     * @param string $jql
511
     * @param int    $startAt
512
     * @param int    $maxResults
513
     * @param array  $fields
514
     * @param array  $expand
515
     * @param bool   $validateQuery
516
     *
517
     * @throws JiraException
518
     * @throws \JsonMapper_Exception
519
     *
520
     * @return IssueSearchResult|object
521
     */
522
    public function search($jql, $startAt = 0, $maxResults = 15, $fields = [], $expand = [], $validateQuery = true)
523
    {
524
        $data = json_encode([
525
            'jql'           => $jql,
526
            'startAt'       => $startAt,
527
            'maxResults'    => $maxResults,
528
            'fields'        => $fields,
529
            'expand'        => $expand,
530
            'validateQuery' => $validateQuery,
531
        ]);
532
533
        $ret = $this->exec('search', $data, 'POST');
534
        $json = json_decode($ret);
535
536
        $result = null;
537
        if ($this->isRestApiV3()) {
538
            $result = $this->json_mapper->map(
539
                $json, new IssueSearchResultV3()
540
            );
541
        } else {
542
            $result = $this->json_mapper->map(
543
                $json, new IssueSearchResult()
544
            );
545
        }
546
547
        return $result;
548
    }
549
550
    /**
551
     * get TimeTracking info.
552
     *
553
     * @param string|int $issueIdOrKey
554
     *
555
     * @throws JiraException
556
     * @throws \JsonMapper_Exception
557
     *
558
     * @return TimeTracking
559
     */
560
    public function getTimeTracking($issueIdOrKey)
561
    {
562
        $ret = $this->exec($this->uri."/$issueIdOrKey", null);
563
        $this->log->debug("getTimeTracking res=$ret\n");
564
565
        $issue = $this->json_mapper->map(
566
             json_decode($ret), new Issue()
567
        );
568
569
        return $issue->fields->timeTracking;
570
    }
571
572
    /**
573
     * TimeTracking issues.
574
     *
575
     * @param string|int   $issueIdOrKey Issue id or key
576
     * @param TimeTracking $timeTracking
577
     *
578
     * @throws JiraException
579
     *
580
     * @return string
581
     */
582
    public function timeTracking($issueIdOrKey, $timeTracking)
583
    {
584
        $array = [
585
            'update' => [
586
                'timetracking' => [
587
                    ['edit' => $timeTracking],
588
                ],
589
            ],
590
        ];
591
592
        $data = json_encode($array);
593
594
        $this->log->debug("TimeTracking req=$data\n");
595
596
        // if success, just return HTTP 201.
597
        $ret = $this->exec($this->uri."/$issueIdOrKey", $data, 'PUT');
598
599
        return $ret;
600
    }
601
602
    /**
603
     * get getWorklog.
604
     *
605
     * @param string|int $issueIdOrKey
606
     *
607
     * @throws JiraException
608
     * @throws \JsonMapper_Exception
609
     *
610
     * @return PaginatedWorklog|object
611
     */
612
    public function getWorklog($issueIdOrKey)
613
    {
614
        $ret = $this->exec($this->uri."/$issueIdOrKey/worklog");
615
        $this->log->debug("getWorklog res=$ret\n");
616
        $worklog = $this->json_mapper->map(
617
            json_decode($ret), new PaginatedWorklog()
618
        );
619
620
        return $worklog;
621
    }
622
623
    /**
624
     * get getWorklog by Id.
625
     *
626
     * @param string|int $issueIdOrKey
627
     * @param int        $workLogId
628
     *
629
     * @throws JiraException
630
     * @throws \JsonMapper_Exception
631
     *
632
     * @return Worklog|object PaginatedWorklog object
633
     */
634
    public function getWorklogById($issueIdOrKey, $workLogId)
635
    {
636
        $ret = $this->exec($this->uri."/$issueIdOrKey/worklog/$workLogId");
637
        $this->log->debug("getWorklogById res=$ret\n");
638
        $worklog = $this->json_mapper->map(
639
            json_decode($ret), new Worklog()
640
        );
641
642
        return $worklog;
643
    }
644
645
    /**
646
     * add work log to issue.
647
     *
648
     * @param string|int     $issueIdOrKey
649
     * @param Worklog|object $worklog
650
     *
651
     * @throws JiraException
652
     * @throws \JsonMapper_Exception
653
     *
654
     * @return Worklog|object Worklog Object
655
     */
656
    public function addWorklog($issueIdOrKey, $worklog)
657
    {
658
        $this->log->info("addWorklog=\n");
659
660
        $data = json_encode($worklog);
661
        $url = $this->uri."/$issueIdOrKey/worklog";
662
        $type = 'POST';
663
664
        $ret = $this->exec($url, $data, $type);
665
666
        $ret_worklog = $this->json_mapper->map(
667
           json_decode($ret), new Worklog()
668
        );
669
670
        return $ret_worklog;
671
    }
672
673
    /**
674
     * edit the worklog.
675
     *
676
     * @param string|int     $issueIdOrKey
677
     * @param Worklog|object $worklog
678
     * @param string|int     $worklogId
679
     *
680
     * @throws JiraException
681
     * @throws \JsonMapper_Exception
682
     *
683
     * @return Worklog|object
684
     */
685
    public function editWorklog($issueIdOrKey, $worklog, $worklogId)
686
    {
687
        $this->log->info("editWorklog=\n");
688
689
        $data = json_encode($worklog);
690
        $url = $this->uri."/$issueIdOrKey/worklog/$worklogId";
691
        $type = 'PUT';
692
693
        $ret = $this->exec($url, $data, $type);
694
695
        $ret_worklog = $this->json_mapper->map(
696
            json_decode($ret), new Worklog()
697
        );
698
699
        return $ret_worklog;
700
    }
701
702
    /**
703
     * Get all priorities.
704
     *
705
     * @throws JiraException
706
     *
707
     * @return Priority[] array of priority class
708
     */
709
    public function getAllPriorities()
710
    {
711
        $ret = $this->exec('priority', null);
712
713
        $priorities = $this->json_mapper->mapArray(
714
             json_decode($ret, false), new \ArrayObject(), '\JiraRestApi\Issue\Priority'
715
        );
716
717
        return $priorities;
718
    }
719
720
    /**
721
     * Get priority by id.
722
     * throws  HTTPException if the priority is not found, or the calling user does not have permission or view it.
723
     *
724
     * @param string|int $priorityId Id of priority.
725
     *
726
     * @throws JiraException
727
     * @throws \JsonMapper_Exception
728
     *
729
     * @return Priority|object priority
730
     */
731
    public function getPriority($priorityId)
732
    {
733
        $ret = $this->exec("priority/$priorityId", null);
734
735
        $this->log->info('Result='.$ret);
736
737
        $prio = $this->json_mapper->map(
738
             json_decode($ret), new Priority()
739
        );
740
741
        return $prio;
742
    }
743
744
    /**
745
     * Get priority by id.
746
     * throws HTTPException if the priority is not found, or the calling user does not have permission or view it.
747
     *
748
     * @param string|int $priorityId Id of priority.
749
     *
750
     * @throws JiraException
751
     * @throws \JsonMapper_Exception
752
     *
753
     * @return Priority|object priority
754
     */
755
    public function getCustomFields($priorityId)
756
    {
757
        $ret = $this->exec("priority/$priorityId", null);
758
759
        $this->log->info('Result='.$ret);
760
761
        $prio = $this->json_mapper->map(
762
            json_decode($ret), new Priority()
763
        );
764
765
        return $prio;
766
    }
767
768
    /**
769
     * get watchers.
770
     *
771
     * @param $issueIdOrKey
772
     *
773
     * @throws JiraException
774
     *
775
     * @return Reporter[]
776
     */
777
    public function getWatchers($issueIdOrKey)
778
    {
779
        $this->log->info("getWatchers=\n");
780
781
        $url = $this->uri."/$issueIdOrKey/watchers";
782
783
        $ret = $this->exec($url, null);
784
785
        $watchers = $this->json_mapper->mapArray(
786
            json_decode($ret, false)->watchers, new \ArrayObject(), '\JiraRestApi\Issue\Reporter'
787
        );
788
789
        return $watchers;
790
    }
791
792
    /**
793
     * add watcher to issue.
794
     *
795
     * @param string|int $issueIdOrKey
796
     * @param string     $watcher      watcher id
797
     *
798
     * @throws JiraException
799
     *
800
     * @return bool
801
     */
802
    public function addWatcher($issueIdOrKey, $watcher)
803
    {
804
        $this->log->info("addWatcher=\n");
805
806
        $data = json_encode($watcher);
807
        $url = $this->uri."/$issueIdOrKey/watchers";
808
        $type = 'POST';
809
810
        $this->exec($url, $data, $type);
811
812
        return $this->http_response == 204 ? true : false;
813
    }
814
815
    /**
816
     * remove watcher from issue.
817
     *
818
     * @param string|int $issueIdOrKey
819
     * @param string     $watcher      watcher id
820
     *
821
     * @throws JiraException
822
     *
823
     * @return bool
824
     */
825
    public function removeWatcher($issueIdOrKey, $watcher)
826
    {
827
        $this->log->addInfo("removeWatcher=\n");
0 ignored issues
show
Bug introduced by
The method addInfo() does not exist on Monolog\Logger. ( Ignorable by Annotation )

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

827
        $this->log->/** @scrutinizer ignore-call */ 
828
                    addInfo("removeWatcher=\n");

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
828
829
        $ret = $this->exec($this->uri."/$issueIdOrKey/watchers/?username=$watcher", '', 'DELETE');
830
831
        $this->log->addInfo('remove watcher '.$issueIdOrKey.' result='.var_export($ret, true));
832
833
        return $this->http_response == 204 ? true : false;
834
    }
835
    
836
    /**
837
     * remove watcher from issue by watcher account id.
838
     *
839
     * @param string|int $issueIdOrKey
840
     * @param string $accountId    Watcher account id.
841
     *
842
     * @throws JiraException
843
     *
844
     * @return bool
845
     */
846
    public function removeWatcherByAccountId($issueIdOrKey, $accountId)
847
    {
848
        $this->log->info("removeWatcher=\n");
849
850
        $ret = $this->exec($this->uri."/$issueIdOrKey/watchers/?accountId=$accountId", '', 'DELETE');
851
852
        $this->log->info('remove watcher '.$issueIdOrKey.' result='.var_export($ret, true));
853
854
        return $this->http_response == 204 ? true : false;
855
    }
856
857
    /**
858
     * Get the meta data for creating issues.
859
     *
860
     * @param array $paramArray Possible keys for $paramArray: 'projectIds', 'projectKeys', 'issuetypeIds', 'issuetypeNames'.
861
     * @param bool  $expand     Retrieve all issue fields and values
862
     *
863
     * @throws JiraException
864
     *
865
     * @return object array of meta data for creating issues.
866
     */
867
    public function getCreateMeta($paramArray = [], $expand = true)
868
    {
869
        $paramArray['expand'] = ($expand) ? 'projects.issuetypes.fields' : null;
870
        $paramArray = array_filter($paramArray);
871
872
        $queryParam = '?'.http_build_query($paramArray);
873
874
        $ret = $this->exec($this->uri.'/createmeta'.$queryParam, null);
875
876
        return json_decode($ret);
877
    }
878
879
    /**
880
     * returns the metadata(include custom field) for an issue.
881
     *
882
     * @param string $idOrKey                issue id or key
883
     * @param bool   $overrideEditableFlag   Allows retrieving edit metadata for fields in non-editable status
884
     * @param bool   $overrideScreenSecurity Allows retrieving edit metadata for the fields hidden on Edit screen.
885
     *
886
     * @throws JiraException
887
     *
888
     * @return array of custom fields
889
     *
890
     * @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
891
     * @see https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-editmeta-get
892
     */
893
    public function getEditMeta($idOrKey, $overrideEditableFlag = false, $overrideScreenSecurity = false)
894
    {
895
        $queryParam = '?'.http_build_query([
896
            'overrideEditableFlag'   => $overrideEditableFlag,
897
            'overrideScreenSecurity' => $overrideScreenSecurity,
898
        ]);
899
900
        $uri = sprintf('%s/%s/editmeta', $this->uri, $idOrKey).$queryParam;
901
902
        $ret = $this->exec($uri, null);
903
904
        $metas = json_decode($ret, true);
905
906
        // extract only custom field(startWith customefield_XXXXX)
907
        $cfs = array_filter($metas['fields'], function ($key) {
908
            $pos = strpos($key, 'customfield');
909
910
            return $pos !== false;
911
        }, ARRAY_FILTER_USE_KEY);
912
913
        return $cfs;
914
    }
915
916
    /**
917
     * Sends a notification (email) to the list or recipients defined in the request.
918
     *
919
     * @param string|int $issueIdOrKey Issue id Or Key
920
     * @param Notify     $notify
921
     *
922
     * @throws JiraException
923
     *
924
     * @see https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-notify
925
     */
926
    public function notify($issueIdOrKey, $notify)
927
    {
928
        $full_uri = $this->uri."/$issueIdOrKey/notify";
929
930
        // set self value
931
        foreach ($notify->to['groups'] as &$g) {
932
            $g['self'] = $this->getConfiguration()->getJiraHost().'/rest/api/2/group?groupname='.$g['name'];
933
        }
934
        foreach ($notify->restrict['groups'] as &$g) {
935
            $g['self'] = $this->getConfiguration()->getJiraHost().'/rest/api/2/group?groupname='.$g['name'];
936
        }
937
938
        $data = json_encode($notify, JSON_UNESCAPED_SLASHES);
939
940
        $this->log->debug("notify=$data\n");
941
942
        $ret = $this->exec($full_uri, $data, 'POST');
943
944
        if ($ret !== true) {
0 ignored issues
show
introduced by
The condition $ret !== true is always true.
Loading history...
945
            throw new JiraException('notify failed: response code='.$ret);
946
        }
947
    }
948
949
    /**
950
     * Get a remote issue links on the issue.
951
     *
952
     * @param string|int $issueIdOrKey Issue id Or Key
953
     *
954
     * @throws JiraException
955
     *
956
     * @return array array os RemoteIssueLink class
957
     *
958
     * @see https://developer.atlassian.com/server/jira/platform/jira-rest-api-for-remote-issue-links/
959
     * @see https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-getRemoteIssueLinks
960
     */
961
    public function getRemoteIssueLink($issueIdOrKey)
962
    {
963
        $full_uri = $this->uri."/$issueIdOrKey/remotelink";
964
965
        $ret = $this->exec($full_uri, null);
966
967
        $rils = $this->json_mapper->mapArray(
968
            json_decode($ret, false), new \ArrayObject(), RemoteIssueLink::class
969
        );
970
971
        return $rils;
972
    }
973
974
    /**
975
     * @param string|int      $issueIdOrKey
976
     * @param RemoteIssueLink $ril
977
     *
978
     * @throws JiraException
979
     * @throws \JsonMapper_Exception
980
     *
981
     * @return object
982
     */
983
    public function createOrUpdateRemoteIssueLink($issueIdOrKey, RemoteIssueLink $ril)
984
    {
985
        $full_uri = $this->uri."/$issueIdOrKey/remotelink";
986
987
        $data = json_encode($ril, JSON_UNESCAPED_SLASHES);
988
989
        $this->log->debug("create remoteIssueLink=$data\n");
990
991
        $ret = $this->exec($full_uri, $data, 'POST');
992
993
        $res = $this->json_mapper->map(
994
            json_decode($ret), new RemoteIssueLink()
995
        );
996
997
        return $res;
998
    }
999
1000
    /**
1001
     * @param string|int $issueIdOrKey
1002
     * @param string|int $globalId
1003
     *
1004
     * @throws JiraException
1005
     *
1006
     * @return string|bool
1007
     */
1008
    public function removeRemoteIssueLink($issueIdOrKey, $globalId)
1009
    {
1010
        $query = http_build_query(['globalId' => $globalId]);
1011
1012
        $full_uri = sprintf('%s/%s/remotelink?%s', $this->uri, $issueIdOrKey, $query);
1013
1014
        $ret = $this->exec($full_uri, '', 'DELETE');
1015
1016
        $this->log->info(
1017
            sprintf(
1018
                'delete remote issue link for issue "%s" with globalId "%s". Result=%s',
1019
                $issueIdOrKey,
1020
                $globalId,
1021
                var_export($ret, true)
1022
            )
1023
        );
1024
1025
        return $ret;
1026
    }
1027
1028
    /**
1029
     * get all issue security schemes.
1030
     *
1031
     * @throws JiraException
1032
     * @throws \JsonMapper_Exception
1033
     *
1034
     * @return SecurityScheme[] array of SecurityScheme class
1035
     */
1036
    public function getAllIssueSecuritySchemes()
1037
    {
1038
        $url = '/issuesecurityschemes';
1039
1040
        $ret = $this->exec($url);
1041
1042
        $data = json_decode($ret, true);
1043
1044
        // extract schem field
1045
        $schemes = json_decode(json_encode($data['issueSecuritySchemes']), false);
1046
1047
        $res = $this->json_mapper->mapArray(
1048
            $schemes, new \ArrayObject(), '\JiraRestApi\Issue\SecurityScheme'
1049
        );
1050
1051
        return $res;
1052
    }
1053
1054
    /**
1055
     *  get issue security scheme.
1056
     *
1057
     * @param int $securityId security scheme id
1058
     *
1059
     * @throws JiraException
1060
     * @throws \JsonMapper_Exception
1061
     *
1062
     * @return SecurityScheme SecurityScheme
1063
     */
1064
    public function getIssueSecuritySchemes($securityId)
1065
    {
1066
        $url = '/issuesecurityschemes/'.$securityId;
1067
1068
        $ret = $this->exec($url);
1069
1070
        $res = $this->json_mapper->map(
1071
            json_decode($ret), new SecurityScheme()
1072
        );
1073
1074
        return $res;
1075
    }
1076
1077
    /**
1078
     * convenient wrapper function for add or remove labels.
1079
     *
1080
     * @param string|int $issueIdOrKey
1081
     * @param array|null $addLablesParam
1082
     * @param array|null $removeLabelsParam
1083
     * @param bool       $notifyUsers
1084
     *
1085
     * @throws JiraException
1086
     *
1087
     * @return Issue|object class
1088
     */
1089
    public function updateLabels($issueIdOrKey, $addLablesParam, $removeLabelsParam, $notifyUsers = true)
1090
    {
1091
        $labels = [];
1092
        foreach ($addLablesParam as $a) {
1093
            array_push($labels, ['add' => $a]);
1094
        }
1095
1096
        foreach ($removeLabelsParam as $r) {
1097
            array_push($labels, ['remove' => $r]);
1098
        }
1099
1100
        $postData = json_encode([
1101
            'update' => [
1102
                'labels' => $labels,
1103
            ],
1104
        ], JSON_UNESCAPED_UNICODE);
1105
1106
        $this->log->info("Update labels=\n".$postData);
1107
1108
        $queryParam = '?'.http_build_query(['notifyUsers' => $notifyUsers]);
1109
1110
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, $postData, 'PUT');
1111
1112
        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...
1113
    }
1114
1115
    /**
1116
     * convenient wrapper function for add or remove fix versions.
1117
     *
1118
     * @param string|int $issueIdOrKey
1119
     * @param array|null $addFixVersionsParam
1120
     * @param array|null $removeFixVersionsParam
1121
     * @param bool       $notifyUsers
1122
     *
1123
     * @throws JiraException
1124
     *
1125
     * @return Issue|object class
1126
     */
1127
    public function updateFixVersions($issueIdOrKey, $addFixVersionsParam, $removeFixVersionsParam, $notifyUsers = true)
1128
    {
1129
        $fixVersions = [];
1130
        foreach ($addFixVersionsParam as $a) {
1131
            array_push($fixVersions, ['add' => ['name' => $a]]);
1132
        }
1133
1134
        foreach ($removeFixVersionsParam as $r) {
1135
            array_push($fixVersions, ['remove' => ['name' => $r]]);
1136
        }
1137
1138
        $postData = json_encode([
1139
            'update' => [
1140
                'fixVersions' => $fixVersions,
1141
            ],
1142
        ], JSON_UNESCAPED_UNICODE);
1143
1144
        $this->log->info("Update fixVersions=\n".$postData);
1145
1146
        $queryParam = '?'.http_build_query(['notifyUsers' => $notifyUsers]);
1147
1148
        $ret = $this->exec($this->uri."/$issueIdOrKey".$queryParam, $postData, 'PUT');
1149
1150
        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...
1151
    }
1152
}
1153