Skip to content

Commit e6311d8

Browse files
committed
update merge requests api for v4 api
1 parent dcbc960 commit e6311d8

File tree

6 files changed

+228
-195
lines changed

6 files changed

+228
-195
lines changed

UPGRADE.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ See [documentation](doc/customize.md) to know how to customize the client timeou
2525

2626
## `Gitlab\Api\MergeRequests` changes
2727

28-
* The `getList` method have been removed. Use `all` instead.
28+
* The `getList`, `getByIid`, `merged`, `opened` and `closed` methods have been removed. Use `all` method instead.
29+
* The `ORDER_BY` and `SORT` class constants have been removed.
30+
* The `all` method now take a single argument which is an associative array of query string parameters.
31+
* The `getNotes` method now take only two arguments, the project id and the merge request iid.
2932

3033
## `Gitlab\Api\Projects` changes
3134

lib/Gitlab/Api/AbstractApi.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<?php namespace Gitlab\Api;
22

33
use Gitlab\Client;
4+
use Gitlab\HttpClient\Message\QueryStringBuilder;
45
use Gitlab\HttpClient\Message\ResponseMediator;
6+
use Gitlab\Tests\HttpClient\Message\QueryStringBuilderTest;
57
use Http\Discovery\StreamFactoryDiscovery;
68
use Http\Message\MultipartStream\MultipartStreamBuilder;
79
use Http\Message\StreamFactory;
@@ -216,8 +218,9 @@ protected function createOptionsResolver()
216218

