packages/sql-fixture/src/Fixture/TableOverrides.php

1<?php
2
3declare(strict_types=1);
4
5namespace SqlFixture\Fixture;
6
7/**
8 * Column values to use instead of generated ones, for one table.
9 *
10 * Generated table classes build these through named arguments, so the column
11 * names and their types are checked where they are written rather than when
12 * the fixture runs. A null argument means "leave this column to the
13 * generator"; withNull() is how a column is deliberately set to NULL.
14 * @template TValue = mixed
15 */
16final class TableOverrides
17{
18    /**
19     * @param array<string, TValue> $values
20     * @param array<array-key, string> $nulls Columns to set to NULL rather than generate
21     */
22    public function __construct(
23        private readonly array $values,
24        private readonly array $nulls,
25    ) {
26    }
27
28    /**
29     * Keep only the arguments that were actually given.
30     *
31     * @template TColumn
32     * @param array<string, TColumn> $values
33     * @return self<TColumn>
34     */
35    public static function of(array $values = []): self
36    {
37        $provided = [];
38        foreach ($values as $column => $value) {
39            if ($value !== null) {
40                $provided[$column] = $value;
41            }
42        }
43
44        return new self($provided, []);
45    }
46
47    /**
48     * Set a column to NULL rather than leaving it to the generator.
49     *
50     * @return self<TValue>
51     */
52    public function withNull(string ...$columns): self
53    {
54        return new self($this->values, [...$this->nulls, ...$columns]);
55    }
56
57    /**
58     * @return array<string, TValue|null>
59     */
60    public function toArray(): array
61    {
62        $values = $this->values;
63
64        foreach ($this->nulls as $column) {
65            $values[$column] = null;
66        }
67
68        return $values;
69    }
70}
71