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