Parameter::resolve()   A
last analyzed

Complexity

Conditions 5
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 5
eloc 11
nc 6
nop 1
dl 0
loc 21
rs 9.6111
c 3
b 1
f 0
1
<?php
2
3
namespace Zenstruck\Callback;
4
5
use Zenstruck\Callback\Exception\UnresolveableArgument;
6
use Zenstruck\Callback\Parameter\TypedParameter;
7
use Zenstruck\Callback\Parameter\UnionParameter;
8
use Zenstruck\Callback\Parameter\UntypedParameter;
9
10
/**
11
 * @author Kevin Bond <[email protected]>
12
 */
13
abstract class Parameter
14
{
15
    /** @var bool */
16
    private $optional = false;
17
18
    /**
19
     * @see UnionParameter::__construct()
20
     */
21
    final public static function union(self ...$parameters): self
22
    {
23
        return new UnionParameter(...$parameters);
24
    }
25
26
    /**
27
     * @see TypedParameter::__construct()
28
     */
29
    final public static function typed(string $type, $value, int $options = Argument::EXACT|Argument::COVARIANCE|Argument::CONTRAVARIANCE|Argument::VERY_STRICT): self
30
    {
31
        return new TypedParameter($type, $value, $options);
32
    }
33
34
    /**
35
     * @see UntypedParameter::__construct()
36
     */
37
    final public static function untyped($value): self
38
    {
39
        return new UntypedParameter($value);
40
    }
41
42
    /**
43
     * @see ValueFactory::__construct()
44
     */
45
    final public static function factory(callable $factory): ValueFactory
46
    {
47
        return new ValueFactory($factory);
48
    }
49
50
    final public function optional(): self
51
    {
52
        $this->optional = true;
53
54
        return $this;
55
    }
56
57
    /**
58
     * @internal
59
     *
60
     * @return mixed
61
     *
62
     * @throws UnresolveableArgument
63
     */
64
    final public function resolve(Argument $argument)
65
    {
66
        try {
67
            $value = $this->valueFor($argument);
68
        } catch (UnresolveableArgument $e) {
69
            if ($argument->isOptional()) {
70
                return $argument->defaultValue();
71
            }
72
73
            throw $e;
74
        }
75
76
        if ($value instanceof ValueFactory) {
77
            $value = $value($argument);
78
        }
79
80
        if (!$argument->allows($value)) {
81
            throw new UnresolveableArgument(\sprintf('Unable to resolve argument. Expected "%s", got "%s".', $argument->type(), get_debug_type($value)));
82
        }
83
84
        return $value;
85
    }
86
87
    /**
88
     * @internal
89
     */
90
    final public function isOptional(): bool
91
    {
92
        return $this->optional;
93
    }
94
95
    abstract public function type(): string;
96
97
    abstract protected function valueFor(Argument $argument);
98
}
99