Skip to content

Commit 7c4e70c

Browse files
authored
Merge pull request #458 from kbsali/create-named-constructors-in-api
Create factory methods in all API classes
2 parents 63b0368 + 4513b5d commit 7c4e70c

151 files changed

Lines changed: 4482 additions & 2417 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

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

1010
### Added
1111

12+
- New method `Redmine\Api\Attachment::fromHttpClient()` for creating the class.
13+
- New method `Redmine\Api\CustomField::fromHttpClient()` for creating the class.
14+
- New method `Redmine\Api\Group::fromHttpClient()` for creating the class.
15+
- New method `Redmine\Api\Issue::fromHttpClient()` for creating the class.
16+
- New method `Redmine\Api\IssueCategory::fromHttpClient()` for creating the class.
17+
- New method `Redmine\Api\IssuePriority::fromHttpClient()` for creating the class.
18+
- New method `Redmine\Api\IssueRelation::fromHttpClient()` for creating the class.
19+
- New method `Redmine\Api\IssueStatus::fromHttpClient()` for creating the class.
20+
- New method `Redmine\Api\Membership::fromHttpClient()` for creating the class.
21+
- New method `Redmine\Api\News::fromHttpClient()` for creating the class.
22+
- New method `Redmine\Api\Project::fromHttpClient()` for creating the class.
23+
- New method `Redmine\Api\Query::fromHttpClient()` for creating the class.
24+
- New method `Redmine\Api\Role::fromHttpClient()` for creating the class.
25+
- New method `Redmine\Api\Search::fromHttpClient()` for creating the class.
26+
- New method `Redmine\Api\TimeEntry::fromHttpClient()` for creating the class.
27+
- New method `Redmine\Api\TimeEntryActivity::fromHttpClient()` for creating the class.
28+
- New method `Redmine\Api\Tracker::fromHttpClient()` for creating the class.
29+
- New method `Redmine\Api\User::fromHttpClient()` for creating the class.
30+
- New method `Redmine\Api\Version::fromHttpClient()` for creating the class.
31+
- New method `Redmine\Api\Wiki::fromHttpClient()` for creating the class.
1232
- Add support for PHP 8.5
1333
- Add support for Redmine 6.1.
1434

1535
### Changed
1636

1737
- Behaviour-driven tests are run against Redmine 6.1.0, 6.0.7, 5.1.10.
1838

