DataTableGateway::create()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 14
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 21
ccs 16
cts 16
cp 1
crap 3
rs 9.7998
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\SatCatalogosPopulate\Database;
6
7
use LogicException;
8
use PDOException;
9
10
class DataTableGateway
11
{
12 20
    public function __construct(private readonly DataTable $dataTable, private readonly Repository $repository)
13
    {
14 20
    }
15
16 16
    public function dataTable(): DataTable
17
    {
18 16
        return $this->dataTable;
19
    }
20
21 17
    public function recreate(): void
22
    {
23 17
        $this->drop();
24 17
        $this->create();
25
    }
26
27 20
    private function sqlDiscoverField(DataFieldInterface $field): string
28
    {
29 20
        if ($field instanceof PreprocessDataField) {
30 1
            return $this->sqlDiscoverField($field->getNextDataField());
31
        }
32 20
        $sqlName = $this->repository->escapeName($field->name());
33 20
        if ($field instanceof TextDataField || $field instanceof DateDataField) {
34 20
            return $sqlName . ' text not null';
35
        }
36 11
        if ($field instanceof IntegerDataField || $field instanceof BoolDataField) {
37 11
            return $sqlName . ' int not null';
38
        }
39
        if ($field instanceof FloatDataField) {
40
            return $sqlName . ' real not null';
41
        }
42
43
        throw new LogicException("Don't know what to do with " . $field::class);
44
    }
45
46 17
    public function drop(): void
47
    {
48 17
        $sql = 'DROP TABLE IF EXISTS ' . $this->repository->escapeName($this->dataTable->name()) . ';';
49 17
        $this->repository->execute($sql);
50
    }
51
52 20
    public function create(): void
53
    {
54 20
        $fields = [];
55 20
        foreach ($this->dataTable->fields() as $field) {
56 20
            $fields[] = $this->sqlDiscoverField($field);
57
        }
58
59 20
        $pkDefinition = '';
60 20
        if (count($this->dataTable->primaryKey()) > 0) {
61 19
            $pkDefinition = 'PRIMARY KEY ('
62 19
                . implode(', ', array_map(
63 19
                    fn (string $input): string => $this->repository->escapeName($input),
64 19
                    $this->dataTable->primaryKey()
65 19
                ))
66 19
                . ')';
67
        }
68
69 20
        $sql = 'CREATE TABLE ' . $this->repository->escapeName($this->dataTable->name())
70 20
            . ' ( ' . implode(', ', array_filter([...$fields, ...[$pkDefinition]])) . ' )'
71 20
            . ';';
72 20
        $this->repository->execute($sql);
73
    }
74
75
    /** @param mixed[] $input */
76 19
    public function insert(array $input): void
77
    {
78 19
        $sql = $this->sqlInsert('INSERT INTO');
79
80
        try {
81 19
            $this->repository->execute($sql, $input);
82 1
        } catch (PDOException $exception) {
83 1
            $message = sprintf('Unable to run %s using %s', $sql, json_encode($input, JSON_THROW_ON_ERROR));
84 1
            throw new PDOException($message, 0, $exception);
85
        }
86
    }
87
88
    /** @param mixed[] $input */
89 1
    public function replace(array $input): void
90
    {
91 1
        $sql = $this->sqlInsert('REPLACE INTO');
92
93
        try {
94 1
            $this->repository->execute($sql, $input);
95
        } catch (PDOException $exception) {
96
            $message = sprintf('Unable to run %s using %s', $sql, json_encode($input, JSON_THROW_ON_ERROR));
97
            throw new PDOException($message, 0, $exception);
98
        }
99
    }
100
101 19
    private function sqlInsert(string $sqlCommand): string
102
    {
103 19
        $fieldNames = [];
104 19
        $preparedNames = [];
105 19
        foreach ($this->dataTable->fields() as $dataField) {
106 19
            $fieldNames[] = $this->repository->escapeName($dataField->name());
107 19
            $preparedNames[] = ':' . $dataField->name();
108
        }
109
110 19
        return $sqlCommand . ' ' . $this->repository->escapeName($this->dataTable->name())
111 19
            . ' (' . implode(', ', $fieldNames) . ')'
112 19
            . ' VALUES (' . implode(', ', $preparedNames) . ')'
113 19
            . ';';
114
    }
115
}
116