PrimaryKeyRegistry::__construct()   B
last analyzed

Complexity

Conditions 7
Paths 9

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 22
rs 8.8333
c 0
b 0
f 0
cc 7
nc 9
nop 4
1
<?php
2
namespace DBFaker\Helpers;
3
4
use DBFaker\Exceptions\PrimaryKeyColumnMismatchException;
5
use DBFaker\Exceptions\SchemaLogicException;
6
use Doctrine\DBAL\Connection;
7
use Doctrine\DBAL\Schema\Column;
8
use Doctrine\DBAL\Schema\Table;
9
10
class PrimaryKeyRegistry
11
{
12
13
    /**
14
     * @var string
15
     */
16
    private $tableName;
17
18
    /**
19
     * @var string[]
20
     */
21
    private $columnNames;
22
23
    /**
24
     * @var Connection
25
     */
26
    private $connection;
27
28
    /**
29
     * @var array
30
     */
31
    private $values;
32
33
    /**
34
     * @var bool
35
     */
36
    private $valuesLoaded = false;
37
38
    /**
39
     * PrimaryKeyRegistry constructor.
40
     * @param Connection $connection
41
     * @param Table $table
42
     * @param SchemaHelper $helper
43
     * @param bool $isSelfReferencing
44
     * @throws \Doctrine\DBAL\DBALException
45
     */
46
    public function __construct(Connection $connection, Table $table, SchemaHelper $helper, bool $isSelfReferencing = false)
47
    {
48
        $this->connection = $connection;
49
        $refTable = null;
50
        $refCols = [];
51
        foreach ($table->getForeignKeys() as $fk) {
52
            if ($helper->isExtendingKey($fk) && $table->getName() !== $fk->getForeignTableName()) {
53
                $refTable = $fk->getForeignTableName();
54
                $refCols = $fk->getForeignColumns();
55
            }
56
        }
57
        if ($isSelfReferencing || !$refTable) {
58
            $pk = $table->getPrimaryKey();
59
            if ($pk === null) {
60
                throw new SchemaLogicException('No PK on table ' . $table->getName());
61
            }
62
            $refTable = $table->getName();
63
            $refCols = $pk->getColumns();
64
        }
65
        $this->tableName = $refTable;
66
        $this->columnNames = $refCols;
67
        sort($this->columnNames);
68
    }
69
70
    /**
71
     * Loads all PK values fro ma table and stores them
72
     * @throws \Doctrine\DBAL\DBALException
73
     */
74
    public function loadValuesFromTable() : PrimaryKeyRegistry
75
    {
76
        if (!$this->valuesLoaded) {
77
            $this->values = [];
78
            $colNames = implode(",", $this->columnNames);
79
            $rows = $this->connection->query("SELECT $colNames FROM " . $this->tableName)->fetchAll();
80
            foreach ($rows as $row) {
81
                $pk = [];
82
                foreach ($this->columnNames as $column) {
83
                    $pk[$column] = $row[$column];
84
                }
85
                $this->values[] = $pk;
86
            }
87
        }
88
        return $this;
89
    }
90
91
    /**
92
     * Adds a PK value to the store
93
     * @param mixed[] $value
94
     * @throws \DBFaker\Exceptions\PrimaryKeyColumnMismatchException
95
     */
96
    public function addValue(array $value) : void
97
    {
98
        $keys = array_keys($value);
99
        sort($keys);
100
        if ($this->columnNames != $keys) {
101
            throw new PrimaryKeyColumnMismatchException('PrimaryKeys do not match between PKStore and addValue');
102
        }
103
        $this->values[] = $value;
104
    }
105
106
    /**
107
     * @param mixed[] $excludedValues
108
     * @return mixed[]
109
     * @throws \Exception
110
     */
111
    public function getRandomValue(array $excludedValues) : array
112
    {
113
        $values = array_filter($this->values, function ($value) use ($excludedValues) {
114
            return !\in_array($value, $excludedValues, true);
115
        });
116
        return $values[array_rand($values, 1)];
117
    }
118
119
    /**
120
     * @return mixed[][]
121
     */
122
    public function getAllValues() : array
123
    {
124
        return $this->values;
125
    }
126
}
127