39+
### Deprecated
40+
41+
- `Redmine\Api\Attachment::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Attachment::fromHttpClient()` instead.
42+
- Extending `Redmine\Api\Attachment` is deprecated and will be set to final in future, create a wrapper class instead.
43+
- `Redmine\Api\CustomField::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\CustomField::fromHttpClient()` instead.
44+
- Extending `Redmine\Api\CustomField` is deprecated and will be set to final in future, create a wrapper class instead.
45+
- `Redmine\Api\Group::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Group::fromHttpClient()` instead.
46+
- Extending `Redmine\Api\Group` is deprecated and will be set to final in future, create a wrapper class instead.
47+
- `Redmine\Api\Issue::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Issue::fromHttpClient()` instead.
48+
- Extending `Redmine\Api\Issue` is deprecated and will be set to final in future, create a wrapper class instead.
49+
- `Redmine\Api\IssueCategory::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\IssueCategory::fromHttpClient()` instead.
50+
- Extending `Redmine\Api\IssueCategory` is deprecated and will be set to final in future, create a wrapper class instead.
51+
- `Redmine\Api\IssuePriority::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\IssuePriority::fromHttpClient()` instead.
52+
- Extending `Redmine\Api\IssuePriority` is deprecated and will be set to final in future, create a wrapper class instead.
53+
- `Redmine\Api\IssueRelation::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\IssueRelation::fromHttpClient()` instead.
54+
- Extending `Redmine\Api\IssueRelation` is deprecated and will be set to final in future, create a wrapper class instead.
55+
- `Redmine\Api\IssueStatus::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\IssueStatus::fromHttpClient()` instead.
56+
- Extending `Redmine\Api\IssueStatus` is deprecated and will be set to final in future, create a wrapper class instead.
57+
- `Redmine\Api\Membership::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Membership::fromHttpClient()` instead.
58+
- Extending `Redmine\Api\Membership` is deprecated and will be set to final in future, create a wrapper class instead.
59+
- `Redmine\Api\News::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\News::fromHttpClient()` instead.
60+
- Extending `Redmine\Api\News` is deprecated and will be set to final in future, create a wrapper class instead.
61+
- `Redmine\Api\Project::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Project::fromHttpClient()` instead.
62+
- Extending `Redmine\Api\Project` is deprecated and will be set to final in future, create a wrapper class instead.
63+
- `Redmine\Api\Query::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Query::fromHttpClient()` instead.
64+
- Extending `Redmine\Api\Query` is deprecated and will be set to final in future, create a wrapper class instead.
65+
- `Redmine\Api\Role::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Role::fromHttpClient()` instead.
66+
- Extending `Redmine\Api\Role` is deprecated and will be set to final in future, create a wrapper class instead.
67+
- `Redmine\Api\Search::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Search::fromHttpClient()` instead.
68+
- Extending `Redmine\Api\Search` is deprecated and will be set to final in future, create a wrapper class instead.
69+
- `Redmine\TimeEntry::__construct()` is deprecated and will be set to private in future, use `\Redmine\TimeEntry::fromHttpClient()` instead.
70+
- Extending `Redmine\TimeEntry` is deprecated and will be set to final in future, create a wrapper class instead.
71+
- `Redmine\Api\TimeEntryActivity::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\TimeEntryActivity::fromHttpClient()` instead.
72+
- Extending `Redmine\Api\TimeEntryActivity` is deprecated and will be set to final in future, create a wrapper class instead.
73+
- `Redmine\Api\Tracker::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Tracker::fromHttpClient()` instead.
74+
- Extending `Redmine\Api\Tracker` is deprecated and will be set to final in future, create a wrapper class instead.
75+
- `Redmine\Api\User::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\User::fromHttpClient()` instead.
76+
- Extending `Redmine\Api\User` is deprecated and will be set to final in future, create a wrapper class instead.
77+
- `Redmine\Api\Version::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Version::fromHttpClient()` instead.
78+
- Extending `Redmine\Api\Version` is deprecated and will be set to final in future, create a wrapper class instead.
79+
- `Redmine\Api\Wiki::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Wiki::fromHttpClient()` instead.
80+
- Extending `Redmine\Api\Wiki` is deprecated and will be set to final in future, create a wrapper class instead.
81+
1982
### Removed
2083

2184
- Drop support for Redmine 5.0.x.

