Passed
Pull Request — master (#185)
by Tobias
02:33
created

ModelFactory::__callStatic()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 7
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Zenstruck\Foundry;
4
5
/**
6
 * @template TModel of object
7
 * @extends Factory<TModel>
8
 *
9
 * @author Kevin Bond <[email protected]>
10
 */
11
abstract class ModelFactory extends Factory
12
{
13 604
    public function __construct()
14
    {
15 604
        parent::__construct(static::getClass());
16 604
    }
17
18
    /**
19
     * @return list<Proxy<TModel>&TModel>
0 ignored issues
show
Bug introduced by
The type Zenstruck\Foundry\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
     */
21
    public static function createMany(): array
22
    {
23
        $arguments = func_get_args();
24 611
25
        return static::new()->many($arguments[0])->create($arguments[1] ?? []);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::new()->ma...rguments[1] ?? array()) returns the type array which is incompatible with the documented return type Zenstruck\Foundry\list.
Loading history...
26 611
    }
27 10
28 10
    /**
29
     * @param array|callable|string $defaultAttributes If string, assumes state
30
     * @param string                ...$states         Optionally pass default states (these must be methods on your ObjectFactory with no arguments)
31
     *
32 611
     * @return static
33 16
     */
34 10
    final public static function new($defaultAttributes = [], string ...$states): self
35
    {
36
        if (\is_string($defaultAttributes)) {
37
            $states = \array_merge([$defaultAttributes], $states);
38 604
            $defaultAttributes = [];
39 604
        }
40 604
41
        try {
42
            $factory = self::isBooted() ? self::configuration()->factories()->create(static::class) : new static();
43 604
        } catch (\ArgumentCountError $e) {
44 20
            throw new \RuntimeException('Model Factories with dependencies (Model Factory services) cannot be created before foundry is booted.', 0, $e);
45
        }
46
47 600
        $factory = $factory
48 10
            ->withAttributes([$factory, 'getDefaults'])
49
            ->withAttributes($defaultAttributes)
50
            ->initialize()
51 600
        ;
52
53
        if (!$factory instanceof static) {
0 ignored issues
show
introduced by
$factory is always a sub-type of static.
Loading history...
54
            throw new \TypeError(\sprintf('"%1$s::initialize()" must return an instance of "%1$s".', static::class));
55
        }
56
57
        foreach ($states as $state) {
58
            $factory = $factory->{$state}();
59
        }
60
61
        return $factory;
62 10
    }
63
64 10
    /**
65 10
     * A shortcut to create a single model without states.
66
     *
67
     * @return Proxy<TModel>&TModel
68 10
     */
69
    final public static function createOne(array $attributes = []): Proxy
70
    {
71
        return static::new()->create($attributes);
72
    }
73
74 20
    /**
75
     * Try and find existing object for the given $attributes. If not found,
76 20
     * instantiate and persist.
77
     *
78
     * @return Proxy<TModel>&TModel
79
     */
80
    final public static function findOrCreate(array $attributes): Proxy
81
    {
82 10
        if ($found = static::repository()->find($attributes)) {
83
            return \is_array($found) ? $found[0] : $found;
0 ignored issues
show
introduced by
The condition is_array($found) is always false.
Loading history...
84 10
        }
85
86
        return static::new()->create($attributes);
87
    }
88
89
    /**
90 10
     * @see RepositoryProxy::first()
91
     * @return Proxy<TModel>&TModel
92 10
     *
93
     * @throws \RuntimeException If no entities exist
94
     */
95
    final public static function first(string $sortedField = 'id'): Proxy
96 210
    {
97
        if (null === $proxy = static::repository()->first($sortedField)) {
98 210
            throw new \RuntimeException(\sprintf('No "%s" objects persisted.', static::getClass()));
99
        }
100
101
        return $proxy;
102
    }
103
104
    /**
105
     * @see RepositoryProxy::last()
106 600
     * @return Proxy<TModel>&TModel
107
     *
108 600
     * @throws \RuntimeException If no entities exist
109
     */
110
    final public static function last(string $sortedField = 'id'): Proxy
111
    {
112
        if (null === $proxy = static::repository()->last($sortedField)) {
113
            throw new \RuntimeException(\sprintf('No "%s" objects persisted.', static::getClass()));
114
        }
115
116 30
        return $proxy;
117
    }
118 30
119
    /**
120
     * @see RepositoryProxy::random()
121
     * @return Proxy<TModel>&TModel
122
     */
123
    final public static function random(array $attributes = []): Proxy
124
    {
125
        return static::repository()->random($attributes);
126
    }
127
128
    /**
129
     * Fetch one random object and create a new object if none exists.
130
     *
131
     * @return Proxy<TModel>&TModel
132
     */
133
    final public static function randomOrCreate(array $attributes = []): Proxy
134
    {
135
        try {
136
            return static::repository()->random($attributes);
137
        } catch (\RuntimeException $e) {
138
            return static::new()->create($attributes);
139
        }
140
    }
141
142
    /**
143
     * @see RepositoryProxy::randomSet()
144
     * @return list<Proxy<TModel>&TModel>
145
     */
146
    final public static function randomSet(int $number, array $attributes = []): array
147
    {
148
        return static::repository()->randomSet($number, $attributes);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::repositor...t($number, $attributes) returns the type array which is incompatible with the documented return type Zenstruck\Foundry\list.
Loading history...
149
    }
150
151
    /**
152
     * @see RepositoryProxy::randomRange()
153
     * @return list<Proxy<TModel>&TModel>
154
     */
155
    final public static function randomRange(int $min, int $max, array $attributes = []): array
156
    {
157
        return static::repository()->randomRange($min, $max, $attributes);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::repositor...min, $max, $attributes) returns the type array which is incompatible with the documented return type Zenstruck\Foundry\list.
Loading history...
158
    }
