Skip to content

Commit c4b2ec8

Browse files
G15Nm1guelpf
authored andcommitted
Adds issue links API methods.
1 parent c8e8f1d commit c4b2ec8

File tree

7 files changed

+444
-0
lines changed

7 files changed

+444
-0
lines changed

lib/Gitlab/Api/IssueLinks.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php namespace Gitlab\Api;
2+
3+
class IssueLinks extends AbstractApi
4+
{
5+
/**
6+
* @param int $project_id
7+
* @param int $issue_iid
8+
* @return mixed
9+
*/
10+
public function all($project_id, $issue_iid)
11+
{
12+
return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)).'/links');
13+
}
14+
15+
/**
16+
* @param int $source_project_id
17+
* @param int $source_issue_iid
18+
* @param int $target_project_id
19+
* @param int $target_issue_iid
20+
* @return mixed
21+
*/
22+
public function create($source_project_id, $source_issue_iid, $target_project_id, $target_issue_iid)
23+
{
24+
return $this->post($this->getProjectPath($source_project_id, 'issues/'.$this->encodePath($source_issue_iid).'/links'), array(
25+
'target_project_id' => $target_project_id,
26+
'target_issue_iid' => $target_issue_iid
27+
));
28+
}
29+
30+
/**
31+
* @param int $project_id
32+
* @param int $issue_iid
33+
* @param int $issue_link_id
34+
* @return mixed
35+
*/
36+
public function remove($project_id, $issue_iid, $issue_link_id)
37+
{
38+
return $this->delete($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_iid)).'/links/'.$this->encodePath($issue_link_id));
39+
}
40+
}

lib/Gitlab/Client.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ public function issueBoards()
150150
return new Api\IssueBoards($this);
151151
}
152152

153+
/**
154+
* @return Api\IssueLinks
155+
*/
156+
public function issueLinks()
157+
{
158+
return new Api\IssueLinks($this);
159+
}
160+
153161
/**
154162
* @return Api\Jobs
155163
*/
@@ -292,6 +300,10 @@ public function api($name)
292300
case 'board':
293301
case 'issue_boards':
294302
return $this->issueBoards();
303+
304+
case 'issue_links':
305+
return $this->issueLinks();
306+
295307
case 'jobs':
296308
return $this->jobs();
297309

lib/Gitlab/Model/Issue.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,65 @@ public function hasLabel($label)
184184
{
185185
return in_array($label, $this->labels);
186186
}
187+
188+
/**
189+
* @return IssueLink[]
190+
*/
191+
public function links()
192+
{
193+
$data = $this->client->issueLinks()->all($this->project->id, $this->iid);
194+
if (!is_array($data)) {
195+
return array();
196+
}
197+
198+
$projects = $this->client->projects();
199+
200+
return array_map(function($data) use ($projects) {
201+
return IssueLink::fromArray(
202+
$this->client,
203+
Project::fromArray($this->client, $projects->show($data['project_id'])),
204+
$data
205+
);
206+
}, $data);
207+
}
208+
209+
/**
210+
* @param Issue $target
211+
* @return Issue[]
212+
*/
213+
public function addLink(Issue $target)
214+
{
215+
$data = $this->client->issueLinks()->create($this->project->id, $this->iid, $target->project->id, $target->iid);
216+
if (!is_array($data)) {
217+
return array();
218+
}
219+
220+
return [
221+
'source_issue' => static::fromArray($this->client, $this->project, $data['source_issue']),
222+
'target_issue' => static::fromArray($this->client, $target->project, $data['target_issue']),
223+
];
224+
}
225+
226+
/**
227+
* @param int $issue_link_id
228+
* @return Issue[]
229+
*/
230+
public function removeLink($issue_link_id)
231+
{
232+
// The two related issues have the same link ID.
233+
$data = $this->client->issueLinks()->remove($this->project->id, $this->iid, $issue_link_id);
234+
if (!is_array($data)) {
235+
return array();
236+
}
237+
238+
$targetProject = Project::fromArray(
239+
$this->client,
240+
$this->client->projects()->show($data['target_issue']['project_id'])
241+
);
242+
243+
return [
244+
'source_issue' => static::fromArray($this->client, $this->project, $data['source_issue']),
245+
'target_issue' => static::fromArray($this->client, $targetProject, $data['target_issue']),
246+
];
247+
}
187248
}

