Passed
Pull Request — main (#4)
by Michael
03:30
created

BindingBuilder::wrapToClosure()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 2
b 0
f 0
nc 2
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\EnhancedContainer\Core;
6
7
use MichaelRubel\EnhancedContainer\Traits\InteractsWithContainer;
8
9
class BindingBuilder
10
{
11
    use InteractsWithContainer;
0 ignored issues
show
introduced by
The trait MichaelRubel\EnhancedCon...\InteractsWithContainer requires some properties which are not provided by MichaelRubel\EnhancedContainer\Core\BindingBuilder: $contextual, $map
Loading history...
12
13
    /**
14
     * @var string
15
     */
16
    protected string $abstract;
17
18
    /**
19
     * @var \Closure|string|array
20
     */
21
    protected \Closure|string|array $contextualImplementation;
22
23
    /**
24
     * BindingBuilder constructor.
25
     *
26
     * @param  object|string  $abstract
27
     */
28 37
    public function __construct(object | string $abstract)
29
    {
30 37
        $this->abstract = $this->convertToNamespace($abstract);
31
    }
32
33
    /**
34
     * Method binding.
35
     *
36
     * @param  string|null  $method
37
     * @param  \Closure|null  $override
38
     *
39
     * @return $this|null
40
     */
41 13
    public function method(string $method = null, \Closure $override = null): self|null
42
    {
43
        // Try to auto-resolve an implementation
44
        // for this particular abstract type.
45 13
        $this->resolve();
46
47 13
        if (is_null($method) || is_null($override)) {
48 8
            return $this;
49
        }
50
51 5
        return $this->{$method}($override);
52
    }
53
54
    /**
55
     * Basic "bind".
56
     *
57
     * @param  object|string|null  $concrete
58
     * @param  bool  $shared
59
     *
60
     * @return $this
61
     */
62 18
    public function to(object|string $concrete = null, bool $shared = false): self
63
    {
64 18
        app()->bind($this->abstract, $this->wrapToClosure($concrete), $shared);
65
66 18
        return $this;
67
    }
68
69
    /**
70
     * Basic "bind", binds itself.
71
     *
72
     * @return void
73
     */
74 1
    public function itself(): void
75
    {
76 1
        app()->bind($this->abstract);
77
    }
78
79
    /**
80
     * Singleton.
81
     *
82
     * @param  object|string|null  $concrete
83
     *
84
     * @return void
85
     */
86 3
    public function singleton(object|string $concrete = null): void
87
    {
88 3
        app()->singleton($this->abstract, $this->wrapToClosure($concrete));
89
    }
90
91
    /**
92
     * Scoped instance.
93
     *
94
     * @param  object|string|null  $concrete
95
     *
96
     * @return void
97
     */
98 2
    public function scoped(object|string $concrete = null): void
99
    {
100 2
        app()->scoped($this->abstract, $this->wrapToClosure($concrete));
101
    }
102
103
    /**
104
     * Enables contextual binding.
105
     *
106
     * @return $this
107
     */
108 6
    public function contextual(\Closure|string|array $implementation): self
109
    {
110 6
        $this->contextualImplementation = $implementation;
111
112 6
        return $this;
113
    }
114
115
    /**
116
     * Contextual binding.
117
     *
118
     * @param  array|string  $concrete
119
     *
120
     * @return void
121
     */
122 6
    public function for(array|string $concrete): void
123
    {
124 6
        app()->when($concrete)
125 6
             ->needs($this->abstract)
126 6
             ->give($this->contextualImplementation);
127
    }
128
129
    /**
130
     * Extend the abstract type.
131
     *
132
     * @param  \Closure  $closure
133
     *
134
     * @return BindingBuilder
135
     */
136 1
    public function extend(\Closure $closure): self
137
    {
138 1
        app()->extend($this->abstract, $closure);
139
140 1
        return $this;
141
    }
142
143
    /**
144
     * Register an existing instance as shared in the container.
145
     *
146
     * @param  mixed  $instance
147
     *
148
     * @return BindingBuilder
149
     */
150 1
    public function instance(mixed $instance): self
151
    {
152 1
        app()->instance($this->abstract, $instance);
153
154 1
        return $this;
155
    }
156
157
    /**
158
     * Try to resolve an implementation for this particular abstract type.
159
     *
160
     * @return mixed
161
     */
162 13
    protected function resolve(): mixed
163
    {
164 13
        $concrete = rescue(
165 13
            fn () => app($this->abstract),
166
            report: false
167
        );
168
169 13
        if (! is_null($concrete)) {
170 12
            $this->abstract = $this->convertToNamespace($concrete);
171
        }
172
173 13
        return $this->abstract;
174
    }
175
176
    /**
177
     * Bind the method to the container.
178
     *
179
     * @param  string  $method
180
     * @param  array  $parameters
181
     *
182
     * @return void
183
     */
184 11
    public function __call(string $method, array $parameters): void
185
    {
186 11
        app()->bindMethod([$this->abstract, $method], current($parameters));
187
    }
188
}
189