Passed
Push — master ( b97c32...e7e450 )
by Carlos C
10:36 queued 12s
created

Repository   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Test Coverage

Coverage 86.36%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 37
c 4
b 1
f 0
dl 0
loc 109
ccs 38
cts 44
cp 0.8636
rs 10
wmc 18

11 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 6 2
A queryArray() 0 13 3
A __construct() 0 8 2
A pdo() 0 3 1
A hasTable() 0 4 1
A queryRow() 0 12 3
A getRecordCount() 0 4 1
A escapeName() 0 3 1
A convertScalarNullToStringArray() 0 5 1
A queryOne() 0 5 1
A convertScalarNullToStringValue() 0 3 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\SatCatalogosPopulate\Database;
6
7
use PDO;
8
use PDOException;
9
use RuntimeException;
10
11
class Repository
12
{
13
    private PDO $pdo;
14
15 13
    public function __construct(string $dbfile)
16
    {
17 13
        if (':memory:' !== $dbfile) {
18
            // TODO: validate other sources ?
19
            $dbfile = '//' . $dbfile;
20
        }
21 13
        $this->pdo = new PDO('sqlite:' . $dbfile, '', '', [
22
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
23
        ]);
24
    }
25
26 1
    public function pdo(): PDO
27
    {
28 1
        return $this->pdo;
29
    }
30
31 6
    public function hasTable(string $table): bool
32
    {
33 6
        $sql = 'SELECT count(*) FROM sqlite_master WHERE type = :type AND name = :table;';
34 6
        return (1 === (int) $this->queryOne($sql, ['type' => 'table', 'table' => $table]));
35
    }
36
37 4
    public function getRecordCount(string $table): int
38
    {
39 4
        $sql = 'SELECT count(*) FROM ' . $this->escapeName($table) . ';';
40 4
        return (int) $this->queryOne($sql);
41
    }
42
43
    /**
44
     * @param mixed[] $values
45
     */
46 13
    public function execute(string $sql, array $values = []): void
47
    {
48 13
        $stmt = $this->pdo->prepare($sql);
49 13
        if (false === $stmt->execute($values)) {
50
            $errorInfo = $stmt->errorInfo();
51
            throw new PDOException(sprintf('[%s] %s', $errorInfo[1] ?? 'UNDEF', $errorInfo[2] ?? 'Unknown error'));
52
        }
53
    }
54
55
    /**
56
     * @param mixed[] $values
57
     * @return array<int, array<string, string|null>>
58
     */
59 1
    public function queryArray(string $sql, array $values = []): array
60
    {
61 1
        $stmt = $this->pdo->prepare($sql);
62 1
        if (false === $stmt->execute($values)) {
63
            throw new RuntimeException("Unable to execute $sql");
64
        }
65 1
        $table = [];
66 1
        while (false !== $row = $stmt->fetch(PDO::FETCH_ASSOC)) {
67
            /** @var array<string, scalar|null> $row */
68 1
            $table[] = $this->convertScalarNullToStringArray($row);
69
        }
70
71 1
        return $table;
72
    }
73
74
    /**
75
     * @param mixed[] $values
76
     * @return array<string, string|null>
77
     */
78 4
    public function queryRow(string $sql, array $values = []): array
79
    {
80 4
        $stmt = $this->pdo->prepare($sql);
81 4
        if (false === $stmt->execute($values)) {
82
            throw new RuntimeException("Unable to execute $sql");
83
        }
84
        /** @var false|array<string, scalar|null> $row */
85 4
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
86 4
        if (! is_array($row)) {
87
            return [];
88
        }
89 4
        return $this->convertScalarNullToStringArray($row);
90
    }
91
92
    /** @param array<string, scalar|null> $values */
93 9
    public function queryOne(string $sql, array $values = []): ?string
94
    {
95 9
        $stmt = $this->pdo->prepare($sql);
96 9
        $stmt->execute($values);
97 9
        return $this->convertScalarNullToStringValue($stmt->fetchColumn(0));
98
    }
99
100 13
    public function escapeName(string $name): string
101
    {
102 13
        return '"' . str_replace('"', '""', $name) . '"';
103
    }
104
105
    /** @param scalar|null $value */
106 12
    private function convertScalarNullToStringValue($value): ?string
107
    {
108 12
        return (null === $value) ? null : (string) $value;
109
    }
110
111
    /**
112
     * @param array<scalar|null> $values
113
     * @return array<string|null>
114
     */
115 4
    private function convertScalarNullToStringArray(array $values): array
116
    {
117 4
        return array_map(
118 4
            fn ($value) => $this->convertScalarNullToStringValue($value),
119
            $values
120
        );
121
    }
122
}
123