Skip to content

Commit 097ac2e

Browse files
authored
Merge pull request kbsali#412 from Art4/add-role-listnames
Add `Role::listNames()` method as replacement for `Role::listing()`
2 parents 8fab7fb + a2ea0d4 commit 097ac2e

File tree

6 files changed

+257
-0
lines changed

6 files changed

+257
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- New method `Redmine\Api\IssueCategory::listNamesByProject()` for listing the ids and names of all issue categories of a project.
1515
- New method `Redmine\Api\IssueStatus::listNames()` for listing the ids and names of all issue statuses.
1616
- New method `Redmine\Api\Project::listNames()` for listing the ids and names of all projects.
17+
- New method `Redmine\Api\Role::listNames()` for listing the ids and names of all roles.
1718

1819
### Deprecated
1920

@@ -22,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2223
- `Redmine\Api\IssueCategory::listing()` is deprecated, use `\Redmine\Api\IssueCategory::listNamesByProject()` instead.
2324
- `Redmine\Api\IssueStatus::listing()` is deprecated, use `\Redmine\Api\IssueStatus::listNamesByProject()` instead.
2425
- `Redmine\Api\Project::listing()` is deprecated, use `\Redmine\Api\Project::listNamesByProject()` instead.
26+
- `Redmine\Api\Role::listing()` is deprecated, use `\Redmine\Api\Role::listNamesByProject()` instead.
2527

2628
## [v2.6.0](https://github.com/kbsali/php-redmine-api/compare/v2.5.0...v2.6.0) - 2024-03-25
2729

src/Redmine/Api/Role.php

