Passed
Pull Request — master (#111)
by Wouter
02:24
created

ModelFactory::__callStatic()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 8
rs 10
ccs 0
cts 0
cp 0
cc 2
nc 2
nop 2
crap 6
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
    final static public function __callStatic(string $name, array $arguments)
55
    {
56
        $modelName = substr(strrchr(static::getClass(), "\\"), 1);
57
        if ('create'.ucfirst($modelName) !== $name) {
58
            throw new \BadMethodCallException(sprintf('Call to undefined method "%s::%s".', __CLASS__, $name));
59
        }
60
61
        return static::new()->create(...$arguments);
0 ignored issues
show
Bug introduced by
$arguments is expanded, but the parameter $attributes of Zenstruck\Foundry\Factory::create() does not expect variable arguments. ( Ignorable by Annotation )

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

61
        return static::new()->create(/** @scrutinizer ignore-type */ ...$arguments);
Loading history...
62 10
    }
63
64 10
    /**
65 10
     * Try and find existing object for the given $attributes. If not found,
66
     * instantiate and persist.
67
     *
68 10
     * @return Proxy|object
69
     *
70
     * @psalm-return Proxy<TModel>
71
     */
72
    final public static function findOrCreate(array $attributes): Proxy
73
    {
74 20
        if ($found = static::repository()->find($attributes)) {
75
            return \is_array($found) ? $found[0] : $found;
0 ignored issues
show
introduced by
The condition is_array($found) is always false.
Loading history...
76 20
        }
77
78
        return static::new()->create($attributes);
79
    }
80
81
    /**
82 10
     * @see RepositoryProxy::random()
83
     */
84 10
    final public static function random(): Proxy
85
    {
86
        return static::repository()->random();
87
    }
88
89
    /**
90 10
     * @see RepositoryProxy::randomSet()
91
     */
92 10
    final public static function randomSet(int $number): array
93
    {
94
        return static::repository()->randomSet($number);
95
    }
96 210
97
    /**
98 210
     * @see RepositoryProxy::randomRange()
99
     */
100
    final public static function randomRange(int $min, int $max): array
101
    {
102
        return static::repository()->randomRange($min, $max);
103
    }
104
105
    /** @psalm-return RepositoryProxy<TModel> */
106 600
    final public static function repository(): RepositoryProxy
107
    {
108 600
        return static::configuration()->repositoryFor(static::getClass());
109
    }
110
111
    /**
112
     * Override to add default instantiator and default afterInstantiate/afterPersist events.
113
     *
114
     * @return static
115
     */
116 30
    protected function initialize()
117
    {
118 30
        return $this;
119
    }
120
121
    /**
122
     * @param array|callable $attributes
123
     *
124
     * @return static
125
     */
126
    final protected function addState($attributes = []): self
127
    {
128
        return $this->withAttributes($attributes);
129
    }
130
131
    /** @psalm-return class-string<TModel> */
132
    abstract protected static function getClass(): string;
133
134
    abstract protected function getDefaults(): array;
135
}
136