Passed
Push — main ( a427c0...b402c4 )
by Michael
03:20
created

BindingBuilder::singleton()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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