4 * This file is part of the Behat.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 namespace Behat\Behat\Transformation\Transformation;
13 use Behat\Behat\Definition\Call\DefinitionCall;
14 use Behat\Behat\Transformation\Call\TransformationCall;
15 use Behat\Behat\Transformation\SimpleArgumentTransformation;
16 use Behat\Testwork\Call\CallCenter;
17 use Behat\Testwork\Call\RuntimeCallee;
19 use ReflectionFunctionAbstract;
21 use ReflectionParameter;
24 * By-type object transformation.
26 * @author Konstantin Kudryashov <ever.zet@gmail.com>
28 final class ReturnTypeTransformation extends RuntimeCallee implements SimpleArgumentTransformation
34 static public function supportsPatternAndMethod($pattern, ReflectionMethod $method)
36 $returnClass = self::getReturnClass($method);
38 if (null === $returnClass) {
42 return '' === $pattern;
46 * Initializes transformation.
48 * @param string $pattern
49 * @param callable $callable
50 * @param null|string $description
52 public function __construct($pattern, $callable, $description = null)
54 parent::__construct($callable, $description);
60 public function supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue)
62 $returnClass = self::getReturnClass($this->getReflection());
64 if (null === $returnClass) {
68 $parameterClass = $this->getParameterClassNameByIndex($definitionCall, $argumentIndex);
70 return $parameterClass === $returnClass;
76 public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue)
78 $call = new TransformationCall(
79 $definitionCall->getEnvironment(),
80 $definitionCall->getCallee(),
85 $result = $callCenter->makeCall($call);
87 if ($result->hasException()) {
88 throw $result->getException();
91 return $result->getReturn();
97 public function getPriority()
105 public function getPattern()
113 public function __toString()
115 return 'ReturnTypeTransform';
119 * Extracts parameters from provided definition call.
121 * @param ReflectionFunctionAbstract $reflection
123 * @return null|string
125 static private function getReturnClass(ReflectionFunctionAbstract $reflection)
127 $type = $reflection->getReturnType();
129 if (null === $type || $type->isBuiltin()) {
133 return (string) $type;
137 * Attempts to get definition parameter using its index (parameter position or name).
139 * @param DefinitionCall $definitionCall
140 * @param string|integer $argumentIndex
142 * @return null|string
144 private function getParameterClassNameByIndex(DefinitionCall $definitionCall, $argumentIndex)
146 $parameters = array_filter(
147 array_filter($this->getCallParameters($definitionCall),
148 $this->hasIndex($argumentIndex)
152 return count($parameters) ? current($parameters)->getClass()->getName() : null;
156 * Extracts parameters from provided definition call.
158 * @param DefinitionCall $definitionCall
160 * @return ReflectionParameter[]
162 private function getCallParameters(DefinitionCall $definitionCall)
164 return $definitionCall->getCallee()->getReflection()->getParameters();
168 * Returns appropriate closure for filtering parameter by index.
170 * @param string|integer $index
174 private function hasIndex($index)
176 return is_string($index) ? $this->hasName($index) : $this->hasPosition($index);
180 * Returns closure to filter parameter by name.
182 * @param string $index
186 private function hasName($index)
188 return function (ReflectionParameter $parameter) use ($index) {
189 return $index === $parameter->getName();
194 * Returns closure to filter parameter by position.
196 * @param integer $index
200 private function hasPosition($index)
202 return function (ReflectionParameter $parameter) use ($index) {
203 return $index === $parameter->getPosition();
208 * Returns closure to filter parameter by typehinted class.
212 private function isClass()
214 return function (ReflectionParameter $parameter) {
215 return $parameter->getClass();