Skip to content

Commit 1a95695

Browse files
committed
Add method CustomField::listNames()
1 parent 7d99037 commit 1a95695

File tree

4 files changed

+221
-0
lines changed

4 files changed

+221
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- New method `Redmine\Api\CustomField::listNames()` for listing the ids and names of all custom fields.
1213
- New method `Redmine\Api\Group::listNames()` for listing the ids and names of all groups.
1314
- New method `Redmine\Api\IssueCategory::listNamesByProject()` for listing the ids and names of all issue categories of a project.
1415

src/Redmine/Api/CustomField.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class CustomField extends AbstractApi
1717
{
1818
private $customFields = [];
1919

20+
private $customFieldNames = null;
21+
2022
/**
2123
* List custom fields.
2224
*
@@ -37,6 +39,30 @@ final public function list(array $params = []): array
3739
}
3840
}
3941

42+
/**
43+
* Returns an array of all custom fields with id/name pairs.
44+
*
45+
* @return array<int,string> list of custom fields (id => name)
46+
*/
47+
final public function listNames(): array
48+
{
49+
if ($this->customFieldNames !== null) {
50+
return $this->customFieldNames;
51+
}
52+
53+
$this->customFieldNames = [];
54+
55+
$list = $this->list();
56+
57+
if (array_key_exists('custom_fields', $list)) {
58+
foreach ($list['custom_fields'] as $customField) {
59+
$this->customFieldNames[(int) $customField['id']] = (string) $customField['name'];
60+
}
61+
}
62+
63+
return $this->customFieldNames;
64+
}
65+
4066
/**
4167
* List custom fields.
4268
*

tests/Behat/features/custom_field.feature

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,89 @@ Feature: Interacting with the REST API for custom fields
1515
"""
1616
And the returned data "custom_fields" property is an array
1717
And the returned data "custom_fields" property contains "0" items
18+
19+
Scenario: Listing of multiple custom fields
20+
Given I have a "NativeCurlClient" client
21+
And I create a custom field for issues with the name "Note B"
22+
And I create a custom field for issues with the name "Note A"
23+
When I list all custom fields
24+
Then the response has the status code "200"
25+
And the response has the content type "application/json"
26+
And the returned data has only the following properties
27+
"""
28+
custom_fields
29+
"""
30+
And the returned data "custom_fields" property is an array
31+
And the returned data "custom_fields" property contains "2" items
32+
# field 'description' was added in Redmine 5.1.0, see https://www.redmine.org/issues/37617
33+
And the returned data "custom_fields.0" property contains the following data with Redmine version ">= 5.1.0"
34+
| property | value |
35+
| id | 1 |
36+
| name | Note B |
37+
| description | null |
38+
| customized_type | issue |
39+
| field_format | string |
40+
| regexp | |
41+
| min_length | null |
42+
| max_length | null |
43+
| is_required | false |
44+
| is_filter | false |
45+
| searchable | false |
46+
| multiple | false |
47+
| default_value | null |
48+
| visible | true |
49+
| trackers | [] |
50+
| roles | [] |
51+
But the returned data "custom_fields.0" property contains the following data with Redmine version "< 5.1.0"
52+
| property | value |
53+
| id | 1 |
54+
| name | Note B |
55+
| customized_type | issue |
56+
| field_format | string |
57+
| regexp | |
58+
| min_length | null |
59+
| max_length | null |
60+
| is_required | false |
61+
| is_filter | false |
62+
| searchable | false |
63+
| multiple | false |
64+
| default_value | null |
65+
| visible | true |
66+
| trackers | [] |
67+
| roles | [] |
68+
# field 'description' was added in Redmine 5.1.0, see https://www.redmine.org/issues/37617
69+
And the returned data "custom_fields.1" property contains the following data with Redmine version ">= 5.1.0"
70+
| property | value |
71+
| id | 2 |
72+
| name | Note A |
73+
| description | null |
74+
| customized_type | issue |
75+
| field_format | string |
76+
| regexp | |
77+
| min_length | null |
78+
| max_length | null |
79+
| is_required | false |
80+
| is_filter | false |
81+
| searchable | false |
82+
| multiple | false |
83+
| default_value | null |
84+
| visible | true |
85+
| trackers | [] |
86+
| roles | [] |
87+
But the returned data "custom_fields.1" property contains the following data with Redmine version "< 5.1.0"
88+
| property | value |
89+
| id | 2 |
90+
| name | Note A |
91+
| customized_type | issue |
92+
| field_format | string |
93+
| regexp | |
94+
| min_length | null |
95+
| max_length | null |
96+
| is_required | false |
97+
| is_filter | false |
98+
| searchable | false |
99+
| multiple | false |
100+
| default_value | null |
101+
| visible | true |
102+
| trackers | [] |
103+
| roles | [] |
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Redmine\Tests\Unit\Api\CustomField;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\TestCase;
10+
use Redmine\Api\CustomField;
11+
use Redmine\Tests\Fixtures\AssertingHttpClient;
12+
13+
#[CoversClass(CustomField::class)]
14+
class ListNamesTest extends TestCase
15+
{
16+
/**
17+
* @dataProvider getListNamesData
18+
*/
19+
#[DataProvider('getListNamesData')]
20+
public function testListNamesReturnsCorrectResponse($expectedPath, $responseCode, $response, $expectedResponse)
21+
{
22+
$client = AssertingHttpClient::create(
23+
$this,
24+
[
25+
'GET',
26+
$expectedPath,
27+
'application/json',
28+
'',
29+
$responseCode,
30+
'application/json',
31+
$response,
32+
],
33+
);
34+
35+
// Create the object under test
36+
$api = new CustomField($client);
37+
38+
// Perform the tests
39+
$this->assertSame($expectedResponse, $api->listNames());
40+
}
41+
42+
public static function getListNamesData(): array
43+
{
44+
return [
45+
'test without custom fields' => [
46+
'/custom_fields.json',
47+
201,
48+
<<<JSON
49+
{
50+
"custom_fields": []
51+
}
52+
JSON,
53+
[],
54+
],
55+
'test with multiple custom fields' => [
56+
'/custom_fields.json',
57+
201,
58+
<<<JSON
59+
{
60+
"custom_fields": [
61+
{"id": 7, "name": "CustomField 3"},
62+
{"id": 8, "name": "CustomField 2"},
63+
{"id": 9, "name": "CustomField 1"}
64+
]
65+
}
66+
JSON,
67+
[
68+
7 => "CustomField 3",
69+
8 => "CustomField 2",
70+
9 => "CustomField 1",
71+
],
72+
],
73+
];
74+
}
75+
76+
public function testListNamesCallsHttpClientOnlyOnce()
77+
{
78+
$client = AssertingHttpClient::create(
79+
$this,
80+
[
81+
'GET',
82+
'/custom_fields.json',
83+
'application/json',
84+
'',
85+
200,
86+
'application/json',
87+
<<<JSON
88+
{
89+
"custom_fields": [
90+
{
91+
"id": 1,
92+
"name": "CustomField 1"
93+
}
94+
]
95+
}
96+
JSON,
97+
],
98+
);
99+
100+
// Create the object under test
101+
$api = new CustomField($client);
102+
103+
// Perform the tests
104+
$this->assertSame([1 => 'CustomField 1'], $api->listNames());
105+
$this->assertSame([1 => 'CustomField 1'], $api->listNames());
106+
$this->assertSame([1 => 'CustomField 1'], $api->listNames());
107+
}
108+
}

0 commit comments

Comments
 (0)