You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using the Redmine API there are some famous tasks like create an issue, add a note to an issue, list projects. Every task has other requirements and one has to check to Redmine wiki to learn about the parameter types and possibilities.
I'm working on the idea of a new client that allows an IDE to suggest the required and optional parameters for typical Redmine tasks. I would call this the high-level API.
Basics
The basic will be a minimalistic HTTP client and Request/Response interfaces described in #341 and a new Command interface.
The main task of a HttpClient is to send a request with the correct headers (authentication, content-type, impersonation) and return the response. However we have the possibility to adjust this headers using the methods startImpersonateUser(), stopImpersonateUser() and authentication with $apiKey or username/password. This allows to change the state of the client, which can lead to race conditions.
I propose to split this changeable parts into a new Configuration class, leaving the Client in an unchangeable state.
$config = Configuration::from($redmineUrl, $httpClient, $requestFactory, $streamFactory)
// using authentication is optional
->authenticate($apiKey)
->withUserImpersonation('kim')
;
// or with native curl support$config = Configuration::fromNativeCurl($redmineUrl);
// Create the client$client = $config->createClient();
// you can reuse the config to create different client instances$config->authenticateWithUsernameAndPassword($username, $password)
->withoutUserImpersonation()
;
$clientWithoutImpersonation = $config->createClient();
This allows us to add new features in Configuration without changing the API of the Client.
$client = Configuration::from($redmineUrl, $httpClient, $requestFactory, $streamFactory)
->authenticate($apiKey)
// possible feature: set the redmine version
->withRedmineVersion('5.0.0')
// possible feature: set a PSR-6 cache pool
->withCache($cachePool)
->createClient()
;
Command concepts
The created client implements the HttpClient interface, but also have the mid-level API getApi() method. Additionally we could add methods for typical tasks, that returns a Command implementation like CreateProjectCommand. This CreateProjectCommand class requires all required parameter and allows to set optional parameters.
Adding custom fields might become straight forward.
$client->createGroup($groupName)
->withCustomField($fieldId, $value)
// or by field name; requires a front up request to list all custom fields
->withCustomFieldByName($fieldName, $value)
->execute();
The Command implementation could also have a switch to use the XML or JSON endpoint, to address #146.
$client->updateIssue($issueId)
->withNote('add this text as note in the issue')
->useXmlEndpoint()
// ->useJsonEndpoint()
->execute();
Return data
Every Command will declares a execute(): Response method, but could also declare more methods like asArray().
Other data formats would be an implementation detail and will not need an interface.
finalclass ListUsersCommand implements Command
{
// [...] other implementation details not shown/** * @return array<int,string> list of users (id => 'username') */publicfunctiongetAsListing(): array
{
return$this->responseToListingArray($this->execute());
}
}
We have to make sure that calling execute() would not rerun a request, but only return an already cached response.
Forward compatibility
If a new Redmine version adds new parameter the commands should have generic methods like ->with() or ->filter() to add such parameters without the need to update this library.
I might became suitable to let the user define the Redmine version of the server to provide more information about available features or deprecations.
$client = $config->setRedmineVersion('3.0.0')->createClient();
$client->listMyAccountData()->execute();
// should throw Exception with message "endpoint `/my/account.json` requires Redmine 4.1.0 and is not supported on Redmine 3.0.0."
Example code
This code shows examples how the new Configuration and Client would look like if used by the users:
Art4
changed the title
Create new CommandClient (High-level API)
[Idea] Create new CommandClient (High-level API)
Jan 5, 2024
Art4
changed the title
[Idea] Create new CommandClient (High-level API)
[Idea] New CommandClient (High-level API), split Client and Configuration
Jan 31, 2024
Using the Redmine API there are some famous tasks like create an issue, add a note to an issue, list projects. Every task has other requirements and one has to check to Redmine wiki to learn about the parameter types and possibilities.
I'm working on the idea of a new client that allows an IDE to suggest the required and optional parameters for typical Redmine tasks. I would call this the high-level API.
Basics
The basic will be a minimalistic HTTP client and Request/Response interfaces described in #341 and a new
Command
interface.Create Client from Configuration
The main task of a
HttpClient
is to send a request with the correct headers (authentication, content-type, impersonation) and return the response. However we have the possibility to adjust this headers using the methodsstartImpersonateUser()
,stopImpersonateUser()
and authentication with$apiKey
or username/password. This allows to change the state of the client, which can lead to race conditions.I propose to split this changeable parts into a new
Configuration
class, leaving the Client in an unchangeable state.This allows us to add new features in Configuration without changing the API of the Client.
Command concepts
The created client implements the
HttpClient
interface, but also have the mid-level APIgetApi()
method. Additionally we could add methods for typical tasks, that returns aCommand
implementation likeCreateProjectCommand
. ThisCreateProjectCommand
class requires all required parameter and allows to set optional parameters.The
Command
implementation could also be created independent from aHttpClient
but requires it in the factory method.Adding custom fields might become straight forward.
The
Command
implementation could also have a switch to use the XML or JSON endpoint, to address #146.Return data
Every
Command
will declares aexecute(): Response
method, but could also declare more methods likeasArray()
.Other data formats would be an implementation detail and will not need an interface.
We have to make sure that calling
execute()
would not rerun a request, but only return an already cached response.Forward compatibility
If a new Redmine version adds new parameter the commands should have generic methods like
->with()
or->filter()
to add such parameters without the need to update this library.The new filter and parameters could then be implemented later as methods.
I might became suitable to let the user define the Redmine version of the server to provide more information about available features or deprecations.
Example code
This code shows examples how the new Configuration and Client would look like if used by the users:
The text was updated successfully, but these errors were encountered: