Skip to content

Commit 99e3149

Browse files
Merge pull request #33 from DaveLiddament/feature/restrict-trait-to
ADD RestrictTraitTo
2 parents 39bac3d + 23fdaa4 commit 99e3149

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The intention, at least initially, is that these extra language features are enf
1919
- [NamespaceVisibility](#namespaceVisibility)
2020
- [InjectableVersion](#injectableVersion)
2121
- [Override](#override)
22+
- [RestrictTraitTo](#restricttraitto)
2223
- [Sealed](#sealed)
2324
- [TestTag](#testtag)
2425

@@ -34,6 +35,7 @@ The intention, at least initially, is that these extra language features are enf
3435
- [NamespaceVisibility](#namespaceVisibility)
3536
- [InjectableVersion](#injectableVersion)
3637
- [Override](#override)
38+
- [RestrictTraitTo](#restricttraitto)
3739
- [Sealed](#sealed)
3840
- [TestTag](#testtag)
3941
- Deprecated
@@ -417,6 +419,32 @@ NOTE:
417419
- If you are using PHP 8.3 then use the real `#[Override]` attribute.
418420
- This implementation doesn't consider traits.
419421

422+
## RestrictTraitTo
423+
424+
This limits the use of a Trait to only be used by a specified class of a child of that class.
425+
426+
E.g. this trait is limited to classes that are or extend `Controller`
427+
428+
```php
429+
#[RestrictTraitTo(Controller::class)]
430+
trait ControllerHelpers {}
431+
```
432+
433+
This would be allowed:
434+
```php
435+
class LoginController extends Controller {
436+
use ControllerHelpers;
437+
}
438+
```
439+
440+
But this would NOT be allowed:
441+
```php
442+
class Repository {
443+
use ControllerHelpers;
444+
}
445+
```
446+
447+
420448
## Sealed
421449

422450
This is inspired by the rejected [sealed classes RFC](https://wiki.php.net/rfc/sealed_classes)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RestrictTraitTo;
6+
7+
use DaveLiddament\PhpLanguageExtensions\RestrictTraitTo;
8+
9+
trait UseAnywhere {}
10+
11+
#[RestrictTraitTo(Interface1::class)]
12+
trait UseOnlyOnInterface1 {}
13+
14+
#[RestrictTraitTo(AbstractClass1::class)]
15+
trait UseOnlyOnAbstractClass1 {}
16+
17+
#[RestrictTraitTo(Class2::class)]
18+
trait UseOnlyOnClass2 {}
19+
20+
21+
interface Interface1 {}
22+
23+
24+
class AClass {
25+
use UseAnywhere; // OK
26+
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
27+
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
28+
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
29+
}
30+
31+
32+
class ImplementsInterface1 implements Interface1 {
33+
use UseAnywhere; // OK
34+
use UseOnlyOnInterface1; // OK
35+
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
36+
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
37+
}
38+
39+
abstract class AbstractClass1
40+
{
41+
42+
}
43+
44+
class ExtendsAbstractClass1 extends AbstractClass1 {
45+
use UseAnywhere; // OK
46+
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
47+
use UseOnlyOnAbstractClass1; // OK
48+
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
49+
}
50+
51+
class Class2 {
52+
use UseAnywhere; // OK
53+
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
54+
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
55+
use UseOnlyOnClass2; // OK
56+
}

src/RestrictTraitTo.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpLanguageExtensions;
6+
7+
/**
8+
* Enforces that the trait can only be used on the specified class, or children of that class.
9+
*
10+
* E.g. this trait is limited to classes that are or extend `Controller`
11+
*
12+
* ```
13+
* #[RestrictTraitTo(Controller::class)]
14+
* trait ControllerHelpers {}
15+
* ```
16+
*
17+
* This would be allowed:
18+
* ```
19+
* class LoginController extends Controller {
20+
* use ControllerHelpers;
21+
* }
22+
* ```
23+
*
24+
* But this would NOT be allowed:
25+
* ```
26+
* class Repository {
27+
* use ControllerHelpers;
28+
* }
29+
* ```
30+
*/
31+
#[\Attribute(\Attribute::TARGET_CLASS)]
32+
final class RestrictTraitTo
33+
{
34+
/** @param class-string $className */
35+
public function __construct(
36+
public string $className,
37+
) {
38+
}
39+
}

0 commit comments

Comments
 (0)