Skip to content

Commit 18fc838

Browse files
committed
Merge branch 'feature/webhooks' into develop
Implemented webhooks endpoints Support new [webhooks system][1]. Close #29 [1]: https://confluence.atlassian.com/display/BITBUCKET/Manage+Webhooks
2 parents e9f8230 + 829c04b commit 18fc838

File tree

4 files changed

+353
-2
lines changed

4 files changed

+353
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5-
## [Unreleased][unreleased]
5+
## [0.7.0] / [unreleased]
6+
7+
### Added:
8+
- Implemented webhooks endpoints.
69

710
## 0.6.2 / 2015-05-18
811

lib/Bitbucket/API/Http/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Client extends ClientListener implements ClientInterface
3333
'api_versions' => array('1.0', '2.0'), // supported versions
3434
'format' => 'json',
3535
'formats' => array('json', 'xml'), // supported response formats
36-
'user_agent' => 'bitbucket-api-php/0.6.2 (https://bitbucket.org/gentlero/bitbucket-api)',
36+
'user_agent' => 'bitbucket-api-php/0.7.0 (https://bitbucket.org/gentlero/bitbucket-api)',
3737
'timeout' => 10,
3838
'verify_peer' => false
3939
);
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the bitbucket-api package.
5+
*
6+
* (c) Alexandru Guzinschi <alex@gentle.ro>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Bitbucket\API\Repositories;
13+
14+
use Bitbucket\API;
15+
use Buzz\Message\MessageInterface;
16+
17+
/**
18+
* @author Alexandru Guzinschi <alex@gentle.ro>
19+
*/
20+
class Hooks extends API\Api
21+
{
22+
/**
23+
* @access public
24+
* @param string $account The team or individual account owning the repository.
25+
* @param string $repo The repository identifier.
26+
* @param array $params Additional service parameters
27+
* @return MessageInterface
28+
*
29+
* @throws \InvalidArgumentException
30+
*/
31+
public function create($account, $repo, array $params = array())
32+
{
33+
$mandatory = array(
34+
'description' => 'My webhook',
35+
'url' => '',
36+
'active' => true,
37+
'events' => array()
38+
);
39+
40+
$diff = array_diff(array_keys($mandatory), array_keys($params));
41+
42+
if (count($diff) > 0) {
43+
throw new \InvalidArgumentException('Missing parameters for creating a new webhook.');
44+
}
45+
46+
if (false === array_key_exists('events', $params) || 0 === count($params['events'])) {
47+
throw new \InvalidArgumentException('Missing events for creating a new webhook.');
48+
}
49+
50+
return $this->getClient()->setApiVersion('2.0')->post(
51+
sprintf('repositories/%s/%s/hooks', $account, $repo),
52+
json_encode($params),
53+
array('Content-Type' => 'application/json')
54+
);
55+
}
56+
57+
/**
58+
* @access public
59+
* @param string $account The team or individual account owning the repository.
60+
* @param string $repo The repository identifier.
61+
* @param string $uuid The universally unique identifier of the webhook.
62+
* @param array $params Additional service parameters
63+
* @return MessageInterface
64+
*
65+
* @throws \InvalidArgumentException
66+
*/
67+
public function update($account, $repo, $uuid, array $params = array())
68+
{
69+
$mandatory = array(
70+
'description' => 'My webhook',
71+
'url' => '',
72+
'active' => true,
73+
'events' => array()
74+
);
75+
76+
$diff = array_diff(array_keys($mandatory), array_keys($params));
77+
78+
if (count($diff) > 0) {
79+
throw new \InvalidArgumentException('Missing parameters for updating a webhook.');
80+
}
81+
82+
if (false === array_key_exists('events', $params) || 0 === count($params['events'])) {
83+
throw new \InvalidArgumentException('Missing events for updating a new webhook.');
84+
}
85+
86+
return $this->getClient()->setApiVersion('2.0')->put(
87+
sprintf('repositories/%s/%s/hooks/%s', $account, $repo, $uuid),
88+
json_encode($params),
89+
array('Content-Type' => 'application/json')
90+
);
91+
}
92+
93+
/**
94+
* @access public
95+
* @param string $account The team or individual account owning the repository.
96+
* @param string $repo The repository identifier.
97+
* @return MessageInterface
98+
*/
99+
public function all($account, $repo)
100+
{
101+
return $this->getClient()->setApiVersion('2.0')->get(
102+
sprintf('repositories/%s/%s/hooks', $account, $repo)
103+
);
104+
}
105+
106+
/**
107+
* @access public
108+
* @param string $account The team or individual account owning the repository.
109+
* @param string $repo The repository identifier.
110+
* @param string $uuid The universally unique identifier of the webhook.
111+
* @return MessageInterface
112+
*/
113+
public function get($account, $repo, $uuid)
114+
{
115+
return $this->getClient()->setApiVersion('2.0')->get(
116+
sprintf('repositories/%s/%s/hooks/%s', $account, $repo, $uuid)
117+
);
118+
}
119+
120+
/**
121+
* @access public
122+
* @param string $account The team or individual account owning the repository.
123+
* @param string $repo The repository identifier.
124+
* @param string $uuid The universally unique identifier of the webhook.
125+
* @return MessageInterface
126+
*/
127+
public function delete($account, $repo, $uuid)
128+
{
129+
return $this->getClient()->setApiVersion('2.0')->delete(
130+
sprintf('repositories/%s/%s/hooks/%s', $account, $repo, $uuid)
131+
);
132+
}
133+
}
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the bitbucket-api package.
5+
*
6+
* (c) Alexandru Guzinschi <alex@gentle.ro>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Bitbucket\Tests\API\Repositories;
13+
14+
use Bitbucket\Tests\API as Tests;
15+
use Bitbucket\API;
16+
17+
class HooksTest extends Tests\TestCase
18+
{
19+
public function invalidCreateProvider()
20+
{
21+
return array(
22+
array(array(
23+
'dummy' => 'data',
24+
)),
25+
array(array(
26+
'description' => 'My webhook',
27+
'url' => '',
28+
'active' => true,
29+
)),
30+
array(array(
31+
'description' => 'My webhook',
32+
'url' => '',
33+
'active' => true,
34+
'events' => array(),
35+
)),
36+
array(array(
37+
'description' => 'My webhook',
38+
'url' => '',
39+
'events' => array(
40+
'event1',
41+
'event2',
42+
),
43+
)),
44+
array(array(
45+
'description' => 'My webhook',
46+
'active' => true,
47+
'events' => array(
48+
'event1',
49+
'event2',
50+
),
51+
'extra' => 'Allow user to specify custom data',
52+
)),
53+
);
54+
}
55+
56+
/**
57+
* @access public
58+
* @param mixed $check
59+
* @return void
60+
*
61+
* @expectedException \InvalidArgumentException
62+
* @dataProvider invalidCreateProvider
63+
*/
64+
public function testInvalidCreate($check)
65+
{
66+
$client = $this->getHttpClientMock();
67+
68+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
69+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
70+
$hooks->create('gentle', 'my-repo', $check);
71+
}
72+
73+
public function testCreateSuccess()
74+
{
75+
$endpoint = 'repositories/gentle/eof/hooks';
76+
$params = array(
77+
'description' => 'My first webhook',
78+
'url' => 'http://requestb.in/xxx',
79+
'active' => true,
80+
'events' => array(
81+
'repo:push',
82+
'issue:created',
83+
),
84+
);
85+
86+
$client = $this->getHttpClientMock();
87+
$client->expects($this->any())
88+
->method('post')
89+
->with($endpoint, json_encode($params))
90+
;
91+
92+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
93+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
94+
$hooks->create('gentle', 'eof', $params);
95+
}
96+
97+
public function testCreateSuccessWithExtraParameters()
98+
{
99+
$endpoint = 'repositories/gentle/eof/hooks';
100+
$params = array(
101+
'description' => 'My first webhook',
102+
'url' => 'http://requestb.in/xxx',
103+
'active' => true,
104+
'extra' => 'User can specify additional parameters',
105+
'events' => array(
106+
'repo:push',
107+
'issue:created',
108+
),
109+
);
110+
111+
$client = $this->getHttpClientMock();
112+
$client->expects($this->any())
113+
->method('post')
114+
->with($endpoint, json_encode($params))
115+
;
116+
117+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
118+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
119+
$hooks->create('gentle', 'eof', $params);
120+
}
121+
122+
public function testUpdateSuccess()
123+
{
124+
$endpoint = 'repositories/gentle/eof/hooks/30b60aee-9cdf-407d-901c-2de106ee0c9d';
125+
$params = array(
126+
'description' => 'My first webhook',
127+
'url' => 'http://requestb.in/zzz',
128+
'active' => true,
129+
'events' => array(
130+
'repo:push',
131+
'issue:created',
132+
),
133+
);
134+
135+
$client = $this->getHttpClientMock();
136+
$client->expects($this->any())
137+
->method('put')
138+
->with($endpoint, json_encode($params))
139+
;
140+
141+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
142+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
143+
$hooks->update('gentle', 'eof', '30b60aee-9cdf-407d-901c-2de106ee0c9d', $params);
144+
}
145+
146+
/**
147+
* @access public
148+
* @param mixed $check
149+
* @return void
150+
*
151+
* @expectedException \InvalidArgumentException
152+
* @dataProvider invalidCreateProvider
153+
*/
154+
public function testInvalidUpdate($check)
155+
{
156+
$client = $this->getHttpClientMock();
157+
158+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
159+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
160+
$hooks->update('gentle', 'eof', '30b60aee-9cdf-407d-901c-2de106ee0c9d', $check);
161+
}
162+
163+
public function testGetAllHooks()
164+
{
165+
$endpoint = 'repositories/gentle/eof/hooks';
166+
$expectedResult = $this->fakeResponse(array('dummy'));
167+
168+
$client = $this->getHttpClientMock();
169+
$client->expects($this->any())
170+
->method('get')
171+
->with($endpoint)
172+
->will($this->returnValue($expectedResult))
173+
;
174+
175+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
176+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
177+
$actual = $hooks->all('gentle', 'eof');
178+
179+
$this->assertEquals($expectedResult, $actual);
180+
}
181+
182+
public function testGetSingleHook()
183+
{
184+
$endpoint = 'repositories/gentle/eof/hooks/30b60aee-9cdf-407d-901c-2de106ee0c9d';
185+
$expectedResult = $this->fakeResponse(array('dummy'));
186+
187+
$client = $this->getHttpClientMock();
188+
$client->expects($this->any())
189+
->method('get')
190+
->with($endpoint)
191+
->will($this->returnValue($expectedResult))
192+
;
193+
194+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
195+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
196+
$actual = $hooks->get('gentle', 'eof', '30b60aee-9cdf-407d-901c-2de106ee0c9d');
197+
198+
$this->assertEquals($expectedResult, $actual);
199+
}
200+
201+
public function testDeleteSingleHook()
202+
{
203+
$endpoint = 'repositories/gentle/eof/hooks/30b60aee-9cdf-407d-901c-2de106ee0c9d';
204+
205+
$client = $this->getHttpClientMock();
206+
$client->expects($this->once())
207+
->method('delete')
208+
->with($endpoint);
209+
210+
/** @var \Bitbucket\API\Repositories\Hooks $hooks */
211+
$hooks = $this->getClassMock('Bitbucket\API\Repositories\Hooks', $client);
212+
213+
$hooks->delete('gentle', 'eof', '30b60aee-9cdf-407d-901c-2de106ee0c9d');
214+
}
215+
}

0 commit comments

Comments
 (0)