Skip to content

Commit

Permalink
Merge pull request #33 from DaveLiddament/feature/restrict-trait-to
Browse files Browse the repository at this point in the history
ADD RestrictTraitTo
  • Loading branch information
DaveLiddament authored Aug 8, 2024
2 parents 39bac3d + 23fdaa4 commit 99e3149
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The intention, at least initially, is that these extra language features are enf
- [NamespaceVisibility](#namespaceVisibility)
- [InjectableVersion](#injectableVersion)
- [Override](#override)
- [RestrictTraitTo](#restricttraitto)
- [Sealed](#sealed)
- [TestTag](#testtag)

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

## RestrictTraitTo

This limits the use of a Trait to only be used by a specified class of a child of that class.

E.g. this trait is limited to classes that are or extend `Controller`

```php
#[RestrictTraitTo(Controller::class)]
trait ControllerHelpers {}
```

This would be allowed:
```php
class LoginController extends Controller {
use ControllerHelpers;
}
```

But this would NOT be allowed:
```php
class Repository {
use ControllerHelpers;
}
```


## Sealed

This is inspired by the rejected [sealed classes RFC](https://wiki.php.net/rfc/sealed_classes)
Expand Down
56 changes: 56 additions & 0 deletions examples/restrictTraitTo/restrictTraitTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace RestrictTraitTo;

use DaveLiddament\PhpLanguageExtensions\RestrictTraitTo;

trait UseAnywhere {}

#[RestrictTraitTo(Interface1::class)]
trait UseOnlyOnInterface1 {}

#[RestrictTraitTo(AbstractClass1::class)]
trait UseOnlyOnAbstractClass1 {}

#[RestrictTraitTo(Class2::class)]
trait UseOnlyOnClass2 {}


interface Interface1 {}


class AClass {
use UseAnywhere; // OK
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
}


class ImplementsInterface1 implements Interface1 {
use UseAnywhere; // OK
use UseOnlyOnInterface1; // OK
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
}

abstract class AbstractClass1
{

}

class ExtendsAbstractClass1 extends AbstractClass1 {
use UseAnywhere; // OK
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
use UseOnlyOnAbstractClass1; // OK
use UseOnlyOnClass2; // ERROR RestrictTraitTo\Class2
}

class Class2 {
use UseAnywhere; // OK
use UseOnlyOnInterface1; // ERROR RestrictTraitTo\Interface1
use UseOnlyOnAbstractClass1; // ERROR RestrictTraitTo\AbstractClass1
use UseOnlyOnClass2; // OK
}
39 changes: 39 additions & 0 deletions src/RestrictTraitTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace DaveLiddament\PhpLanguageExtensions;

/**
* Enforces that the trait can only be used on the specified class, or children of that class.
*
* E.g. this trait is limited to classes that are or extend `Controller`
*
* ```
* #[RestrictTraitTo(Controller::class)]
* trait ControllerHelpers {}
* ```
*
* This would be allowed:
* ```
* class LoginController extends Controller {
* use ControllerHelpers;
* }
* ```
*
* But this would NOT be allowed:
* ```
* class Repository {
* use ControllerHelpers;
* }
* ```
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
final class RestrictTraitTo
{
/** @param class-string $className */
public function __construct(
public string $className,
) {
}
}

0 comments on commit 99e3149

Please sign in to comment.