159
160
    /**
161
     * @see RepositoryProxy::count()
162
     */
163
    final public static function count(): int
164
    {
165
        return static::repository()->count();
166
    }
167
168
    /**
169
     * @see RepositoryProxy::truncate()
170
     */
171
    final public static function truncate(): void
172
    {
173
        static::repository()->truncate();
174
    }
175
176
    /**
177
     * @see RepositoryProxy::findAll()
178
     * @return list<Proxy<TModel>&TModel>
179
     */
180
    final public static function all(): array
181
    {
182
        return static::repository()->findAll();
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::repository()->findAll() returns the type array which is incompatible with the documented return type Zenstruck\Foundry\list.
Loading history...
183
    }
184
185
    /**
186
     * @see RepositoryProxy::find()
187
     * @return Proxy<TModel>&TModel
188
     *
189
     * @throws \RuntimeException If no entity found
190
     */
191
    final public static function find($criteria): Proxy
192
    {
193
        if (null === $proxy = static::repository()->find($criteria)) {
194
            throw new \RuntimeException(\sprintf('Could not find "%s" object.', static::getClass()));
195
        }
196
197
        return $proxy;
198
    }
199
200
    /**
201
     * @see RepositoryProxy::findBy()
202
     * @return list<Proxy<TModel>&TModel>
203
     */
204
    final public static function findBy(array $attributes): array
205
    {
206
        return static::repository()->findBy($attributes);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::repository()->findBy($attributes) returns the type array which is incompatible with the documented return type Zenstruck\Foundry\list.
Loading history...
207
    }
208
209
    final public static function assert(): RepositoryAssertions
210
    {
211
        return static::repository()->assert();
212
    }
213
214
    /**
215
     * @psalm-return RepositoryProxy<TModel>
216
     */
217
    final public static function repository(): RepositoryProxy
218
    {
219
        return static::configuration()->repositoryFor(static::getClass());
220
    }
221
222
    /**
223
     * @internal
224
     * @psalm-return class-string<TModel>
225
     */
226
    final public static function getEntityClass(): string
227
    {
228
        return static::getClass();
229
    }
230
231
    /** @psalm-return class-string<TModel> */
232
    abstract protected static function getClass(): string;
233
234
    /**
235
     * Override to add default instantiator and default afterInstantiate/afterPersist events.
236
     *
237
     * @return static
238
     */
239
    protected function initialize()
240
    {
241
        return $this;
242
    }
243
244
    /**
245
     * @param array|callable $attributes
246
     *
247
     * @return static
248
     */
249
    final protected function addState($attributes = []): self
250
    {
251
        return $this->withAttributes($attributes);
252
    }
253
254
    abstract protected function getDefaults(): array;
255
}
256