1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace Autarky\Container\Factory;
12:
13: use Autarky\Container\ContainerInterface;
14: use Autarky\Container\Exception\UnresolvableArgumentException;
15:
16: 17: 18:
19: class Factory implements FactoryInterface
20: {
21: 22: 23: 24: 25:
26: protected $definition;
27:
28: 29: 30: 31: 32:
33: protected $params;
34:
35: 36: 37: 38: 39: 40:
41: public function __construct(Definition $definition, array $params = array())
42: {
43: $this->definition = $definition;
44: $this->params = $params;
45: }
46:
47: 48: 49: 50: 51: 52: 53:
54: public function getFactory(array $params = array())
55: {
56: $factory = clone $this;
57: $factory->params = $params;
58: return $factory;
59: }
60:
61: 62: 63:
64: public function invoke(ContainerInterface $container, array $params = array())
65: {
66: $params = array_replace($this->params, $params);
67: $callable = $this->definition->getCallable();
68:
69: if (is_array($callable) && is_string($callable[0])) {
70: $callable[0] = $container->resolve($callable[0]);
71: }
72:
73: $args = [];
74:
75: foreach ($this->definition->getArguments() as $arg) {
76: if ($arg->isClass()) {
77: $resolvedArg = $this->resolveClassArg($container, $arg, $params);
78: } else {
79: $resolvedArg = $this->resolveScalarArg($container, $arg, $params);
80: }
81:
82: if ($resolvedArg instanceof FactoryInterface) {
83: $resolvedArg = $resolvedArg->invoke($container);
84: }
85:
86: $args[$arg->getPosition()] = $resolvedArg;
87: }
88:
89: return call_user_func_array($callable, $args);
90: }
91:
92: protected function resolveClassArg(ContainerInterface $container, ClassArgument $arg, array $params)
93: {
94: $name = $arg->getName();
95: $class = $arg->getClass();
96:
97:
98:
99:
100: while ($name !== null) {
101: if ($params && array_key_exists($name, $params)) {
102: $class = $params[$name];
103: }
104:
105: if (is_object($class)) {
106: return $class;
107: }
108:
109: $name = ($name != $class) ? $class : null;
110: }
111:
112: try {
113: return $container->resolve($class);
114: } catch (\ReflectionException $exception) {
115: if (!$arg->isRequired()) {
116: return null;
117: }
118:
119: throw $exception;
120: }
121: }
122:
123: protected function resolveScalarArg(ContainerInterface $container, ScalarArgument $arg, array $params)
124: {
125: $name = $arg->getName();
126:
127: if ($params && array_key_exists($name, $params)) {
128: return $params[$name];
129: }
130:
131: if (!$arg->isRequired()) {
132: return $arg->getDefault();
133: }
134:
135: $pos = $arg->getPosition() + 1;
136: $defName = $this->definition->getName();
137: $message = "Unresolvable argument: Argument #{$pos} ($name) of $defName"
138: .' - Argument is required and has no value';
139:
140: throw new UnresolvableArgumentException($message);
141: }
142:
143: 144: 145: 146: 147: 148: 149: 150:
151: public function __invoke(ContainerInterface $container, array $params = array())
152: {
153: return $this->invoke($container, $params);
154: }
155: }
156: