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

CallProxy::setState()   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
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\EnhancedContainer\Core;
6
7
use Illuminate\Support\Traits\ForwardsCalls;
8
use MichaelRubel\EnhancedContainer\Call;
9
use MichaelRubel\EnhancedContainer\Exceptions\InstanceInteractionException;
10
use MichaelRubel\EnhancedContainer\Traits\InteractsWithContainer;
11
12
class CallProxy implements Call
13
{
14
    use InteractsWithContainer, ForwardsCalls;
0 ignored issues
show
introduced by
The trait MichaelRubel\EnhancedCon...\InteractsWithContainer requires some properties which are not provided by MichaelRubel\EnhancedContainer\Core\CallProxy: $contextual, $map
Loading history...
15
16
    /**
17
     * @var object
18
     */
19
    protected object $instance;
20
21
    /**
22
     * @var object
23
     */
24
    protected object $previous;
25
26
    /**
27
     * @var array
28
     */
29
    protected array $state = [];
30
31
    /**
32
     * CallProxy constructor.
33
     *
34
     * @param  object|string  $class
35
     * @param  array  $dependencies
36
     * @param  string|null  $context
37
     */
38 60
    public function __construct(
39
        object | string $class,
40
        array $dependencies = [],
41
        ?string $context = null
42
    ) {
43 60
        $this->instance = $this->getInstance($class, $dependencies, $context);
44
    }
45
46
    /**
47
     * Gets the internal property by name.
48
     *
49
     * @param  string  $property
50
     *
51
     * @return mixed
52
     */
53 10
    public function getInternal(string $property): mixed
54
    {
55 10
        return $this->{$property};
56
    }
57
58
    /**
59
     * Perform the container call.
60
     *
61
     * @param  object  $service
62
     * @param  string  $method
63
     * @param  array  $parameters
64
     *
65
     * @return mixed
66
     */
67 51
    protected function containerCall(object $service, string $method, array $parameters): mixed
68
    {
69
        try {
70 51
            return app()->call(
71 51
                [$service, $method],
72 51
                $this->getParameters($service, $method, $parameters)
73
            );
74 10
        } catch (\ReflectionException) {
75 3
            return $this->forwardCallTo($service, $method, $parameters);
76
        }
77
    }
78
79
    /**
80
     * @return void
81
     */
82 16
    protected function findForwardedInstance(): void
83
    {
84 16
        $clue = $this->instance::class . Forwarding::CONTAINER_KEY;
85
86 16
        if (app()->bound($clue)) {
87 11
            $newInstance = rescue(fn () => app($clue), report: false);
88
89 11
            if (! is_null($newInstance)) {
90 11
                $this->previous = $this->instance;
91 11
                $this->instance = $newInstance;
92
            }
93
        }
94
    }
95
96
    /**
97
     * @param  string  $name
98
     * @param  string  $type
99
     *
100
     * @return void
101
     */
102 57
    protected function setState(string $name, string $type): void
103
    {
104 57
        $this->state[$name] = $type;
105
    }
106
107
    /**
108
     * @param  string  $name
109
     *
110
     * @return bool
111
     */
112 13
    protected function hasPreviousState(string $name): bool
113
    {
114 13
        return isset($this->state[$name]) && isset($this->previous);
115
    }
116
117
    /**
118
     * Pass the call through container.
119
     *
120
     * @param  string  $method
121
     * @param  array  $parameters
122
     *
123
     * @return mixed
124
     * @throws InstanceInteractionException
125
     */
126 51
    public function __call(string $method, array $parameters): mixed
127
    {
128 51
        if (! method_exists($this->instance, $method)) {
129 11
            if ($this->hasPreviousState($method)) {
130 1
                throw new InstanceInteractionException;
131
            }
132
133 11
            $this->findForwardedInstance();
134
        }
135
136 51
        $this->setState($method, Call::METHOD);
137
138 51
        return $this->containerCall($this->instance, $method, $parameters);
139
    }
140
141
    /**
142
     * Get the instance's property.
143
     *
144
     * @param  string  $name
145
     *
146
     * @return mixed
147
     * @throws InstanceInteractionException
148
     */
149 8
    public function __get(string $name): mixed
150
    {
151 8
        if (! property_exists($this->instance, $name)) {
152 2
            if ($this->hasPreviousState($name)) {
153 1
                throw new InstanceInteractionException;
154
            }
155
156 1
            $this->findForwardedInstance();
157
158 1
            $this->setState($name, Call::GET);
159
        }
160
161 8
        return $this->instance->{$name};
162
    }
163
164
    /**
165
     * Set the instance's property.
166
     *
167
     * @param  string  $name
168
     * @param  mixed  $value
169
     */
170 6
    public function __set(string $name, mixed $value): void
171
    {
172 6
        if (! property_exists($this->instance, $name)) {
173 4
            $this->findForwardedInstance();
174
        }
175
176 6
        $this->setState($name, Call::SET);
177
178 6
        $this->instance->{$name} = $value;
179
    }
180
}
181