Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allowInMethodsWithAttributes does not work on method parameters #314

Closed
ruudk opened this issue Feb 26, 2025 · 4 comments · Fixed by #315
Closed

allowInMethodsWithAttributes does not work on method parameters #314

ruudk opened this issue Feb 26, 2025 · 4 comments · Fixed by #315

Comments

@ruudk
Copy link
Contributor

ruudk commented Feb 26, 2025

I noticed an issue.

return [
    'parameters' => [
        'disallowedClasses' => [
            [
                'allowInUse' => true,
                'class' => 'EventRecorder',
                'errorTip' => 'Only allowed in command handlers. Inject the EventBus in subscribers.',
                'allowInMethodsWithAttributes' => [
                    AsCommandHandler::class,
                ]
            ],
        ],
    ],
];
final readonly class SomeHandler
{
    #[AsCommandHandler]
    public function __invoke(SomeCommand $command, Actor $actor, EventRecorder $eventRecorder) : void // error
    {
        $eventRecorder = new EventRecorder(); // allowed
    }
}
Class EventRecorder is forbidden.
💡 Only allowed in command handlers. Inject the EventBus in subscribers.
🔖 disallowed.class
↳ src/SomeHandler.php:4

So within the class it works, but not on the signature. That should be considered "within the method" to me?

@spaze
Copy link
Owner

spaze commented Feb 27, 2025

Huh, I guess this should be supported, let me check why it's not the case.

spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
spaze added a commit that referenced this issue Mar 2, 2025
When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
@spaze
Copy link
Owner

spaze commented Mar 2, 2025

Hey @ruudk, I think I have added the support for "classes in signature are within the method", but would like to ask you for help verifying the "fix". It is sort of a not straightforward fix because it seems that PHPStan is missing a way to get a method reflection from the namespace node in the signature, or at least I can't find it, so I had to emulate it.

Would you please try and run the code from #315 and see 1) it works as expected, 2) it doesn't break anything?

@ruudk
Copy link
Contributor Author

ruudk commented Mar 3, 2025

Just tested it out and it works as expected! 🎉 Thanks!

@spaze spaze closed this as completed in #315 Mar 3, 2025
spaze added a commit that referenced this issue Mar 3, 2025
…315)

When a disallowed classname is detected in method or function params, and it is allowed by method/function attributes, this change will allow to get the method/func attributes. It's way hacky as it seems to be not possible natively in PHPStan because `$scope->getFunction()` returns null for `FullyQualified` nodes in method/func parameter types. So we store the method name in `ClassMethod` rule, use it in `Allowed` service when set, and unset the function name in `InClassMethodNode` which is a virtual node which marks the beginning of the method body. Similar for functions in `Function_` and `InFunctionBody`.

Close #314
@spaze
Copy link
Owner

spaze commented Mar 3, 2025

Thanks for testing! I've now released the fix in 4.4.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants