Passed
Pull Request — master (#108)
by Wouter
02:19
created

ModelFactory::randomOrCreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
ccs 1
cts 1
cp 1
rs 10
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Zenstruck\Foundry;
4
5
/**
6
 * @template TModel of object
7
 * @template-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|string $defaultAttributes If string, assumes state
20
     * @param string                ...$states         Optionally pass default states (these must be methods on your ObjectFactory with no arguments)
21
     *
22
     * @return static
23
     */
24 611
    final public static function new($defaultAttributes = [], string ...$states): self
25
    {
26 611
        if (\is_string($defaultAttributes)) {
27 10
            $states = \array_merge([$defaultAttributes], $states);
28 10
            $defaultAttributes = [];
29
        }
30
31
        try {
32 611
            $factory = self::isBooted() ? self::configuration()->factories()->create(static::class) : new static();
33 16
        } catch (\ArgumentCountError $e) {
34 10
            throw new \RuntimeException('Model Factories with dependencies (Model Factory services) cannot be created before foundry is booted.', 0, $e);
35
        }
36
37
        $factory = $factory
38 604
            ->withAttributes([$factory, 'getDefaults'])
39 604
            ->withAttributes($defaultAttributes)
40 604
            ->initialize()
41
        ;
42
43 604
        if (!$factory instanceof static) {
0 ignored issues
show
introduced by
$factory is always a sub-type of static.
Loading history...
44 20
            throw new \TypeError(\sprintf('"%1$s::initialize()" must return an instance of "%1$s".', static::class));
45
        }
46
47 600
        foreach ($states as $state) {
48 10
            $factory = $factory->{$state}();
49
        }
50
51 600
        return $factory;
52
    }
53
54
    /**
55
     * Try and find existing object for the given $attributes. If not found,
56
     * instantiate and persist.
57
     *
58
     * @return Proxy|object
59
     *
60
     * @psalm-return Proxy<TModel>
61
     */
62 10
    final public static function findOrCreate(array $attributes): Proxy
63
    {
64 10
        if ($found = static::repository()->find($attributes)) {
65 10
            return \is_array($found) ? $found[0] : $found;
0 ignored issues
show
introduced by
The condition is_array($found) is always false.
Loading history...
66
        }
67
68 10
        return static::new()->create($attributes);
69
    }
70
71
    /**
72
     * @see RepositoryProxy::random()
73
     */
74 20
    final public static function random(): Proxy
75
    {
76 20
        return static::repository()->random();
77
    }
78
79
    /**
80
     * Fetch one random object and create a new object if none exists.
81
     *
82 10
     * @return Proxy|object
83
     *
84 10
     * @psalm-return Proxy<TModel>
85
     */
86
    final public static function randomOrCreate(): Proxy
87
    {
88
        try {
89
            return static::repository()->random();
90 10
        } catch (\RuntimeException $e) {
91
            return static::new()->create();
92 10
        }
93
    }
94
95
    /**
96 210
     * @see RepositoryProxy::randomSet()
97
     */
98 210
    final public static function randomSet(int $number): array
99
    {
100
        return static::repository()->randomSet($number);
101
    }
102
103
    /**
104
     * @see RepositoryProxy::randomRange()
105
     */
106 600
    final public static function randomRange(int $min, int $max): array
107
    {
108 600
        return static::repository()->randomRange($min, $max);
109
    }
110
111
    /** @psalm-return RepositoryProxy<TModel> */
112
    final public static function repository(): RepositoryProxy
113
    {
114
        return static::configuration()->repositoryFor(static::getClass());
115
    }
116 30
117
    /**
118 30
     * Override to add default instantiator and default afterInstantiate/afterPersist events.
119
     *
120
     * @return static
121
     */
122
    protected function initialize()
123
    {
124
        return $this;
125
    }
126
127
    /**
128
     * @param array|callable $attributes
129
     *
130
     * @return static
131
     */
132
    final protected function addState($attributes = []): self
133
    {
134
        return $this->withAttributes($attributes);
135
    }
136
137
    /** @psalm-return class-string<TModel> */
138
    abstract protected static function getClass(): string;
139
140
    abstract protected function getDefaults(): array;
141
}
142