+30
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Role extends AbstractApi
1919
{
2020
private $roles = [];
2121

22+
private $roleNames = null;
23+
2224
/**
2325
* List roles.
2426
*
@@ -39,6 +41,29 @@ final public function list(array $params = []): array
3941
}
4042
}
4143

44+
/**
45+
* Returns an array of all roles with id/name pairs.
46+
*
47+
* @return array<int,string> list of roles (id => name)
48+
*/
49+
final public function listNames(): array
50+
{
51+
if ($this->roleNames !== null) {
52+
return $this->roleNames;
53+
}
54+
55+
$this->roleNames = [];
56+
$list = $this->list();
57+
58+
if (array_key_exists('roles', $list)) {
59+
foreach ($list['roles'] as $role) {
60+
$this->roleNames[(int) $role['id']] = $role['name'];
61+
}
62+
}
63+
64+
return $this->roleNames;
65+
}
66+
4267
/**
4368
* List roles.
4469
*
@@ -75,12 +100,17 @@ public function all(array $params = [])
75100
/**
76101
* Returns an array of roles with name/id pairs.
77102
*
103+
* @deprecated v2.7.0 Use listNames() instead.
104+
* @see Role::listNames()
105+
*
78106
* @param bool $forceUpdate to force the update of the roles var
79107
*
80108
* @return array list of roles (id => name)
81109
*/
82110
public function listing($forceUpdate = false)
83111
{
112+
@trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED);
113+
84114
if (empty($this->roles) || $forceUpdate) {
85115
$this->roles = $this->list();
86116
}

tests/Behat/Bootstrap/RoleContextTrait.php

+30
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Redmine\Tests\Behat\Bootstrap;
66

7+
use Redmine\Api\Role;
8+
79
trait RoleContextTrait
810
{
911
/**
@@ -28,4 +30,32 @@ public function iHaveARoleWithTheName($name)
2830
],
2931
);
3032
}
33+
34+
/**
35+
* @When I list all roles
36+
*/
37+
public function iListAllRoles()
38+
{
39+
/** @var Role */
40+
$api = $this->getNativeCurlClient()->getApi('role');
41+
42+
$this->registerClientResponse(
43+
$api->list(),
44+
$api->getLastResponse(),
45+
);
46+
}
47+
48+
/**
49+
* @When I list all role names
50+
*/
51+
public function iListAllRoleNames()
52+
{
53+
/** @var Role */
54+
$api = $this->getNativeCurlClient()->getApi('role');
55+
56+
$this->registerClientResponse(
57+
$api->listNames(),
58+
$api->getLastResponse(),
59+
);
60+
}
3161
}

tests/Behat/features/role.feature

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
@role
2+
Feature: Interacting with the REST API for roles
3+
In order to interact with REST API for roles
4+
As a user
5+
I want to make sure the Redmine server replies with the correct response
6+
7+
Scenario: Listing of zero roles
8+
Given I have a "NativeCurlClient" client
9+
When I list all roles
10+
Then the response has the status code "200"
11+
And the response has the content type "application/json"
12+
And the returned data has only the following properties
13+
"""
14+
roles
15+
"""
16+
And the returned data "roles" property is an array
17+
And the returned data "roles" property contains "0" items
18+
19+
Scenario: Listing of multiple roles
20+
Given I have a "NativeCurlClient" client
21+
And I have a role with the name "Reporter"
22+
And I have a role with the name "Developer"
23+
When I list all roles
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+
roles
29+
"""
30+
And the returned data "roles" property is an array
31+
And the returned data "roles" property contains "2" items
32+
And the returned data "roles.0" property contains "2" items
33+
And the returned data "roles.0" property contains the following data
34+
| property | value |
35+
| id | 3 |
36+
| name | Reporter |
37+
And the returned data "roles.1" property contains "2" items
38+
And the returned data "roles.1" property contains the following data
39+
| property | value |
40+
| id | 4 |
41+
| name | Developer |
42+
43+
Scenario: Listing of multiple role names
44+
Given I have a "NativeCurlClient" client
45+
And I have a role with the name "Reporter"
46+
And I have a role with the name "Developer"
47+
When I list all role names
48+
Then the response has the status code "200"
49+
And the response has the content type "application/json"
50+
And the returned data is an array
51+
And the returned data contains "2" items
52+
And the returned data contains the following data
53+
| property | value |
54+
| 3 | Reporter |
55+
| 4 | Developer |

tests/Unit/Api/Role/ListNamesTest.php

+108
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\Role;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\TestCase;
10+
use Redmine\Api\Role;
11+
use Redmine\Tests\Fixtures\AssertingHttpClient;
12+
13+
#[CoversClass(Role::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 Role($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 roles' => [
46+
'/roles.json',
47+
201,
48+
<<<JSON
49+
{
50+
"roles": []
51+
}
52+
JSON,
53+
[],
54+
],
55+
'test with multiple roles' => [
56+
'/roles.json',
57+
201,
58+
<<<JSON
59+
{
60+
"roles": [
61+
{"id": 7, "name": "Role 3"},
62+
{"id": 8, "name": "Role 2"},
63+
{"id": 9, "name": "Role 1"}
64+
]
65+
}
66+
JSON,
67+
[
68+
7 => "Role 3",
69+
8 => "Role 2",
70+
9 => "Role 1",
71+
],
72+
],
73+
];
74+
}
75+
76+
public function testListNamesCallsHttpClientOnlyOnce()
77+
{
78+
$client = AssertingHttpClient::create(
79+
$this,
80+
[
81+
'GET',
82+
'/roles.json',
83+
'application/json',
84+
'',
85+
200,
86+
'application/json',
87+
<<<JSON
88+
{
89+
"roles": [
90+
{
91+
"id": 1,
92+
"name": "Role 1"
93+
}
94+
]
95+
}
96+
JSON,
97+
],
98+
);
99+
100+
// Create the object under test
101+
$api = new Role($client);
102+
103+
// Perform the tests
104+
$this->assertSame([1 => 'Role 1'], $api->listNames());
105+
$this->assertSame([1 => 'Role 1'], $api->listNames());
106+
$this->assertSame([1 => 'Role 1'], $api->listNames());
107+
}
108+
}

tests/Unit/Api/RoleTest.php

+32
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,36 @@ public function testListingCallsGetEveryTimeWithForceUpdate()
214214
$this->assertSame($expectedReturn, $api->listing(true));
215215
$this->assertSame($expectedReturn, $api->listing(true));
216216
}
217+
218+
/**
219+
* Test listing().
220+
*/
221+
public function testListingTriggersDeprecationWarning()
222+
{
223+
$client = $this->createMock(Client::class);
224+
$client->method('requestGet')
225+
->willReturn(true);
226+
$client->method('getLastResponseBody')
227+
->willReturn('{"roles":[{"id":1,"name":"Role 1"},{"id":5,"name":"Role 5"}]}');
228+
$client->method('getLastResponseContentType')
229+
->willReturn('application/json');
230+
231+
$api = new Role($client);
232+
233+
// PHPUnit 10 compatible way to test trigger_error().
234+
set_error_handler(
235+
function ($errno, $errstr): bool {
236+
$this->assertSame(
237+
'`Redmine\Api\Role::listing()` is deprecated since v2.7.0, use `Redmine\Api\Role::listNames()` instead.',
238+
$errstr,
239+
);
240+
241+
restore_error_handler();
242+
return true;
243+
},
244+
E_USER_DEPRECATED,
245+
);
246+
247+
$api->listing();
248+
}
217249
}

0 commit comments

Comments
 (0)