diff --git a/.gitattributes b/.gitattributes index 2eb384a6..a5487307 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1,4 @@ -.docker export-ignore -.github export-ignore -.editorconfig export-ignore -.gitattributes export-ignore -.gitignore export-ignore -.php-cs-fixer.php export-ignore -.phpstan.neon export-ignore -.scrutinizer.yml export-ignore -.docker-compose.yml export-ignore +.* export-ignore +docker-compose.yml +phpunit.xml.dist export-ignore +tests export-ignore diff --git a/CHANGELOG.md b/CHANGELOG.md index d984b244..4da2eccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,15 +25,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Deprecated - `Redmine\Api\CustomField::listing()` is deprecated, use `\Redmine\Api\CustomField::listNames()` instead. +- `Redmine\Api\CustomField::getIdByName()` is deprecated, use `\Redmine\Api\CustomField::listNames()` instead. - `Redmine\Api\Group::listing()` is deprecated, use `\Redmine\Api\Group::listNames()` instead. - `Redmine\Api\IssueCategory::listing()` is deprecated, use `\Redmine\Api\IssueCategory::listNamesByProject()` instead. +- `Redmine\Api\IssueCategory::getIdByName()` is deprecated, use `\Redmine\Api\IssueCategory::listNamesByProject()` instead. - `Redmine\Api\IssueStatus::listing()` is deprecated, use `\Redmine\Api\IssueStatus::listNames()` instead. +- `Redmine\Api\IssueStatus::getIdByName()` is deprecated, use `\Redmine\Api\IssueStatus::listNames()` instead. - `Redmine\Api\Project::listing()` is deprecated, use `\Redmine\Api\Project::listNames()` instead. +- `Redmine\Api\Project::getIdByName()` is deprecated, use `\Redmine\Api\Project::listNames()` instead. - `Redmine\Api\Role::listing()` is deprecated, use `\Redmine\Api\Role::listNames()` instead. - `Redmine\Api\TimeEntryActivity::listing()` is deprecated, use `\Redmine\Api\TimeEntryActivity::listNames()` instead. +- `Redmine\Api\TimeEntryActivity::getIdByName()` is deprecated, use `\Redmine\Api\TimeEntryActivity::listNames()` instead. - `Redmine\Api\Tracker::listing()` is deprecated, use `\Redmine\Api\Tracker::listNames()` instead. +- `Redmine\Api\Tracker::getIdByName()` is deprecated, use `\Redmine\Api\Tracker::listNames()` instead. - `Redmine\Api\User::listing()` is deprecated, use `\Redmine\Api\User::listLogins()` instead. +- `Redmine\Api\User::getIdByUsername()` is deprecated, use `\Redmine\Api\User::listLogins()` instead. - `Redmine\Api\Version::listing()` is deprecated, use `\Redmine\Api\Version::listNamesByProject()` instead. +- `Redmine\Api\Version::getIdByName()` is deprecated, use `\Redmine\Api\Version::listNamesByProject()` instead. ## [v2.6.0](https://github.com/kbsali/php-redmine-api/compare/v2.5.0...v2.6.0) - 2024-03-25 diff --git a/src/Redmine/Api/CustomField.php b/src/Redmine/Api/CustomField.php index 54c1366b..da88d5b6 100644 --- a/src/Redmine/Api/CustomField.php +++ b/src/Redmine/Api/CustomField.php @@ -111,19 +111,14 @@ public function listing($forceUpdate = false, array $params = []) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); - if (empty($this->customFields) || $forceUpdate) { - $this->customFields = $this->list($params); - } - $ret = []; - foreach ($this->customFields['custom_fields'] as $e) { - $ret[$e['name']] = (int) $e['id']; - } - - return $ret; + return $this->doListing($forceUpdate, $params); } /** - * Get a tracket id given its name. + * Get a custom field id given its name. + * + * @deprecated v2.7.0 Use listNames() instead. + * @see CustomField::listNames() * * @param string|int $name customer field name * @param array $params optional parameters to be passed to the api (offset, limit, ...) @@ -132,11 +127,29 @@ public function listing($forceUpdate = false, array $params = []) */ public function getIdByName($name, array $params = []) { - $arr = $this->listing(false, $params); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false, $params); + if (!isset($arr[$name])) { return false; } return $arr[(string) $name]; } + + private function doListing(bool $forceUpdate, array $params) + { + if (empty($this->customFields) || $forceUpdate) { + $this->customFields = $this->list($params); + } + + $ret = []; + + foreach ($this->customFields['custom_fields'] as $e) { + $ret[$e['name']] = (int) $e['id']; + } + + return $ret; + } } diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php index 1c98dceb..fde13968 100644 --- a/src/Redmine/Api/Issue.php +++ b/src/Redmine/Api/Issue.php @@ -319,7 +319,7 @@ public function setIssueStatus($id, $status) $issueStatusApi = $this->getIssueStatusApi(); return $this->update($id, [ - 'status_id' => $issueStatusApi->getIdByName($status), + 'status_id' => array_search($status, $issueStatusApi->listNames(), true), ]); } @@ -348,42 +348,67 @@ private function cleanParams(array $params = []) if (isset($params['project'])) { $projectApi = $this->getProjectApi(); - $params['project_id'] = $projectApi->getIdByName($params['project']); + // TODO: project names are not unique; there could be collisions + $params['project_id'] = array_search( + $params['project'], + $projectApi->listNames(), + true, + ); unset($params['project']); } if (isset($params['category']) && isset($params['project_id'])) { $issueCategoryApi = $this->getIssueCategoryApi(); - $params['category_id'] = $issueCategoryApi->getIdByName($params['project_id'], $params['category']); + $params['category_id'] = array_search( + $params['category'], + $issueCategoryApi->listNamesByProject($params['project_id']), + true, + ); unset($params['category']); } if (isset($params['status'])) { $issueStatusApi = $this->getIssueStatusApi(); - $params['status_id'] = $issueStatusApi->getIdByName($params['status']); + $params['status_id'] = array_search( + $params['status'], + $issueStatusApi->listNames(), + true, + ); unset($params['status']); } if (isset($params['tracker'])) { $trackerApi = $this->getTrackerApi(); - $params['tracker_id'] = $trackerApi->getIdByName($params['tracker']); + $params['tracker_id'] = array_search( + $params['tracker'], + $trackerApi->listNames(), + true, + ); unset($params['tracker']); } if (isset($params['assigned_to'])) { $userApi = $this->getUserApi(); - $params['assigned_to_id'] = $userApi->getIdByUsername($params['assigned_to']); + $params['assigned_to_id'] = array_search( + $params['assigned_to'], + $userApi->listLogins(), + true, + ); unset($params['assigned_to']); } if (isset($params['author'])) { $userApi = $this->getUserApi(); - $params['author_id'] = $userApi->getIdByUsername($params['author']); + $params['author_id'] = array_search( + $params['author'], + $userApi->listLogins(), + true, + ); unset($params['author']); } diff --git a/src/Redmine/Api/IssueCategory.php b/src/Redmine/Api/IssueCategory.php index 25a05eb9..b86f9df4 100644 --- a/src/Redmine/Api/IssueCategory.php +++ b/src/Redmine/Api/IssueCategory.php @@ -137,20 +137,15 @@ public function listing($project, $forceUpdate = false) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNamesByProject()` instead.', E_USER_DEPRECATED); - if (true === $forceUpdate || empty($this->issueCategories)) { - $this->issueCategories = $this->listByProject($project); - } - $ret = []; - foreach ($this->issueCategories['issue_categories'] as $e) { - $ret[$e['name']] = (int) $e['id']; - } - - return $ret; + return $this->doListing($project, $forceUpdate); } /** * Get a category id given its name and related project. * + * @deprecated v2.7.0 Use listNamesByProject() instead. + * @see IssueCategory::listNamesByProject() + * * @param string|int $project project id or literal identifier * @param string $name * @@ -158,7 +153,10 @@ public function listing($project, $forceUpdate = false) */ public function getIdByName($project, $name) { - $arr = $this->listing($project); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNamesByProject()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing($project, false); + if (!isset($arr[$name])) { return false; } @@ -283,4 +281,19 @@ public function remove($id, array $params = []) return $this->lastResponse->getContent(); } + + private function doListing($project, bool $forceUpdate) + { + if (true === $forceUpdate || empty($this->issueCategories)) { + $this->issueCategories = $this->listByProject($project); + } + + $ret = []; + + foreach ($this->issueCategories['issue_categories'] as $e) { + $ret[$e['name']] = (int) $e['id']; + } + + return $ret; + } } diff --git a/src/Redmine/Api/IssueStatus.php b/src/Redmine/Api/IssueStatus.php index 022b1e43..a587705c 100644 --- a/src/Redmine/Api/IssueStatus.php +++ b/src/Redmine/Api/IssueStatus.php @@ -110,31 +110,44 @@ public function listing($forceUpdate = false) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); - if (empty($this->issueStatuses) || $forceUpdate) { - $this->issueStatuses = $this->list(); - } - $ret = []; - foreach ($this->issueStatuses['issue_statuses'] as $e) { - $ret[$e['name']] = (int) $e['id']; - } - - return $ret; + return $this->doListing($forceUpdate); } /** * Get a status id given its name. * + * @deprecated v2.7.0 Use listNames() instead. + * @see IssueStatus::listNames() + * * @param string $name * * @return int|false */ public function getIdByName($name) { - $arr = $this->listing(); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false); + if (!isset($arr[$name])) { return false; } return $arr[(string) $name]; } + + private function doListing(bool $forceUpdate) + { + if (empty($this->issueStatuses) || $forceUpdate) { + $this->issueStatuses = $this->list(); + } + + $ret = []; + + foreach ($this->issueStatuses['issue_statuses'] as $e) { + $ret[$e['name']] = (int) $e['id']; + } + + return $ret; + } } diff --git a/src/Redmine/Api/Project.php b/src/Redmine/Api/Project.php index b224e067..62f83f11 100755 --- a/src/Redmine/Api/Project.php +++ b/src/Redmine/Api/Project.php @@ -132,20 +132,15 @@ public function listing($forceUpdate = false, $reverse = true, array $params = [ { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); - if (true === $forceUpdate || empty($this->projects)) { - $this->projects = $this->list($params); - } - $ret = []; - foreach ($this->projects['projects'] as $e) { - $ret[(int) $e['id']] = $e['name']; - } - - return $reverse ? array_flip($ret) : $ret; + return $this->doListing($forceUpdate, $reverse, $params); } /** * Get a project id given its name. * + * @deprecated v2.7.0 Use listNames() instead. + * @see Project::listNames() + * * @param string $name * @param array $params to allow offset/limit (and more) to be passed * @@ -153,7 +148,10 @@ public function listing($forceUpdate = false, $reverse = true, array $params = [ */ public function getIdByName($name, array $params = []) { - $arr = $this->listing(false, true, $params); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false, true, $params); + if (!isset($arr[$name])) { return false; } @@ -447,4 +445,19 @@ public function remove($id) return $this->lastResponse->getContent(); } + + private function doListing(bool $forceUpdate, bool $reverse, array $params) + { + if (true === $forceUpdate || empty($this->projects)) { + $this->projects = $this->list($params); + } + + $ret = []; + + foreach ($this->projects['projects'] as $e) { + $ret[(int) $e['id']] = $e['name']; + } + + return $reverse ? array_flip($ret) : $ret; + } } diff --git a/src/Redmine/Api/TimeEntryActivity.php b/src/Redmine/Api/TimeEntryActivity.php index 511d5e21..93ea2a35 100644 --- a/src/Redmine/Api/TimeEntryActivity.php +++ b/src/Redmine/Api/TimeEntryActivity.php @@ -105,31 +105,44 @@ public function listing($forceUpdate = false) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); - if (empty($this->timeEntryActivities) || $forceUpdate) { - $this->timeEntryActivities = $this->list(); - } - $ret = []; - foreach ($this->timeEntryActivities['time_entry_activities'] as $e) { - $ret[$e['name']] = (int) $e['id']; - } - - return $ret; + return $this->doListing((bool) $forceUpdate); } /** * Get a activities id given its name. * + * @deprecated v2.7.0 Use listNames() instead. + * @see Project::listNames() + * * @param string $name * * @return int|false */ public function getIdByName($name) { - $arr = $this->listing(); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false); + if (!isset($arr[$name])) { return false; } return $arr[(string) $name]; } + + private function doListing(bool $forceUpdate) + { + if (empty($this->timeEntryActivities) || $forceUpdate) { + $this->timeEntryActivities = $this->list(); + } + + $ret = []; + + foreach ($this->timeEntryActivities['time_entry_activities'] as $e) { + $ret[$e['name']] = (int) $e['id']; + } + + return $ret; + } } diff --git a/src/Redmine/Api/Tracker.php b/src/Redmine/Api/Tracker.php index 1babf0d3..72a46f4a 100644 --- a/src/Redmine/Api/Tracker.php +++ b/src/Redmine/Api/Tracker.php @@ -109,19 +109,14 @@ public function listing($forceUpdate = false) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); - if (empty($this->trackers) || $forceUpdate) { - $this->trackers = $this->list(); - } - $ret = []; - foreach ($this->trackers['trackers'] as $e) { - $ret[$e['name']] = (int) $e['id']; - } - - return $ret; + return $this->doListing($forceUpdate); } /** - * Get a tracket id given its name. + * Get a tracker id given its name. + * + * @deprecated v2.7.0 Use listNames() instead. + * @see Tracker::listNames() * * @param string|int $name tracker name * @@ -129,11 +124,29 @@ public function listing($forceUpdate = false) */ public function getIdByName($name) { - $arr = $this->listing(); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNames()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false); + if (!isset($arr[$name])) { return false; } return $arr[(string) $name]; } + + private function doListing(bool $forceUpdate) + { + if (empty($this->trackers) || $forceUpdate) { + $this->trackers = $this->list(); + } + + $ret = []; + + foreach ($this->trackers['trackers'] as $e) { + $ret[$e['name']] = (int) $e['id']; + } + + return $ret; + } } diff --git a/src/Redmine/Api/User.php b/src/Redmine/Api/User.php index d6d52d3f..027b7aca 100644 --- a/src/Redmine/Api/User.php +++ b/src/Redmine/Api/User.php @@ -130,17 +130,7 @@ public function listing($forceUpdate = false, array $params = []) { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listLogins()` instead.', E_USER_DEPRECATED); - if (empty($this->users) || $forceUpdate) { - $this->users = $this->list($params); - } - $ret = []; - if (is_array($this->users) && isset($this->users['users'])) { - foreach ($this->users['users'] as $e) { - $ret[$e['login']] = (int) $e['id']; - } - } - - return $ret; + return $this->doListing($forceUpdate, $params); } /** @@ -160,6 +150,9 @@ public function getCurrentUser(array $params = []) /** * Get a user id given its username. * + * @deprecated v2.7.0 Use listLogins() instead. + * @see User::listLogins() + * * @param string $username * @param array $params to allow offset/limit (and more) to be passed * @@ -167,7 +160,10 @@ public function getCurrentUser(array $params = []) */ public function getIdByUsername($username, array $params = []) { - $arr = $this->listing(false, $params); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listLogins()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing(false, $params); + if (!isset($arr[$username])) { return false; } @@ -318,4 +314,21 @@ public function remove($id) return $this->lastResponse->getContent(); } + + private function doListing(bool $forceUpdate, array $params) + { + if (empty($this->users) || $forceUpdate) { + $this->users = $this->list($params); + } + + $ret = []; + + if (is_array($this->users) && isset($this->users['users'])) { + foreach ($this->users['users'] as $e) { + $ret[$e['login']] = (int) $e['id']; + } + } + + return $ret; + } } diff --git a/src/Redmine/Api/Version.php b/src/Redmine/Api/Version.php index a7fd51ab..7d11cca2 100644 --- a/src/Redmine/Api/Version.php +++ b/src/Redmine/Api/Version.php @@ -139,20 +139,15 @@ public function listing($project, $forceUpdate = false, $reverse = true, array $ { @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNamesByProject()` instead.', E_USER_DEPRECATED); - if (true === $forceUpdate || empty($this->versions)) { - $this->versions = $this->listByProject($project, $params); - } - $ret = []; - foreach ($this->versions['versions'] as $e) { - $ret[(int) $e['id']] = $e['name']; - } - - return $reverse ? array_flip($ret) : $ret; + return $this->doListing($project, $forceUpdate, $reverse, $params); } /** * Get an version id given its name and related project. * + * @deprecated v2.7.0 Use listNamesByProject() instead. + * @see Version::listNamesByProject() + * * @param string|int $project project id or literal identifier * @param string $name The version name * @param array $params optional parameters to be passed to the api (offset, limit, ...) @@ -161,7 +156,10 @@ public function listing($project, $forceUpdate = false, $reverse = true, array $ */ public function getIdByName($project, $name, array $params = []) { - $arr = $this->listing($project, false, true, $params); + @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.7.0, use `' . __CLASS__ . '::listNamesByProject()` instead.', E_USER_DEPRECATED); + + $arr = $this->doListing($project, false, true, $params); + if (!isset($arr[$name])) { return false; } @@ -319,4 +317,19 @@ public function remove($id) return $this->lastResponse->getContent(); } + + private function doListing($project, bool $forceUpdate, bool $reverse, array $params) + { + if (true === $forceUpdate || empty($this->versions)) { + $this->versions = $this->listByProject($project, $params); + } + + $ret = []; + + foreach ($this->versions['versions'] as $e) { + $ret[(int) $e['id']] = $e['name']; + } + + return $reverse ? array_flip($ret) : $ret; + } } diff --git a/tests/Unit/Api/CustomFieldTest.php b/tests/Unit/Api/CustomFieldTest.php index e6a152a8..0e8d22cc 100644 --- a/tests/Unit/Api/CustomFieldTest.php +++ b/tests/Unit/Api/CustomFieldTest.php @@ -349,4 +349,33 @@ public function testGetIdByNameMakesGetRequest() $this->assertFalse($api->getIdByName('CustomField 1')); $this->assertSame(5, $api->getIdByName('CustomField 5')); } + + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"custom_fields":[{"id":1,"name":"CustomField 1"},{"id":5,"name":"CustomField 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new CustomField($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\CustomField::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\CustomField::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName('CustomField 5'); + } } diff --git a/tests/Unit/Api/Issue/CreateTest.php b/tests/Unit/Api/Issue/CreateTest.php index f3f2d12c..4510d2d3 100644 --- a/tests/Unit/Api/Issue/CreateTest.php +++ b/tests/Unit/Api/Issue/CreateTest.php @@ -299,7 +299,7 @@ public function testCreateWithHttpClientRetrievesProjectId() $this, [ 'GET', - '/projects.json', + '/projects.json?limit=100&offset=0', 'application/json', '', 200, @@ -410,12 +410,12 @@ public function testCreateWithHttpClientRetrievesUserId() $this, [ 'GET', - '/users.json', + '/users.json?limit=100&offset=0', 'application/json', '', 200, 'application/json', - '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}', + '{"users":[{"login":"user_5","id":5},{"login":"user_6","id":6}]}', ], [ 'POST', @@ -432,7 +432,7 @@ public function testCreateWithHttpClientRetrievesUserId() $api = new Issue($client); // Perform the tests - $xmlElement = $api->create(['assigned_to' => 'Assigned to User Name', 'author' => 'Author Name']); + $xmlElement = $api->create(['assigned_to' => 'user_6', 'author' => 'user_5']); $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement); $this->assertXmlStringEqualsXmlString( @@ -450,7 +450,7 @@ public function testCreateWithClientCleansParameters() $this, [ 'GET', - '/projects.json', + '/projects.json?limit=100&offset=0', 'application/json', '', 200, @@ -486,12 +486,12 @@ public function testCreateWithClientCleansParameters() ], [ 'GET', - '/users.json', + '/users.json?limit=100&offset=0', 'application/json', '', 200, 'application/json', - '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}', + '{"users":[{"login":"user_5","id":5},{"login":"user_6","id":6}]}', ], [ 'POST', @@ -519,8 +519,8 @@ public function testCreateWithClientCleansParameters() 'category' => 'Category Name', 'status' => 'Status Name', 'tracker' => 'Tracker Name', - 'assigned_to' => 'Assigned to User Name', - 'author' => 'Author Name', + 'assigned_to' => 'user_6', + 'author' => 'user_5', ]; // Create the object under test diff --git a/tests/Unit/Api/Issue/UpdateTest.php b/tests/Unit/Api/Issue/UpdateTest.php index ffdc446c..5a2e6da3 100644 --- a/tests/Unit/Api/Issue/UpdateTest.php +++ b/tests/Unit/Api/Issue/UpdateTest.php @@ -119,7 +119,7 @@ public function testUpdateCleansParameters() $this, [ 'GET', - '/projects.json', + '/projects.json?limit=100&offset=0', 'application/json', '', 200, @@ -155,7 +155,7 @@ public function testUpdateCleansParameters() ], [ 'GET', - '/users.json', + '/users.json?limit=100&offset=0', 'application/json', '', 200, diff --git a/tests/Unit/Api/IssueCategoryTest.php b/tests/Unit/Api/IssueCategoryTest.php index 5c011f2d..2bdbba84 100644 --- a/tests/Unit/Api/IssueCategoryTest.php +++ b/tests/Unit/Api/IssueCategoryTest.php @@ -281,4 +281,33 @@ public function testGetIdByNameMakesGetRequest() $this->assertFalse($api->getIdByName(5, 'IssueCategory 1')); $this->assertSame(5, $api->getIdByName(5, 'IssueCategory 5')); } + + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"issue_categories":[{"id":1,"name":"IssueCategory 1"},{"id":5,"name":"IssueCategory 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new IssueCategory($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\IssueCategory::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\IssueCategory::listNamesByProject()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName(5, 'Category Name'); + } } diff --git a/tests/Unit/Api/IssueStatusTest.php b/tests/Unit/Api/IssueStatusTest.php index e292ee0b..8ef04106 100644 --- a/tests/Unit/Api/IssueStatusTest.php +++ b/tests/Unit/Api/IssueStatusTest.php @@ -277,4 +277,33 @@ public function testGetIdByNameMakesGetRequest() $this->assertFalse($api->getIdByName('IssueStatus 1')); $this->assertSame(5, $api->getIdByName('IssueStatus 5')); } + + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"issue_statuses":[{"id":1,"name":"IssueStatus 1"},{"id":5,"name":"IssueStatus 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new IssueStatus($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\IssueStatus::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\IssueStatus::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName('IssueStatus 5'); + } } diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php index edce151c..b00d8c21 100644 --- a/tests/Unit/Api/IssueTest.php +++ b/tests/Unit/Api/IssueTest.php @@ -6,7 +6,15 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Redmine\Api\Issue; +use Redmine\Api\IssueCategory; +use Redmine\Api\IssueStatus; +use Redmine\Api\Project; +use Redmine\Api\Tracker; +use Redmine\Api\User; use Redmine\Client\Client; +use Redmine\Http\HttpClient; +use Redmine\Http\Response; +use Redmine\Tests\Fixtures\AssertingHttpClient; use Redmine\Tests\Fixtures\MockClient; /** @@ -141,55 +149,87 @@ public function testCreateWithClientCleansParameters() // Test values $response = ''; $parameters = [ - 'project' => 'Project Name', - 'category' => 'Category Name', - 'status' => 'Status Name', - 'tracker' => 'Tracker Name', - 'assigned_to' => 'Assigned to User Name', - 'author' => 'Author Name', + 'project' => 'Project 1 Name', + 'category' => 'Category 5 Name', + 'status' => 'Status 6 Name', + 'tracker' => 'Tracker 2 Name', + 'assigned_to' => 'user_3', + 'author' => 'user_4', ]; // Create the used mock objects - $getIdByNameApi = $this->createMock('Redmine\Api\Project'); - $getIdByNameApi->expects($this->exactly(3)) - ->method('getIdByName') - ->willReturn('cleanedValue'); - $issueCategoryGetIdByNameApi = $this->createMock('Redmine\Api\IssueCategory'); - $issueCategoryGetIdByNameApi->expects($this->exactly(1)) - ->method('getIdByName') - ->willReturn('cleanedValue'); - $getIdByUsernameApi = $this->createMock('Redmine\Api\User'); - $getIdByUsernameApi->expects($this->exactly(2)) - ->method('getIdByUsername') - ->willReturn('cleanedValue'); + $httpClient = AssertingHttpClient::create( + $this, + [ + 'GET', + '/projects.json?limit=100&offset=0', + 'application/json', + '', + 200, + 'application/json', + '{"projects":[{"id":1,"name":"Project 1 Name"},{"id":2,"name":"Project 1 Name"}]}', + ], + [ + 'GET', + '/projects/1/issue_categories.json', + 'application/json', + '', + 200, + 'application/json', + '{"issue_categories":[{"id":5,"name":"Category 5 Name"}]}', + ], + [ + 'GET', + '/issue_statuses.json', + 'application/json', + '', + 200, + 'application/json', + '{"issue_statuses":[{"id":6,"name":"Status 6 Name"}]}', + ], + [ + 'GET', + '/trackers.json', + 'application/json', + '', + 200, + 'application/json', + '{"trackers":[{"id":2,"name":"Tracker 2 Name"}]}', + ], + [ + 'GET', + '/users.json?limit=100&offset=0', + 'application/json', + '', + 200, + 'application/json', + '{"users":[{"id":3,"login":"user_3"},{"id":4,"login":"user_4"}]}', + ], + ); $client = $this->createMock(Client::class); $client->expects($this->exactly(5)) ->method('getApi') ->willReturnMap( [ - ['project', $getIdByNameApi], - ['issue_category', $issueCategoryGetIdByNameApi], - ['issue_status', $getIdByNameApi], - ['tracker', $getIdByNameApi], - ['user', $getIdByUsernameApi], + ['project', new Project($httpClient)], + ['issue_category', new IssueCategory($httpClient)], + ['issue_status', new IssueStatus($httpClient)], + ['tracker', new Tracker($httpClient)], + ['user', new User($httpClient)], ], - ); + ) + ; $client->expects($this->once()) ->method('requestPost') ->with( '/issues.xml', - $this->logicalAnd( - $this->stringStartsWith('' . "\n" . ''), - $this->stringEndsWith('' . "\n"), - $this->stringContains('cleanedValue'), - $this->stringContains('cleanedValue'), - $this->stringContains('cleanedValue'), - $this->stringContains('cleanedValue'), - $this->stringContains('cleanedValue'), - $this->stringContains('cleanedValue'), - ), + <<< XML + + 156234 + + XML, ) ->willReturn(true); $client->expects($this->exactly(1)) diff --git a/tests/Unit/Api/ProjectTest.php b/tests/Unit/Api/ProjectTest.php index cf5101b4..1c05a772 100644 --- a/tests/Unit/Api/ProjectTest.php +++ b/tests/Unit/Api/ProjectTest.php @@ -280,6 +280,35 @@ public function testGetIdByNameMakesGetRequest() $this->assertSame(5, $api->getIdByName('Project 5')); } + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"projects":[{"id":1,"name":"Project 1"},{"id":5,"name":"Project 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new Project($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\Project::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\Project::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName('Project 1'); + } + public function testDeprecatedPrepareParamsXml() { $client = $this->createMock(Client::class); diff --git a/tests/Unit/Api/TimeEntryActivityTest.php b/tests/Unit/Api/TimeEntryActivityTest.php index 841042cd..a300427c 100644 --- a/tests/Unit/Api/TimeEntryActivityTest.php +++ b/tests/Unit/Api/TimeEntryActivityTest.php @@ -221,4 +221,33 @@ public function testGetIdByNameMakesGetRequest() $this->assertFalse($api->getIdByName('TimeEntryActivities 1')); $this->assertSame(2, $api->getIdByName('TimeEntryActivities 2')); } + + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"time_entry_activities":[{"id":1,"name":"TimeEntryActivity 1"},{"id":5,"name":"TimeEntryActivity 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new TimeEntryActivity($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\TimeEntryActivity::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\TimeEntryActivity::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName('TimeEntryActivities 2'); + } } diff --git a/tests/Unit/Api/TrackerTest.php b/tests/Unit/Api/TrackerTest.php index dc46e170..5ba445b2 100644 --- a/tests/Unit/Api/TrackerTest.php +++ b/tests/Unit/Api/TrackerTest.php @@ -277,4 +277,33 @@ public function testGetIdByNameMakesGetRequest() $this->assertFalse($api->getIdByName('Tracker 1')); $this->assertSame(5, $api->getIdByName('Tracker 5')); } + + public function testGgetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"trackers":[{"id":1,"name":"Tracker 1"},{"id":5,"name":"Tracker 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new Tracker($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\Tracker::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\Tracker::listNames()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName('Tracker 5'); + } } diff --git a/tests/Unit/Api/UserTest.php b/tests/Unit/Api/UserTest.php index 3dc27123..5a327ae0 100644 --- a/tests/Unit/Api/UserTest.php +++ b/tests/Unit/Api/UserTest.php @@ -55,7 +55,7 @@ public function testGetCurrentUserReturnsClientGetResponse() public function testGetIdByUsernameMakesGetRequest() { // Test values - $response = '{"users":[{"id":5,"login":"User 5"}]}'; + $response = '{"users":[{"id":5,"login":"user_5"}]}'; // Create the used mock objects $client = $this->createMock(Client::class); @@ -79,8 +79,37 @@ public function testGetIdByUsernameMakesGetRequest() $api = new User($client); // Perform the tests - $this->assertFalse($api->getIdByUsername('User 1')); - $this->assertSame(5, $api->getIdByUsername('User 5')); + $this->assertFalse($api->getIdByUsername('user_1')); + $this->assertSame(5, $api->getIdByUsername('user_5')); + } + + public function testGetIdByUsernameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"users":[{"id":1,"login":"user_1"},{"id":5,"login":"user_5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new User($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\User::getIdByUsername()` is deprecated since v2.7.0, use `Redmine\Api\User::listLogins()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByUsername('user_5'); } /** @@ -189,10 +218,10 @@ public function testAllReturnsClientGetResponseWithParameters() public function testListingReturnsNameIdArray() { // Test values - $response = '{"users":[{"id":1,"login":"User 1"},{"id":5,"login":"User 5"}]}'; + $response = '{"users":[{"id":1,"login":"user_1"},{"id":5,"login":"user_5"}]}'; $expectedReturn = [ - 'User 1' => 1, - 'User 5' => 5, + 'user_1' => 1, + 'user_5' => 5, ]; // Create the used mock objects @@ -223,10 +252,10 @@ public function testListingReturnsNameIdArray() public function testListingCallsGetOnlyTheFirstTime() { // Test values - $response = '{"users":[{"id":1,"login":"User 1"},{"id":5,"login":"User 5"}]}'; + $response = '{"users":[{"id":1,"login":"user_1"},{"id":5,"login":"user_5"}]}'; $expectedReturn = [ - 'User 1' => 1, - 'User 5' => 5, + 'user_1' => 1, + 'user_5' => 5, ]; // Create the used mock objects @@ -258,10 +287,10 @@ public function testListingCallsGetOnlyTheFirstTime() public function testListingCallsGetEveryTimeWithForceUpdate() { // Test values - $response = '{"users":[{"id":1,"login":"User 1"},{"id":5,"login":"User 5"}]}'; + $response = '{"users":[{"id":1,"login":"user_1"},{"id":5,"login":"user_5"}]}'; $expectedReturn = [ - 'User 1' => 1, - 'User 5' => 5, + 'user_1' => 1, + 'user_5' => 5, ]; // Create the used mock objects diff --git a/tests/Unit/Api/VersionTest.php b/tests/Unit/Api/VersionTest.php index 0ed55c06..7666934e 100644 --- a/tests/Unit/Api/VersionTest.php +++ b/tests/Unit/Api/VersionTest.php @@ -309,6 +309,35 @@ public function testGetIdByNameMakesGetRequest() $this->assertSame(5, $api->getIdByName(5, 'Version 5')); } + public function testGetIdByNameTriggersDeprecationWarning() + { + $client = $this->createMock(Client::class); + $client->method('requestGet') + ->willReturn(true); + $client->method('getLastResponseBody') + ->willReturn('{"versions":[{"id":1,"name":"Version 1"},{"id":5,"name":"Version 5"}]}'); + $client->method('getLastResponseContentType') + ->willReturn('application/json'); + + $api = new Version($client); + + // PHPUnit 10 compatible way to test trigger_error(). + set_error_handler( + function ($errno, $errstr): bool { + $this->assertSame( + '`Redmine\Api\Version::getIdByName()` is deprecated since v2.7.0, use `Redmine\Api\Version::listNamesByProject()` instead.', + $errstr, + ); + + restore_error_handler(); + return true; + }, + E_USER_DEPRECATED, + ); + + $api->getIdByName(5, 'Version 5'); + } + /** * Test validateSharing(). *