composer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
"coverage": "phpunit -c tests/phpunit-coverage.xml.dist --coverage-html=\".phpunit.cache/code-coverage\"",
6565
"phpstan": "phpstan analyze --memory-limit 512M --configuration .phpstan.neon",
6666
"phpunit": "phpunit -c phpunit.xml.dist",
67+
"rectify": [
68+
"@rector",
69+
"@codestyle"
70+
],
6771
"rector": "rector -c .rector.php",
6872
"test": [
6973
"@phpstan",

src/Redmine/Api/Attachment.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Redmine\Api;
44

5+
use Redmine\Client\Client;
56
use Redmine\Exception\SerializerException;
67
use Redmine\Exception\UnexpectedResponseException;
8+
use Redmine\Http\HttpClient;
79
use Redmine\Http\HttpFactory;
810
use Redmine\Serializer\JsonSerializer;
911
use Redmine\Serializer\PathSerializer;
@@ -17,6 +19,37 @@
1719
*/
1820
class Attachment extends AbstractApi
1921
{
22+
final public static function fromHttpClient(HttpClient $httpClient): self
23+
{
24+
return new self($httpClient, true);
25+
}
26+
27+
/**
28+
* @deprecated v2.9.0 Use fromHttpClient() instead.
29+
* @see Attachment::fromHttpClient()
30+
*
31+
* @param Client|HttpClient $client
32+
*/
33+
public function __construct($client/*, bool $privatelyCalled = false*/)
34+
{
35+
$privatelyCalled = (func_num_args() > 1) ? func_get_arg(1) : false;
36+
37+
if ($privatelyCalled === true) {
38+
parent::__construct($client);
39+
40+
return;
41+
}
42+
43+
if (static::class !== self::class) {
44+
$className = (new \ReflectionClass($this))->isAnonymous() ? '' : ' in `' . static::class . '`';
45+
@trigger_error('Class `' . self::class . '` will declared as final in v3.0.0, stop extending it' . $className . '.', E_USER_DEPRECATED);
46+
} else {
47+
@trigger_error('Method `' . __METHOD__ . '()` is deprecated since v2.9.0 and will declared as private in v3.0.0, use `' . self::class . '::fromHttpClient()` instead.', E_USER_DEPRECATED);
48+
}
49+
50+
parent::__construct($client);
51+
}
52+
2053
/**
2154
* Get extended information about an attachment.
2255
*

src/Redmine/Api/CustomField.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
namespace Redmine\Api;
44

5+
use Redmine\Client\Client;
56
use Redmine\Exception;
67
use Redmine\Exception\SerializerException;
78
use Redmine\Exception\UnexpectedResponseException;
9+
use Redmine\Http\HttpClient;
810

911
/**
1012
* Listing custom fields.
@@ -15,6 +17,11 @@
1517
*/
1618
class CustomField extends AbstractApi
1719
{
20+
final public static function fromHttpClient(HttpClient $httpClient): self
21+
{
22+
return new self($httpClient, true);
23+
}
24+
1825
/**
1926
* @var null|array<mixed>
2027
*/
@@ -25,6 +32,32 @@ class CustomField extends AbstractApi
2532
*/
2633
private ?array $customFieldNames = null;
2734

35+
/**
36+
* @deprecated v2.9.0 Use fromHttpClient() instead.
37+
* @see CustomField::fromHttpClient()
38+
*
39+
* @param Client|HttpClient $client
40+
*/
41+
public function __construct($client/*, bool $privatelyCalled = false*/)
42+
{
43+
$privatelyCalled = (func_num_args() > 1) ? func_get_arg(1) : false;
44+
45+
if ($privatelyCalled === true) {
46+
parent::__construct($client);
47+
48+
return;
49+
}
50+
51+
if (static::class !== self::class) {
52+
$className = (new \ReflectionClass($this))->isAnonymous() ? '' : ' in `' . static::class . '`';
53+
@trigger_error('Class `' . self::class . '` will declared as final in v3.0.0, stop extending it' . $className . '.', E_USER_DEPRECATED);
54+
} else {
55+
@trigger_error('Method `' . __METHOD__ . '()` is deprecated since v2.9.0 and will declared as private in v3.0.0, use `' . self::class . '::fromHttpClient()` instead.', E_USER_DEPRECATED);
56+
}
57+
58+
parent::__construct($client);
59+
}
60+
2861
/**
2962
* List custom fields.
3063
*

src/Redmine/Api/Group.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Redmine\Api;
44

5+
use Redmine\Client\Client;
56
use Redmine\Exception;
67
use Redmine\Exception\MissingParameterException;
78
use Redmine\Exception\SerializerException;
89
use Redmine\Exception\UnexpectedResponseException;
10+
use Redmine\Http\HttpClient;
911
use Redmine\Http\HttpFactory;
1012
use Redmine\Serializer\JsonSerializer;
1113
use Redmine\Serializer\PathSerializer;
@@ -21,6 +23,11 @@
2123
*/
2224
class Group extends AbstractApi
2325
{
26+
final public static function fromHttpClient(HttpClient $httpClient): self
27+
{
28+
return new self($httpClient, true);
29+
}
30+
2431
/**
2532
* @var null|array<mixed>
2633
*/
@@ -31,6 +38,32 @@ class Group extends AbstractApi
3138
*/
3239
private ?array $groupNames = null;
3340

41+
/**
42+
* @deprecated v2.9.0 Use fromHttpClient() instead.
43+
* @see Group::fromHttpClient()
44+
*
45+
* @param Client|HttpClient $client
46+
*/
47+
public function __construct($client/*, bool $privatelyCalled = false*/)
48+
{
49+
$privatelyCalled = (func_num_args() > 1) ? func_get_arg(1) : false;
50+
51+
if ($privatelyCalled === true) {
52+
parent::__construct($client);
53+
54+
return;
55+
}
56+
57+
if (static::class !== self::class) {
58+
$className = (new \ReflectionClass($this))->isAnonymous() ? '' : ' in `' . static::class . '`';
59+
@trigger_error('Class `' . self::class . '` will declared as final in v3.0.0, stop extending it' . $className . '.', E_USER_DEPRECATED);
60+
} else {
61+
@trigger_error('Method `' . __METHOD__ . '()` is deprecated since v2.9.0 and will declared as private in v3.0.0, use `' . self::class . '::fromHttpClient()` instead.', E_USER_DEPRECATED);
62+
}
63+
64+
parent::__construct($client);
65+
}
66+
3467
/**
3568
* List groups.
3669
*

src/Redmine/Api/Issue.php

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
namespace Redmine\Api;
44

5+
use Redmine\Client\Client;
56
use Redmine\Client\NativeCurlClient;
67
use Redmine\Client\Psr18Client;
78
use Redmine\Exception;
89
use Redmine\Exception\SerializerException;
910
use Redmine\Exception\UnexpectedResponseException;
11+
use Redmine\Http\HttpClient;
1012
use Redmine\Http\HttpFactory;
1113
use Redmine\Serializer\JsonSerializer;
1214
use Redmine\Serializer\PathSerializer;
@@ -47,6 +49,11 @@ class Issue extends AbstractApi
4749
*/
4850
public const PRIO_IMMEDIATE = 5;
4951

52+
final public static function fromHttpClient(HttpClient $httpClient): self
53+
{
54+
return new self($httpClient, true);
55+
}
56+
5057
/**
5158
* @var null|IssueCategory
5259
*/
@@ -72,6 +79,32 @@ class Issue extends AbstractApi
7279
*/
7380
private $userApi = null;
7481

82+
/**
83+
* @deprecated v2.9.0 Use fromHttpClient() instead.
84+
* @see Issue::fromHttpClient()
85+
*
86+
* @param Client|HttpClient $client
87+
*/
88+
public function __construct($client/*, bool $privatelyCalled = false*/)
89+
{
90+
$privatelyCalled = (func_num_args() > 1) ? func_get_arg(1) : false;
91+
92+
if ($privatelyCalled === true) {
93+
parent::__construct($client);
94+
95+
return;
96+
}
97+
98+
if (static::class !== self::class) {
99+
$className = (new \ReflectionClass($this))->isAnonymous() ? '' : ' in `' . static::class . '`';
100+
@trigger_error('Class `' . self::class . '` will declared as final in v3.0.0, stop extending it' . $className . '.', E_USER_DEPRECATED);
101+
} else {
102+
@trigger_error('Method `' . __METHOD__ . '()` is deprecated since v2.9.0 and will declared as private in v3.0.0, use `' . self::class . '::fromHttpClient()` instead.', E_USER_DEPRECATED);
103+
}
104+
105+
parent::__construct($client);
106+
}
107+
75108
/**
76109
* List issues.
77110
*
@@ -489,7 +522,7 @@ private function getIssueCategoryApi()
489522
/** @var IssueCategory */
490523
$issueCategoryApi = $this->client->getApi('issue_category');
491524
} else {
492-
$issueCategoryApi = new IssueCategory($this->getHttpClient());
525+
$issueCategoryApi = IssueCategory::fromHttpClient($this->getHttpClient());
493526
}
494527

495528
$this->issueCategoryApi = $issueCategoryApi;
@@ -508,7 +541,7 @@ private function getIssueStatusApi()
508541
/** @var IssueStatus */
509542
$issueStatusApi = $this->client->getApi('issue_status');
510543
} else {
511-
$issueStatusApi = new IssueStatus($this->getHttpClient());
544+
$issueStatusApi = IssueStatus::fromHttpClient($this->getHttpClient());
512545
}
513546

514547
$this->issueStatusApi = $issueStatusApi;
@@ -527,7 +560,7 @@ private function getProjectApi()
527560
/** @var Project */
528561
$projectApi = $this->client->getApi('project');
529562
} else {
530-
$projectApi = new Project($this->getHttpClient());
563+
$projectApi = Project::fromHttpClient($this->getHttpClient());
531564
}
532565

533566
$this->projectApi = $projectApi;
@@ -546,7 +579,7 @@ private function getTrackerApi()
546579
/** @var Tracker */
547580
$trackerApi = $this->client->getApi('tracker');
548581
} else {
549-
$trackerApi = new Tracker($this->getHttpClient());
582+
$trackerApi = Tracker::fromHttpClient($this->getHttpClient());
550583
}
551584

552585
$this->trackerApi = $trackerApi;
@@ -565,7 +598,7 @@ private function getUserApi()
565598
/** @var User */
566599
$userApi = $this->client->getApi('user');
567600
} else {
568-
$userApi = new User($this->getHttpClient());
601+
$userApi = User::fromHttpClient($this->getHttpClient());
569602
}
570603

571604
$this->userApi = $userApi;

0 commit comments

Comments
 (0)