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

RepositoryProxy::truncate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 2
Bugs 1 Features 1
Metric Value
cc 2
eloc 4
c 2
b 1
f 1
nc 2
nop 0
dl 0
loc 9
ccs 4
cts 5
cp 0.8
crap 2.032
rs 10
1
<?php
2
3
namespace Zenstruck\Foundry;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Doctrine\ORM\EntityRepository;
7
use Doctrine\Persistence\ObjectRepository;
8
use PHPUnit\Framework\Assert;
9
10
/**
11
 * @mixin EntityRepository
12
 *
13
 * @author Kevin Bond <[email protected]>
14
 */
15
final class RepositoryProxy implements ObjectRepository
16
{
17
    private ObjectRepository $repository;
18
19 42
    public function __construct(ObjectRepository $repository)
20
    {
21 42
        $this->repository = $repository;
22 42
    }
23
24 2
    public function __call(string $method, array $arguments)
25
    {
26 2
        return $this->proxyResult($this->repository->{$method}(...$arguments));
27
    }
28
29 10
    public function getCount(): int
30
    {
31 10
        if ($this->repository instanceof EntityRepository) {
32 10
            return $this->repository->count([]);
0 ignored issues
show
Bug introduced by
The method count() does not exist on Doctrine\Persistence\ObjectRepository. It seems like you code against a sub-type of said class. However, the method does not exist in Doctrine\Common\Persistence\ObjectRepository. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

32
            return $this->repository->/** @scrutinizer ignore-call */ count([]);
Loading history...
33
        }
34
35
        return \count($this->findAll());
36
    }
37
38 4
    public function assertEmpty(): self
39
    {
40 4
        return $this->assertCount(0);
41
    }
42
43 10
    public function assertCount(int $expectedCount): self
44
    {
45
        // todo add message
46 10
        Assert::assertSame($expectedCount, $this->getCount());
47
48 10
        return $this;
49
    }
50
51 2
    public function assertCountGreaterThan(int $expected): self
52
    {
53
        // todo add message
54 2
        Assert::assertGreaterThan($expected, $this->getCount());
55
56 2
        return $this;
57
    }
58
59 2
    public function assertCountGreaterThanOrEqual(int $expected): self
60
    {
61
        // todo add message
62 2
        Assert::assertGreaterThanOrEqual($expected, $this->getCount());
63
64 2
        return $this;
65
    }
66
67 2
    public function assertCountLessThan(int $expected): self
68
    {
69
        // todo add message
70 2
        Assert::assertLessThan($expected, $this->getCount());
71
72 2
        return $this;
73
    }
74
75 2
    public function assertCountLessThanOrEqual(int $expected): self
76
    {
77
        // todo add message
78 2
        Assert::assertLessThanOrEqual($expected, $this->getCount());
79
80 2
        return $this;
81
    }
82
83
    /**
84
     * @param object|array|mixed $criteria
85
     */
86 4
    public function assertExists($criteria): self
87
    {
88
        // todo add message
89 4
        Assert::assertNotNull($this->find($criteria));
90
91 4
        return $this;
92
    }
93
94
    /**
95
     * @param object|array|mixed $criteria
96
     */
97 2
    public function assertNotExists($criteria): self
98
    {
99
        // todo add message
100 2
        Assert::assertNull($this->find($criteria));
101
102 2
        return $this;
103
    }
104
105
    /**
106
     * @return Proxy|object|null
107
     */
108 2
    public function first(): ?object
109
    {
110 2
        return $this->findOneBy([]);
111
    }
112
113
    /**
114
     * Remove all rows.
115
     */
116 2
    public function truncate(): void
117
    {
118 2
        $om = PersistenceManager::objectManagerFor($this->getClassName());
119
120 2
        if (!$om instanceof EntityManagerInterface) {
121
            throw new \RuntimeException('This operation is only available when using doctrine/orm');
122
        }
123
124 2
        $om->createQuery("DELETE {$this->getClassName()} e")->execute();
125 2
    }
126
127
    /**
128
     * @return Proxy|object
129
     */
130 4
    public function random(): Proxy
131
    {
132 4
        return $this->randomSet(1)[0];
133
    }
134
135
    /**
136
     * @param int      $min The minimum number of objects to return (if max is null, will always return this amount)
137
     * @param int|null $max The max number of objects to return
138
     *
139
     * @return Proxy[]|object[]
140
     *
141
     * @throws \RuntimeException         if not enough persisted objects to satisfy the max
142
     * @throws \InvalidArgumentException if min is less than zero
143
     * @throws \InvalidArgumentException if max is less than min
144
     */
145 14
    public function randomSet(int $min, ?int $max = null): array
146
    {
147 14
        if (null === $max) {
148 10
            $max = $min;
149
        }
150
151 14
        if ($min < 0) {
152 2
            throw new \InvalidArgumentException(\sprintf('Min must be positive (%d given).', $min));
153
        }
154
155 12
        if ($max < $min) {
156 2
            throw new \InvalidArgumentException(\sprintf('Max (%d) cannot be less than min (%d).', $max, $min));
157
        }
158
159 10
        $all = \array_values($this->findAll());
160
161 10
        \shuffle($all);
162
163 10
        if (\count($all) < $max) {
164 4
            throw new \RuntimeException(\sprintf('At least %d "%s" object(s) must have been persisted (%d persisted).', $max, $this->getClassName(), \count($all)));
165
        }
166
167 6
        return \array_slice($all, 0, \random_int($min, $max));
168
    }
169
170
    /**
171
     * @param object|array|mixed $criteria
172
     *
173
     * @return Proxy|object|null
174
     */
175 8
    public function find($criteria): ?object
176
    {
177 8
        if ($criteria instanceof Proxy) {
178 2
            $criteria = $criteria->object();
179
        }
180
181 8
        if (!\is_array($criteria)) {
182 2
            return $this->proxyResult($this->repository->find($criteria));
183
        }
184
185 8
        return $this->findOneBy($criteria);
186
    }
187
188
    /**
189
     * @return Proxy[]|object[]
190
     */
191 12
    public function findAll(): array
192
    {
193 12
        return $this->proxyResult($this->repository->findAll());
194
    }
195
196
    /**
197
     * @return Proxy[]|object[]
198
     */
199 2
    public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
200
    {
201 2
        return $this->proxyResult($this->repository->findBy(self::normalizeCriteria($criteria), $orderBy, $limit, $offset));
202
    }
203
204
    /**
205
     * @return Proxy|object|null
206
     */
207 10
    public function findOneBy(array $criteria): ?object
208
    {
209 10
        return $this->proxyResult($this->repository->findOneBy(self::normalizeCriteria($criteria)));
210
    }
211
212 22
    public function getClassName(): string
213
    {
214 22
        return $this->repository->getClassName();
215
    }
216
217
    /**
218
     * @param mixed $result
219
     *
220
     * @return Proxy|Proxy[]|object|object[]|mixed
221
     */
222 22
    private function proxyResult($result)
223
    {
224 22
        if (\is_object($result) && $this->getClassName() === \get_class($result)) {
225 18
            return PersistenceManager::proxy($result);
226
        }
227
228 18
        if (\is_array($result)) {
229 12
            return \array_map([$this, 'proxyResult'], $result);
230
        }
231
232 6
        return $result;
233
    }
234
235 10
    private static function normalizeCriteria(array $criteria): array
236
    {
237 10
        return \array_map(
238
            function($value) {
239 8
                return $value instanceof Proxy ? $value->object() : $value;
240 10
            },
241 10
            $criteria
242
        );
243
    }
244
}
245