Passed
Pull Request — master (#1)
by Kevin
02:03
created

Proxy::instantiator()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Zenstruck\Foundry;
4
5
use Doctrine\Persistence\ObjectManager;
6
use Doctrine\Persistence\ObjectRepository;
7
use PHPUnit\Framework\Assert;
8
9
/**
10
 * @author Kevin Bond <[email protected]>
11
 */
12
final class Proxy
13
{
14
    private static bool $autoRefreshByDefault = true;
15
16
    private object $object;
17
    private string $class;
18
    private ?bool $autoRefresh = null;
19
20 90
    public function __construct(object $object)
21
    {
22 90
        $this->object = $object;
23 90
        $this->class = \get_class($object);
24 90
    }
25
26 30
    public function __call(string $method, array $arguments)
27
    {
28 30
        return $this->object()->{$method}(...$arguments);
29
    }
30
31 2
    public function __get(string $name)
32
    {
33 2
        return $this->object()->{$name};
34
    }
35
36 2
    public function __set(string $name, $value): void
37
    {
38 2
        $this->object()->{$name} = $value;
39 2
    }
40
41 2
    public function __unset(string $name): void
42
    {
43 2
        unset($this->object()->{$name});
44 2
    }
45
46 2
    public function __isset(string $name): bool
47
    {
48 2
        return isset($this->object()->{$name});
49
    }
50
51 4
    public function __toString(): string
52
    {
53 4
        if (!\method_exists($this->object, '__toString')) {
54 2
            throw new \RuntimeException(\sprintf('Proxied object "%s" cannot be converted to a string.', $this->class));
55
        }
56
57 2
        return $this->object()->__toString();
58
    }
59
60 48
    public function object(): object
61
    {
62 48
        if ($this->autoRefresh ?? self::$autoRefreshByDefault) {
63 30
            $this->refresh();
64
        }
65
66 48
        return $this->object;
67
    }
68
69 2
    public function save(): self
70
    {
71 2
        $this->objectManager()->persist($this->object);
72 2
        $this->objectManager()->flush();
73
74 2
        return $this;
75
    }
76
77 2
    public function remove(): self
78
    {
79 2
        $this->objectManager()->remove($this->object);
80 2
        $this->objectManager()->flush();
81
82 2
        return $this;
83
    }
84
85 32
    public function refresh(): self
86
    {
87 32
        if ($this->objectManager()->contains($this->object)) {
88 30
            $this->objectManager()->refresh($this->object);
89
90 30
            return $this;
91
        }
92
93 4
        if (!$object = $this->fetchObject()) {
94 2
            throw new \RuntimeException('The object no longer exists.');
95
        }
96
97 2
        $this->object = $object;
98
99 2
        return $this;
100
    }
101
102
    /**
103
     * @param mixed $value
104
     */
105 4
    public function forceSet(string $property, $value): self
106
    {
107 4
        return $this->forceSetAll([$property => $value]);
108
    }
109
110 4
    public function forceSetAll(array $properties): self
111
    {
112 4
        $object = $this->object();
113
114 4
        foreach ($properties as $property => $value) {
115 4
            Instantiator::forceSet($object, $property, $value);
116
        }
117
118 4
        return $this;
119
    }
120
121
    /**
122
     * @return mixed
123
     */
124 2
    public function forceGet(string $property)
125
    {
126 2
        return Instantiator::forceGet($this->object(), $property);
127
    }
128
129
    /**
130
     * @return RepositoryProxy|ObjectRepository
131
     */
132 2
    public function repository(bool $proxy = true): ObjectRepository
133
    {
134 2
        return PersistenceManager::repositoryFor($this->class, $proxy);
135
    }
136
137 66
    public function withAutoRefresh(): self
138
    {
139 66
        $this->autoRefresh = true;
140
141 66
        return $this;
142
    }
143
144 14
    public function withoutAutoRefresh(): self
145
    {
146 14
        $this->autoRefresh = false;
147
148 14
        return $this;
149
    }
150
151 2
    public function assertPersisted(): self
152
    {
153
        // todo improve message
154 2
        Assert::assertNotNull($this->fetchObject(), 'The object is not persisted.');
155
156 2
        return $this;
157
    }
158
159 2
    public function assertNotPersisted(): self
160
    {
161
        // todo improve message
162 2
        Assert::assertNull($this->fetchObject(), 'The object is persisted but it should not be.');
163
164 2
        return $this;
165
    }
166
167 4
    public static function autoRefreshByDefault(bool $value): void
168
    {
169 4
        self::$autoRefreshByDefault = $value;
170 4
    }
171
172
    /**
173
     * Todo - move to RepositoryProxy?
174
     */
175 8
    private function fetchObject(): ?object
176
    {
177 8
        $id = $this->objectManager()->getClassMetadata($this->class)->getIdentifierValues($this->object);
178
179 8
        return empty($id) ? null : $this->objectManager()->find($this->class, $id);
180
    }
181
182 36
    private function objectManager(): ObjectManager
183
    {
184 36
        return PersistenceManager::objectManagerFor($this->class);
185
    }
186
}
187