Completed
Push — master ( 02cd0c...4a56be )
by Kevin
26s queued 19s
created

Story::addToPool()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 15
ccs 0
cts 0
cp 0
rs 10
cc 4
nc 8
nop 2
crap 20
1
<?php
2
3
namespace Zenstruck\Foundry;
4
5
/**
6
 * @author Kevin Bond <[email protected]>
7
 */
8
abstract class Story
9
{
10
    /** @var array<string, Proxy> */
11
    private $objects = [];
12
13 10
    /** @var array<string, Proxy[]> */
14
    private $pools = [];
15 10
16
    final public function __call(string $method, array $arguments)
17
    {
18 24
        return $this->get($method);
19
    }
20 24
21
    final public static function __callStatic($name, $arguments)
22
    {
23
        return static::load()->get($name);
24
    }
25
26 405
    /**
27
     * @return static
28 405
     */
29
    final public static function load(): self
30
    {
31
        return Factory::configuration()->stories()->load(static::class);
32
    }
33
34 398
    /**
35
     * Get a random item from a pool.
36
     */
37 398
    final public static function getRandom(string $pool): Proxy
38 10
    {
39
        return static::getRandomSet($pool, 1)[0];
40
    }
41
42 398
    /**
43 10
     * Get a random set of items from a pool.
44
     *
45
     * @return Proxy[]
46
     */
47 398
    final public static function getRandomSet(string $pool, int $number): array
48 10
    {
49
        if ($number < 1) {
50
            throw new \InvalidArgumentException(\sprintf('$number must be positive (%d given).', $number));
51 398
        }
52
53 398
        return static::getRandomRange($pool, $number, $number);
54
    }
55
56 44
    /**
57
     * Get a random range of items from a pool.
58 44
     *
59 10
     * @return Proxy[]
60
     */
61
    final public static function getRandomRange(string $pool, int $min, int $max): array
62 34
    {
63
        if ($min < 0) {
64
            throw new \InvalidArgumentException(\sprintf('$min must be zero or greater (%d given).', $min));
65
        }
66
67
        if ($max < $min) {
68
            throw new \InvalidArgumentException(\sprintf('$max (%d) cannot be less than $min (%d).', $max, $min));
69
        }
70
71
        $story = static::load();
72
        $values = $story->pools[$pool] ?? [];
73
74
        \shuffle($values);
75
76
        if (\count($values) < $max) {
77
            throw new \RuntimeException(\sprintf('At least %d items must be in pool "%s" (%d items found).', $max, $pool, \count($values)));
78
        }
79
80
        return \array_slice($values, 0, \random_int($min, $max));
81
    }
82
83
    /**
84
     * @param object|Proxy|Factory $object
85
     *
86
     * @return static
87
     */
88
    final public function add(string $name, object $object): self
89
    {
90
        trigger_deprecation('zenstruck\foundry', '1.17.0', 'Using Story::add() is deprecated, use Story::addState().');
91
92
        return $this->addState($name, $object);
93
    }
94
95
    final public function get(string $name): Proxy
96
    {
97
        if (!\array_key_exists($name, $this->objects)) {
98
            throw new \InvalidArgumentException(\sprintf('"%s" was not registered. Did you forget to call "%s::add()"?', $name, static::class));
99
        }
100
101
        return $this->objects[$name];
102
    }
103
104
    abstract public function build(): void;
105
106
    /**
107
     * @param object|Proxy|Factory|object[]|Proxy[]|Factory[]|FactoryCollection $objects
108
     *
109
     * @return static
110
     */
111
    final protected function addToPool(string $pool, $objects): self
112
    {
113
        if ($objects instanceof FactoryCollection) {
114
            $objects = $objects->create();
115
        }
116
117
        if (!\is_array($objects)) {
118
            $objects = [$objects];
119
        }
120
121
        foreach ($objects as $object) {
122
            $this->pools[$pool][] = self::normalizeObject($object);
123
        }
124
125
        return $this;
126
    }
127
128
    /**
129
     * @param object|Proxy|Factory $object
130
     *
131
     * @return static
132
     */
133
    final protected function addState(string $name, object $object, ?string $pool = null): self
134
    {
135
        $proxy = self::normalizeObject($object);
136
137
        $this->objects[$name] = $proxy;
138
139
        if ($pool) {
140
            $this->addToPool($pool, $proxy);
141
        }
142
143
        return $this;
144
    }
145
146
    private static function normalizeObject(object $object): Proxy
147
    {
148
        // ensure factories are persisted
149
        if ($object instanceof Factory) {
150
            $object = $object->create();
151
        }
152
153
        // ensure objects are proxied
154
        if (!$object instanceof Proxy) {
155
            $object = new Proxy($object);
156
        }
157
158
        // ensure proxies are persisted
159
        if (!$object->isPersisted()) {
160
            $object->save();
161
        }
162
163
        return $object;
164
    }
165
}
166