217219
private function preparePath($path, array $parameters = [])
218220
{
221+
219222
if (count($parameters) > 0) {
220-
$path .= '?'.http_build_query($parameters);
223+
$path .= '?'.QueryStringBuilder::build($parameters);
221224
}
222225

223226
return $path;

lib/Gitlab/Api/MergeRequests.php

Lines changed: 61 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,71 @@
11
<?php namespace Gitlab\Api;
22

3+
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
4+
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
5+
36
class MergeRequests extends AbstractApi
47
{
58
const STATE_ALL = 'all';
69
const STATE_MERGED = 'merged';
710
const STATE_OPENED = 'opened';
811
const STATE_CLOSED = 'closed';
912

10-
const ORDER_BY = 'created_at';
11-
const SORT = 'asc';
12-
13-
/**
14-
* @param int $project_id
15-
* @param int $page
16-
* @param int $per_page
17-
* @param string $order_by
18-
* @param string $sort
19-
* @return mixed
20-
*/
21-
public function all($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
22-
{
23-
return $this->getList($project_id, self::STATE_ALL, $page, $per_page, $order_by, $sort);
24-
}
25-
2613
/**
27-
* @param int $project_id
28-
* @param int $page
29-
* @param int $per_page
30-
* @param string $order_by
31-
* @param string $sort
32-
* @return mixed
33-
*/
34-
public function merged($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
35-
{
36-
return $this->getList($project_id, self::STATE_MERGED, $page, $per_page, $order_by, $sort);
37-
}
38-
39-
/**
40-
* @param int $project_id
41-
* @param int $page
42-
* @param int $per_page
43-
* @param string $order_by
44-
* @param string $sort
45-
* @return mixed
46-
*/
47-
public function opened($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
48-
{
49-
return $this->getList($project_id, self::STATE_OPENED, $page, $per_page, $order_by, $sort);
50-
}
51-
52-
/**
53-
* @param int $project_id
54-
* @param int $page
55-
* @param int $per_page
56-
* @param string $order_by
57-
* @param string $sort
14+
* @param int $project_id
15+
* @param array $parameters {
16+
*
17+
* @var int[] $iids Return the request having the given iid.
18+
* @var string $state Return all merge requests or just those that are opened, closed, or
19+
* merged.
20+
* @var string $order_by Return requests ordered by created_at or updated_at fields. Default
21+
* is created_at.
22+
* @var string $sort Return requests sorted in asc or desc order. Default is desc.
23+
* @var string $milestone Return merge requests for a specific milestone.
24+
* @var string $view If simple, returns the iid, URL, title, description, and basic state
25+
* of merge request.
26+
* @var string $labels Return merge requests matching a comma separated list of labels.
27+
* @var \DateTimeInterface $created_after Return merge requests created after the given time (inclusive).
28+
* @var \DateTimeInterface $created_before Return merge requests created before the given time (inclusive).
29+
* }
30+
*
31+
* @throws UndefinedOptionsException If an option name is undefined.
32+
* @throws InvalidOptionsException If an option doesn't fulfill the specified validation rules.
33+
*
5834
* @return mixed
5935
*/
60-
public function closed($project_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = self::SORT)
61-
{
62-
return $this->getList($project_id, self::STATE_CLOSED, $page, $per_page, $order_by, $sort);
36+
public function all($project_id, array $parameters = [])
37+
{
38+
$resolver = $this->createOptionsResolver();
39+
$datetimeNormalizer = function (\DateTimeInterface $value) {
40+
return $value->format('c');
41+
};
42+
$resolver->setDefined('iids')
43+
->setAllowedTypes('iids', 'array')
44+
->setAllowedValues('iids', function (array $value) {
45+
return count($value) == count(array_filter($value, 'is_int'));
46+
})
47+
;
48+
$resolver->setDefined('state')
49+
->setAllowedValues('state', ['all', 'opened', 'merged', 'closed'])
50+
;
51+
$resolver->setDefined('order_by')
52+
->setAllowedValues('order_by', ['created_at', 'updated_at'])
53+
;
54+
$resolver->setDefined('milestone');
55+
$resolver->setDefined('view')
56+
->setAllowedValues('view', ['simple'])
57+
;
58+
$resolver->setDefined('labels');
59+
$resolver->setDefined('created_after')
60+
->setAllowedTypes('created_after', \DateTimeInterface::class)
61+
->setNormalizer('created_after', $datetimeNormalizer)
62+
;
63+
$resolver->setDefined('created_before')
64+
->setAllowedTypes('created_before', \DateTimeInterface::class)
65+
->setNormalizer('created_before', $datetimeNormalizer)
66+
;
67+
68+
return $this->get($this->getProjectPath($project_id, 'merge_requests'), $resolver->resolve($parameters));
6369
}
6470

6571
/**
@@ -123,13 +129,14 @@ public function merge($project_id, $mr_id, $message = null)
123129
}
124130

125131
/**
126-
* @param int $project_id
127-
* @param int $mr_id
132+
* @param int $project_id
133+
* @param int $mr_id
134+
*
128135
* @return mixed
129136
*/
130-
public function showNotes($project_id, $mr_id, $page = 1, $per_page = self::PER_PAGE, $order_by = self::ORDER_BY, $sort = 'desc')
137+
public function showNotes($project_id, $mr_id)
131138
{
132-
return $this->getList($project_id, null, $page, $per_page, $order_by, $sort, 'merge_requests/'.$this->encodePath($mr_id).'/notes');
139+
return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/notes'));
133140
}
134141

135142
/**
@@ -178,16 +185,6 @@ public function changes($project_id, $mr_id)
178185
return $this->get($this->getProjectPath($project_id, 'merge_requests/'.$this->encodePath($mr_id).'/changes'));
179186
}
180187

181-
/**
182-
* @param $project_id
183-
* @param $mr_iid
184-
* @return mixed
185-
*/
186-
public function getByIid($project_id, $mr_iid)
187-
{
188-
return $this->get($this->getProjectPath($project_id, 'merge_requests'), array('iid' => $mr_iid));
189-
}
190-
191188
/**
192189
* @param int $project_id
193190
* @param int $mr_id
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Gitlab\HttpClient\Message;
4+
5+
final class QueryStringBuilder
6+
{
7+
/**
8+
* Encode a query as a query string according to RFC 3986. Indexed arrays are encoded using
9+
* empty squared brackets ([]) unlike http_build_query.
10+
*
11+
* @param mixed $query
12+
*
13+
* @return string
14+
*/
15+
public static function build($query)
16+
{
17+
if (!is_array($query)) {
18+
return rawurlencode($query);
19+
}
20+
return implode('&', array_map(function ($value, $key) {
21+
return static::encode($value, $key);
22+
}, $query, array_keys($query)));
23+
}
24+
25+
/**
26+
* Encode a value
27+
* @param mixed $query
28+
* @param string $prefix
29+
*
30+
* @return string
31+
*/
32+
private static function encode($query, $prefix)
33+
{
34+
if (!is_array($query)) {
35+
return rawurlencode($prefix).'='.rawurlencode($query);
36+
}
37+
38+
$isIndexedArray = static::isIndexedArray($query);
39+
return implode('&', array_map(function ($value, $key) use ($prefix, $isIndexedArray) {
40+
$prefix = $isIndexedArray ? $prefix.'[]' : $prefix.'['.$key.']';
41+
return static::encode($value, $prefix);
42+
}, $query, array_keys($query)));
43+
}
44+
45+
/**
46+
* Tell if the given array is an indexed one (i.e. contains only sequential integer keys starting from 0).
47+
*
48+
* @param array $query
49+
*
50+
* @return bool
51+
*/
52+
public static function isIndexedArray(array $query)
53+
{
54+
if (empty($query) || !isset($query[0])) {
55+
return false;
56+
}
57+
58+
return array_keys($query) === range(0, count($query) - 1);
59+
}
60+
}

0 commit comments

Comments
 (0)