0424850e144c235aca7b4a85021f6bb36dc2e67d
[yaffs-website] / vendor / symfony / http-kernel / ControllerMetadata / ArgumentMetadataFactory.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpKernel\ControllerMetadata;
13
14 /**
15  * Builds {@see ArgumentMetadata} objects based on the given Controller.
16  *
17  * @author Iltar van der Berg <kjarli@gmail.com>
18  */
19 final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
20 {
21     /**
22      * If the ...$arg functionality is available.
23      *
24      * Requires at least PHP 5.6.0 or HHVM 3.9.1
25      *
26      * @var bool
27      */
28     private $supportsVariadic;
29
30     /**
31      * If the reflection supports the getType() method to resolve types.
32      *
33      * Requires at least PHP 7.0.0 or HHVM 3.11.0
34      *
35      * @var bool
36      */
37     private $supportsParameterType;
38
39     public function __construct()
40     {
41         $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic');
42         $this->supportsParameterType = method_exists('ReflectionParameter', 'getType');
43     }
44
45     /**
46      * {@inheritdoc}
47      */
48     public function createArgumentMetadata($controller)
49     {
50         $arguments = array();
51
52         if (is_array($controller)) {
53             $reflection = new \ReflectionMethod($controller[0], $controller[1]);
54         } elseif (is_object($controller) && !$controller instanceof \Closure) {
55             $reflection = (new \ReflectionObject($controller))->getMethod('__invoke');
56         } else {
57             $reflection = new \ReflectionFunction($controller);
58         }
59
60         foreach ($reflection->getParameters() as $param) {
61             $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull());
62         }
63
64         return $arguments;
65     }
66
67     /**
68      * Returns whether an argument is variadic.
69      *
70      * @param \ReflectionParameter $parameter
71      *
72      * @return bool
73      */
74     private function isVariadic(\ReflectionParameter $parameter)
75     {
76         return $this->supportsVariadic && $parameter->isVariadic();
77     }
78
79     /**
80      * Determines whether an argument has a default value.
81      *
82      * @param \ReflectionParameter $parameter
83      *
84      * @return bool
85      */
86     private function hasDefaultValue(\ReflectionParameter $parameter)
87     {
88         return $parameter->isDefaultValueAvailable();
89     }
90
91     /**
92      * Returns a default value if available.
93      *
94      * @param \ReflectionParameter $parameter
95      *
96      * @return mixed|null
97      */
98     private function getDefaultValue(\ReflectionParameter $parameter)
99     {
100         return $this->hasDefaultValue($parameter) ? $parameter->getDefaultValue() : null;
101     }
102
103     /**
104      * Returns an associated type to the given parameter if available.
105      *
106      * @param \ReflectionParameter $parameter
107      *
108      * @return null|string
109      */
110     private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
111     {
112         if ($this->supportsParameterType) {
113             if (!$type = $parameter->getType()) {
114                 return;
115             }
116             $name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString();
117             if ('array' === $name && !$type->isBuiltin()) {
118                 // Special case for HHVM with variadics
119                 return;
120             }
121         } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $name)) {
122             $name = $name[1];
123         } else {
124             return;
125         }
126         $lcName = strtolower($name);
127
128         if ('self' !== $lcName && 'parent' !== $lcName) {
129             return $name;
130         }
131         if (!$function instanceof \ReflectionMethod) {
132             return;
133         }
134         if ('self' === $lcName) {
135             return $function->getDeclaringClass()->name;
136         }
137         if ($parent = $function->getDeclaringClass()->getParentClass()) {
138             return $parent->name;
139         }
140     }
141 }