--- /dev/null
+<?php
+
+/*
+ * This file is part of the Behat.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Behat\Behat\HelperContainer;
+
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use ReflectionFunctionAbstract;
+use ReflectionParameter;
+
+/**
+ * Automatically wires arguments of a given function from inside the container by using type-hitns.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+final class ArgumentAutowirer
+{
+ /**
+ * @var ContainerInterface
+ */
+ private $container;
+
+ /**
+ * Initialises wirer.
+ *
+ * @param ContainerInterface $container
+ */
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * Autowires given arguments using provided container.
+ *
+ * @param ReflectionFunctionAbstract $reflection
+ * @param array $arguments
+ *
+ * @return array
+ *
+ * @throws ContainerExceptionInterface if unset argument typehint can not be resolved from container
+ */
+ public function autowireArguments(ReflectionFunctionAbstract $reflection, array $arguments)
+ {
+ $newArguments = $arguments;
+ foreach ($reflection->getParameters() as $index => $parameter) {
+ if ($this->isArgumentWireable($newArguments, $index, $parameter)) {
+ $newArguments[$index] = $this->container->get($parameter->getClass()->getName());
+ }
+ }
+
+ return $newArguments;
+ }
+
+ /**
+ * Checks if given argument is wireable.
+ *
+ * Argument is wireable if it was not previously set and it has a class type-hint.
+ *
+ * @param array $arguments
+ * @param integer $index
+ * @param ReflectionParameter $parameter
+ *
+ * @return bool
+ */
+ private function isArgumentWireable(array $arguments, $index, ReflectionParameter $parameter)
+ {
+ return !isset($arguments[$index]) && !isset($arguments[$parameter->getName()]) && $parameter->getClass();
+ }
+}