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

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