Skip to content

Commit 9eeaf27

Browse files
committed
Merge branch 'release/3.2.0'
2 parents c601dc9 + cd5315d commit 9eeaf27

12 files changed

Lines changed: 184 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. This projec
55

66
## Unreleased
77

8+
## [3.2.0] - 2024-04-19
9+
10+
### Added
11+
12+
- New `ApplicationException` for errors originating from the application layer.
13+
- Can now pass a closure to the `Contracts::assert()` method for the message. The closure is only invoked if the
14+
precondition fails.
15+
16+
### Fixed
17+
18+
- Make the `id` property on the `IsEntity` trait readonly. This is considered non-breaking because the `IsEntity` trait
19+
is expected to be used on an entity that always has an identifier, so the id should be set via the constructor. This
20+
fixes a bug where the trait could not be used on a readonly class.
21+
822
## [3.1.0] - 2025-02-15
923

1024
### Added
@@ -402,6 +416,8 @@ All notable changes to this project will be documented in this file. This projec
402416

403417
Initial release.
404418

419+
[3.2.0]: https://github.com/cloudcreativity/ddd-modules/compare/v3.1.0...v3.2.0
420+
405421
[3.1.0]: https://github.com/cloudcreativity/ddd-modules/compare/v3.0.0...v3.1.0
406422

407423
[3.0.0]: https://github.com/cloudcreativity/ddd-modules/compare/v3.0.0-rc.2...v3.0.0

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
"ramsey/uuid": "^4.7"
2828
},
2929
"require-dev": {
30+
"deptrac/deptrac": "^3.0",
3031
"laravel/pint": "^1.19",
3132
"phpstan/phpstan": "^2.1",
32-
"phpunit/phpunit": "^10.5",
33-
"qossmic/deptrac": "^2.0"
33+
"phpunit/phpunit": "^10.5"
3434
},
3535
"autoload": {
3636
"psr-4": {

phpstan.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ parameters:
33
paths:
44
- src
55
- tests
6+
excludePaths:
7+
- tests/Unit/Domain/TestReadOnlyEntity.php
68
treatPhpDocTypesAsCertain: false

pint.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
"elements": ["arguments", "arrays", "match", "parameters"]
77
},
88
"nullable_type_declaration": true
9-
}
10-
}
9+
},
10+
"notPath": [
11+
"tests/Unit/Domain/TestReadOnlyEntity.php"
12+
]
13+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2025 Cloud Creativity Limited
5+
*
6+
* Use of this source code is governed by an MIT-style
7+
* license that can be found in the LICENSE file or at
8+
* https://opensource.org/licenses/MIT.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace CloudCreativity\Modules\Application;
14+
15+
use RuntimeException;
16+
17+
class ApplicationException extends RuntimeException
18+
{
19+
}

src/Domain/IsEntity.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ trait IsEntity
2020
/**
2121
* @var Identifier
2222
*/
23-
private Identifier $id;
23+
private readonly Identifier $id;
2424

2525
/**
2626
* @inheritDoc

src/Toolkit/Contracts.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@
1212

1313
namespace CloudCreativity\Modules\Toolkit;
1414

15+
use Closure;
16+
1517
final class Contracts
1618
{
1719
/**
1820
* Assert that the provided precondition is true.
1921
*
2022
* @param bool $precondition
21-
* @param string $message
23+
* @param string|Closure(): string $message
2224
* @return void
2325
* @phpstan-assert true $precondition
2426
*/
25-
public static function assert(bool $precondition, string $message = ''): void
27+
public static function assert(bool $precondition, string|Closure $message = ''): void
2628
{
2729
if ($precondition === false) {
28-
throw new ContractException($message);
30+
throw new ContractException(is_string($message) ? $message : $message());
2931
}
3032
}
3133

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2025 Cloud Creativity Limited
5+
*
6+
* Use of this source code is governed by an MIT-style
7+
* license that can be found in the LICENSE file or at
8+
* https://opensource.org/licenses/MIT.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace CloudCreativity\Modules\Tests\Unit\Application;
14+
15+
use CloudCreativity\Modules\Application\ApplicationException;
16+
use PHPUnit\Framework\TestCase;
17+
use RuntimeException;
18+
19+
class ApplicationExceptionTest extends TestCase
20+
{
21+
public function test(): void
22+
{
23+
$ex = new ApplicationException();
24+
$this->assertInstanceOf(RuntimeException::class, $ex);
25+
}
26+
}

tests/Unit/Domain/EntityTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use CloudCreativity\Modules\Contracts\Domain\Entity;
1616
use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier;
1717
use CloudCreativity\Modules\Toolkit\Identifiers\Guid;
18+
use CloudCreativity\Modules\Toolkit\Identifiers\IntegerId;
1819
use PHPUnit\Framework\TestCase;
1920

2021
class EntityTest extends TestCase
@@ -97,4 +98,17 @@ public function testItIsDifferentClass(): void
9798
$this->assertFalse($a->is($b));
9899
$this->assertTrue($a->isNot($b));
99100
}
101+
102+
public function testItCanUseTraitOnReadonlyClass(): void
103+
{
104+
if (PHP_VERSION_ID < 80200) {
105+
$this->markTestSkipped('This test requires PHP 8.2 or higher.');
106+
}
107+
108+
$id = new IntegerId(123);
109+
$entity = new TestReadOnlyEntity($id, 'Bob');
110+
111+
$this->assertSame($id, $entity->getId());
112+
$this->assertSame('Bob', $entity->getName());
113+
}
100114
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2025 Cloud Creativity Limited
5+
*
6+
* Use of this source code is governed by an MIT-style
7+
* license that can be found in the LICENSE file or at
8+
* https://opensource.org/licenses/MIT.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace CloudCreativity\Modules\Tests\Unit\Domain;
14+
15+
use CloudCreativity\Modules\Contracts\Domain\Entity;
16+
use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier;
17+
use CloudCreativity\Modules\Domain\IsEntity;
18+
19+
/**
20+
* @TODO remove when dropping PHP 8.1 and update `TestEntity` to be `readonly`.
21+
*/
22+
final readonly class TestReadOnlyEntity implements Entity
23+
{
24+
use IsEntity;
25+
26+
/**
27+
* TestReadOnlyEntity constructor
28+
*
29+
* @param Identifier $id
30+
* @param string $name
31+
*/
32+
public function __construct(Identifier $id, private string $name)
33+
{
34+
$this->id = $id;
35+
}
36+
37+
/**
38+
* @return string
39+
*/
40+
public function getName(): string
41+
{
42+
return $this->name;
43+
}
44+
}

0 commit comments

Comments
 (0)