lib/Gitlab/Model/IssueLink.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php namespace Gitlab\Model;
2+
3+
use Gitlab\Client;
4+
5+
/**
6+
* Class IssueLink
7+
*
8+
* @property-read int $issue_link_id
9+
* @property-read Issue $issue
10+
*/
11+
class IssueLink extends AbstractModel
12+
{
13+
/**
14+
* @var array
15+
*/
16+
protected static $properties = array(
17+
'issue_link_id',
18+
'issue',
19+
);
20+
21+
/**
22+
* @param Client $client
23+
* @param Project $project
24+
* @param array $data
25+
* @return IssueLink
26+
*/
27+
public static function fromArray(Client $client, Project $project, array $data)
28+
{
29+
$issue = Issue::fromArray($client, $project, $data);
30+
$issueLink = new static($issue, $data['issue_link_id'], $client);
31+
32+
return $issueLink->hydrate($data);
33+
}
34+
35+
/**
36+
* @param Issue $issue
37+
* @param int|null $issue_link_id
38+
* @param Client|null $client
39+
*/
40+
public function __construct(Issue $issue, $issue_link_id = null, Client $client = null)
41+
{
42+
$this->setClient($client);
43+
$this->setData('issue', $issue);
44+
$this->setData('issue_link_id', $issue_link_id);
45+
}
46+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php namespace Gitlab\Tests\Api;
2+
3+
use Gitlab\Api\IssueLinks;
4+
5+
class IssueLinksTest extends TestCase
6+
{
7+
/**
8+
* @inheritdoc
9+
*/
10+
protected function getApiClass()
11+
{
12+
return IssueLinks::class;
13+
}
14+
15+
/**
16+
* @test
17+
*/
18+
public function shouldGetIssueLinks()
19+
{
20+
$expectedArray = array(
21+
array('issue_link_id' => 100),
22+
array('issue_link_id' => 101),
23+
);
24+
25+
$api = $this->getApiMock();
26+
$api->expects($this->once())
27+
->method('get')
28+
->with('projects/1/issues/10/links')
29+
->will($this->returnValue($expectedArray))
30+
;
31+
32+
$this->assertEquals($expectedArray, $api->all(1, 10));
33+
}
34+
35+
/**
36+
* @test
37+
*/
38+
public function shouldCreateIssueLink()
39+
{
40+
$expectedArray = array(
41+
'source_issue' => array('iid' => 10, 'project_id' => 1),
42+
'target_issue' => array('iid' => 20, 'project_id' => 2),
43+
);
44+
45+
$api = $this->getApiMock();
46+
$api->expects($this->once())
47+
->method('post')
48+
->with('projects/1/issues/10/links', array('target_project_id' => 2, 'target_issue_iid' => 20))
49+
->will($this->returnValue($expectedArray))
50+
;
51+
52+
$this->assertEquals($expectedArray, $api->create(1, 10, 2, 20));
53+
}
54+
55+
/**
56+
* @test
57+
*/
58+
public function shouldRemoveIssueLink()
59+
{
60+
$expectedArray = array(
61+
'source_issue' => array('iid' => 10, 'project_id' => 1),
62+
'target_issue' => array('iid' => 20, 'project_id' => 2),
63+
);
64+
65+
$api = $this->getApiMock();
66+
$api->expects($this->once())
67+
->method('delete')
68+
->with('projects/1/issues/10/links/100')
69+
->will($this->returnValue($expectedArray))
70+
;
71+
72+
$this->assertEquals($expectedArray, $api->remove(1, 10, 100));
73+
}
74+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php namespace Gitlab\Tests\Model;
2+
3+
use Gitlab\Client;
4+
use Gitlab\Model\Issue;
5+
use Gitlab\Model\IssueLink;
6+
use Gitlab\Model\Project;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class IssueLinkTest extends TestCase
10+
{
11+
/**
12+
* @test
13+
*/
14+
public function testCorrectConstruct()
15+
{
16+
$issue = $this->getMockBuilder(Issue::class)
17+
->disableOriginalConstructor()
18+
->getMock()
19+
;
20+
$client = $this->getMockBuilder(Client::class)
21+
->disableOriginalConstructor()
22+
->getMock()
23+
;
24+
25+
$issueLink = new IssueLink($issue, 1, $client);
26+
27+
$this->assertSame(1, $issueLink->issue_link_id);
28+
$this->assertSame($issue, $issueLink->issue);
29+
$this->assertSame($client, $issueLink->getClient());
30+
}
31+
32+
/**
33+
* @test
34+
*/
35+
public function testFromArray()
36+
{
37+
$client = $this->getMockBuilder(Client::class)
38+
->disableOriginalConstructor()
39+
->getMock()
40+
;
41+
$project = $this->getMockBuilder(Project::class)
42+
->disableOriginalConstructor()
43+
->getMock()
44+
;
45+
46+
$issueLink = IssueLink::fromArray($client, $project, ['issue_link_id' => 1, 'iid' => 10]);
47+
48+
$this->assertSame(1, $issueLink->issue_link_id);
49+
$this->assertInstanceOf(Issue::class, $issueLink->issue);
50+
$this->assertSame(10, $issueLink->issue->iid);
51+
$this->assertSame($client, $issueLink->getClient());
52+
}
53+
}

0 commit comments

Comments
 (0)