Passed
Pull Request — master (#1)
by Kevin
07:49
created

Proxy::assertNotPersisted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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