Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace DI\Definition\Resolver;
6
 
7
use DI\Definition\Definition;
8
use DI\Definition\Exception\InvalidDefinition;
9
use DI\Definition\ObjectDefinition\MethodInjection;
10
use ReflectionMethod;
11
use ReflectionParameter;
12
 
13
/**
14
 * Resolves parameters for a function call.
15
 *
16
 * @since  4.2
17
 * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
 */
19
class ParameterResolver
20
{
21
    /**
22
     * @param DefinitionResolver $definitionResolver Will be used to resolve nested definitions.
23
     */
24
    public function __construct(
25
        private DefinitionResolver $definitionResolver,
26
    ) {
27
    }
28
 
29
    /**
30
     * @return array Parameters to use to call the function.
31
     * @throws InvalidDefinition A parameter has no value defined or guessable.
32
     */
33
    public function resolveParameters(
34
        MethodInjection $definition = null,
35
        ReflectionMethod $method = null,
36
        array $parameters = [],
37
    ) : array {
38
        $args = [];
39
 
40
        if (! $method) {
41
            return $args;
42
        }
43
 
44
        $definitionParameters = $definition ? $definition->getParameters() : [];
45
 
46
        foreach ($method->getParameters() as $index => $parameter) {
47
            if (array_key_exists($parameter->getName(), $parameters)) {
48
                // Look in the $parameters array
49
                $value = &$parameters[$parameter->getName()];
50
            } elseif (array_key_exists($index, $definitionParameters)) {
51
                // Look in the definition
52
                $value = &$definitionParameters[$index];
53
            } else {
54
                // If the parameter is optional and wasn't specified, we take its default value
55
                if ($parameter->isDefaultValueAvailable() || $parameter->isOptional()) {
56
                    $args[] = $this->getParameterDefaultValue($parameter, $method);
57
                    continue;
58
                }
59
 
60
                throw new InvalidDefinition(sprintf(
61
                    'Parameter $%s of %s has no value defined or guessable',
62
                    $parameter->getName(),
63
                    $this->getFunctionName($method)
64
                ));
65
            }
66
 
67
            // Nested definitions
68
            if ($value instanceof Definition) {
69
                // If the container cannot produce the entry, we can use the default parameter value
70
                if ($parameter->isOptional() && ! $this->definitionResolver->isResolvable($value)) {
71
                    $value = $this->getParameterDefaultValue($parameter, $method);
72
                } else {
73
                    $value = $this->definitionResolver->resolve($value);
74
                }
75
            }
76
 
77
            $args[] = &$value;
78
        }
79
 
80
        return $args;
81
    }
82
 
83
    /**
84
     * Returns the default value of a function parameter.
85
     *
86
     * @throws InvalidDefinition Can't get default values from PHP internal classes and functions
87
     */
88
    private function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function) : mixed
89
    {
90
        try {
91
            return $parameter->getDefaultValue();
92
        } catch (\ReflectionException) {
93
            throw new InvalidDefinition(sprintf(
94
                'The parameter "%s" of %s has no type defined or guessable. It has a default value, '
95
                . 'but the default value can\'t be read through Reflection because it is a PHP internal class.',
96
                $parameter->getName(),
97
                $this->getFunctionName($function)
98
            ));
99
        }
100
    }
101
 
102
    private function getFunctionName(ReflectionMethod $method) : string
103
    {
104
        return $method->getName() . '()';
105
    }
106
}