Passed
Pull Request — master (#185)
by Tobias
03:14 queued 11s
created

ModelFactory::createMany()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

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