1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Rules\RestrictedUsage;
4:
5: use PhpParser\Node;
6: use PhpParser\Node\Name;
7: use PHPStan\Analyser\Scope;
8: use PHPStan\DependencyInjection\AutowiredService;
9: use PHPStan\DependencyInjection\Container;
10: use PHPStan\Node\FunctionCallableNode;
11: use PHPStan\Reflection\ReflectionProvider;
12: use PHPStan\Rules\Rule;
13: use PHPStan\Rules\RuleErrorBuilder;
14:
15: /**
16: * @implements Rule<FunctionCallableNode>
17: */
18: #[AutowiredService]
19: final class RestrictedFunctionCallableUsageRule implements Rule
20: {
21:
22: public function __construct(
23: private Container $container,
24: private ReflectionProvider $reflectionProvider,
25: )
26: {
27: }
28:
29: public function getNodeType(): string
30: {
31: return FunctionCallableNode::class;
32: }
33:
34: /**
35: * @api
36: */
37: public function processNode(Node $node, Scope $scope): array
38: {
39: if (!($node->getName() instanceof Name)) {
40: return [];
41: }
42:
43: if (!$this->reflectionProvider->hasFunction($node->getName(), $scope)) {
44: return [];
45: }
46:
47: $functionReflection = $this->reflectionProvider->getFunction($node->getName(), $scope);
48:
49: /** @var RestrictedFunctionUsageExtension[] $extensions */
50: $extensions = $this->container->getServicesByTag(RestrictedFunctionUsageExtension::FUNCTION_EXTENSION_TAG);
51: $errors = [];
52:
53: foreach ($extensions as $extension) {
54: $restrictedUsage = $extension->isRestrictedFunctionUsage($functionReflection, $scope);
55: if ($restrictedUsage === null) {
56: continue;
57: }
58:
59: $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)
60: ->identifier($restrictedUsage->identifier)
61: ->build();
62: }
63:
64: return $errors;
65: }
66:
67: }
68: