Skip to content

Commit 66d88be

Browse files
committed
feat: create News::fromHttpClient()
1 parent ae15675 commit 66d88be

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- New method `Redmine\Api\IssueStatus::fromHttpClient()` for creating the class.
2020
- New method `Redmine\Api\Membership::fromHttpClient()` for creating the class.
2121
- New method `Redmine\Api\News::fromHttpClient()` for creating the class.
22+
- New method `Redmine\Api\Project::fromHttpClient()` for creating the class.
2223
- Add support for PHP 8.5
2324
- Add support for Redmine 6.1.
2425

@@ -48,6 +49,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4849
- Extending `Redmine\Api\Membership` is deprecated and will be set to final in future, create a wrapper class instead.
4950
- `Redmine\Api\News::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\News::fromHttpClient()` instead.
5051
- Extending `Redmine\Api\News` is deprecated and will be set to final in future, create a wrapper class instead.
52+
- `Redmine\Api\Project::__construct()` is deprecated and will be set to private in future, use `\Redmine\Api\Project::fromHttpClient()` instead.
53+
- Extending `Redmine\Api\Project` is deprecated and will be set to final in future, create a wrapper class instead.
5154

5255
### Removed
5356

src/Redmine/Api/Project.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
namespace Redmine\Api;
44

55
use InvalidArgumentException;
6+
use Redmine\Client\Client;
67
use Redmine\Exception;
78
use Redmine\Exception\MissingParameterException;
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;
@@ -22,6 +24,11 @@
2224
*/
2325
class Project extends AbstractApi
2426
{
27+
final public static function fromHttpClient(HttpClient $httpClient): self
28+
{
29+
return new self($httpClient, true);
30+
}
31+
2532
/**
2633
* @var null|array<mixed>
2734
*/
@@ -32,6 +39,32 @@ class Project extends AbstractApi
3239
*/
3340
private ?array $projectNames = null;
3441

42+
/**
43+
* @deprecated v2.9.0 Use fromHttpClient() instead.
44+
* @see Project::fromHttpClient()
45+
*
46+
* @param Client|HttpClient $client
47+
*/
48+
public function __construct($client/*, bool $privatelyCalled = false*/)
49+
{
50+
$privatelyCalled = (func_num_args() > 1) ? func_get_arg(1) : false;
51+
52+
if ($privatelyCalled === true) {
53+
parent::__construct($client);
54+
55+
return;
56+
}
57+
58+
if (static::class !== self::class) {
59+
$className = (new \ReflectionClass($this))->isAnonymous() ? '' : ' in `' . static::class . '`';
60+
@trigger_error('Class `' . self::class . '` will declared as final in v3.0.0, stop extending it' . $className . '.', E_USER_DEPRECATED);
61+
} else {
62+
@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);
63+
}
64+
65+
parent::__construct($client);
66+
}
67+
3568
/**
3669
* List projects.
3770
*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Redmine\Tests\Unit\Api\Project;
4+
5+
use PHPUnit\Framework\Attributes\CoversClass;
6+
use PHPUnit\Framework\TestCase;
7+
use Redmine\Api\Project;
8+
use Redmine\Http\HttpClient;
9+
10+
#[CoversClass(Project::class)]
11+
class FromHttpClientTest extends TestCase
12+
{
13+
public function testReturnsCorrectObject(): void
14+
{
15+
$httpClient = $this->createStub(HttpClient::class);
16+
17+
$api = Project::fromHttpClient($httpClient);
18+
19+
$this->assertInstanceOf(Project::class, $api);
20+
}
21+
}

tests/Unit/Api/ProjectTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPUnit\Framework\TestCase;
88
use Redmine\Api\Project;
99
use Redmine\Client\Client;
10+
use Redmine\Http\HttpClient;
1011
use Redmine\Tests\Fixtures\MockClient;
1112
use ReflectionMethod;
1213
use SimpleXMLElement;
@@ -17,6 +18,44 @@
1718
#[CoversClass(Project::class)]
1819
class ProjectTest extends TestCase
1920
{
21+
public function testExtendingTheClassTriggersDeprecationWarning(): void
22+
{
23+
// PHPUnit 10 compatible way to test trigger_error().
24+
set_error_handler(
25+
function ($errno, $errstr): bool {
26+
$this->assertSame(
27+
'Class `Redmine\Api\Project` will declared as final in v3.0.0, stop extending it.',
28+
$errstr,
29+
);
30+
31+
restore_error_handler();
32+
return true;
33+
},
34+
E_USER_DEPRECATED,
35+
);
36+
37+
new class ($this->createStub(HttpClient::class)) extends Project {};
38+
}
39+
40+
public function testConstructorTriggersDeprecationWarning(): void
41+
{
42+
// PHPUnit 10 compatible way to test trigger_error().
43+
set_error_handler(
44+
function ($errno, $errstr): bool {
45+
$this->assertSame(
46+
'Method `Redmine\Api\Project::__construct()` is deprecated since v2.9.0 and will declared as private in v3.0.0, use `Redmine\Api\Project::fromHttpClient()` instead.',
47+
$errstr,
48+
);
49+
50+
restore_error_handler();
51+
return true;
52+
},
53+
E_USER_DEPRECATED,
54+
);
55+
56+
new Project($this->createStub(HttpClient::class));
57+
}
58+
2059
/**
2160
* Test all().
2261
*/

0 commit comments

Comments
 (0)