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\HelperContainer\Call\Filter;
13 use Behat\Behat\Definition\Definition;
14 use Behat\Behat\HelperContainer\Environment\ServiceContainerEnvironment;
15 use Behat\Behat\Definition\Call\DefinitionCall;
16 use Behat\Behat\HelperContainer\ArgumentAutowirer;
17 use Behat\Behat\HelperContainer\Exception\UnsupportedCallException;
18 use Behat\Behat\Transformation\Call\TransformationCall;
19 use Behat\Behat\Transformation\Transformation;
20 use Behat\Testwork\Call\Call;
21 use Behat\Testwork\Call\Filter\CallFilter;
22 use Behat\Testwork\Environment\Call\EnvironmentCall;
23 use Psr\Container\ContainerExceptionInterface;
24 use Psr\Container\ContainerInterface;
27 * Dynamically resolves call arguments using the service container.
29 * @author Konstantin Kudryashov <ever.zet@gmail.com>
31 final class ServicesResolver implements CallFilter
36 public function supportsCall(Call $call)
38 return ($call instanceof DefinitionCall || $call instanceof TransformationCall)
39 && $call->getEnvironment() instanceof ServiceContainerEnvironment;
43 * Filters a call and returns a new one.
49 * @throws UnsupportedCallException
50 * @throws ContainerExceptionInterface
52 public function filterCall(Call $call)
54 if ($container = $this->getContainer($call)) {
55 $autowirer = new ArgumentAutowirer($container);
56 $newArguments = $autowirer->autowireArguments($call->getCallee()->getReflection(), $call->getArguments());
58 return $this->repackageCallIfNewArguments($call, $newArguments);
65 * Gets container from the call.
69 * @return null|ContainerInterface
71 * @throws UnsupportedCallException if given call is not EnvironmentCall or environment is not ServiceContainerEnvironment
73 private function getContainer(Call $call)
75 if (!$call instanceof EnvironmentCall) {
76 throw new UnsupportedCallException(sprintf(
77 'ServicesResolver can not filter `%s` call.',
82 $environment = $call->getEnvironment();
84 if (!$environment instanceof ServiceContainerEnvironment) {
85 throw new UnsupportedCallException(sprintf(
86 'ServicesResolver can not filter `%s` call.',
91 return $environment->getServiceContainer();
95 * Repackages old calls with new arguments, but only if two differ.
98 * @param array $arguments
102 * @throws UnsupportedCallException if given call is not DefinitionCall or TransformationCall
104 private function repackageCallIfNewArguments(Call $call, array $arguments)
106 if ($arguments === $call->getArguments()) {
110 return $this->repackageCallWithNewArguments($call, $arguments);
114 * Repackages old calls with new arguments.
117 * @param array $newArguments
119 * @return DefinitionCall|TransformationCall
121 * @throws UnsupportedCallException
123 private function repackageCallWithNewArguments(Call $call, array $newArguments)
125 if ($call instanceof DefinitionCall) {
126 return $this->repackageDefinitionCall($call, $newArguments);
129 if ($call instanceof TransformationCall) {
130 return $this->repackageTransformationCall($call, $newArguments);
133 throw new UnsupportedCallException(
135 'ServicesResolver can not filter `%s` call.',
142 * Repackages definition call with new arguments.
144 * @param DefinitionCall $call
145 * @param array $newArguments
147 * @return DefinitionCall
149 * @throws UnsupportedCallException
151 private function repackageDefinitionCall(DefinitionCall $call, array $newArguments)
153 $definition = $call->getCallee();
155 if (!$definition instanceof Definition) {
156 throw new UnsupportedCallException(
158 'Something is wrong in callee associated with `%s` call.',
164 return new DefinitionCall(
165 $call->getEnvironment(),
170 $call->getErrorReportingLevel()
175 * Repackages transformation call with new arguments.
177 * @param TransformationCall $call
178 * @param array $newArguments
180 * @return TransformationCall
182 * @throws UnsupportedCallException
184 private function repackageTransformationCall(TransformationCall $call, array $newArguments)
186 $transformation = $call->getCallee();
188 if (!$transformation instanceof Transformation) {
189 throw new UnsupportedCallException(
191 'Something is wrong in callee associated with `%s` call.',
197 return new TransformationCall(
198 $call->getEnvironment(),
199 $call->getDefinition(),