Passed
Branch dev (f56f10)
by Wilmer
04:41 queued 01:34
created

Quoter::quoteSimpleColumnName()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 8
nop 1
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Schema;
6
7
use function addcslashes;
8
use function explode;
9
use function implode;
10
use function is_string;
11
use function preg_replace_callback;
12
use function str_contains;
13
use function str_replace;
14
use function str_starts_with;
15
use function strlen;
16
use function strpos;
17
use function strrpos;
18
use function substr;
19
20
class Quoter implements QuoterInterface
21
{
22
    public function __construct(
23
        private array|string $columnQuoteCharacter,
24
        private array|string $tableQuoteCharacter,
25
        private string $tablePrefix = ''
26
    ) {
27
    }
28
29
    public function quoteColumnName(string $name): string
30
    {
31
        if (str_contains($name, '(') || str_contains($name, '[[')) {
32
            return $name;
33
        }
34
35
        if (($pos = strrpos($name, '.')) !== false) {
36
            $prefix = $this->quoteTableName(substr($name, 0, $pos)) . '.';
37
            $name = substr($name, $pos + 1);
38
        } else {
39
            $prefix = '';
40
        }
41
42
        if (str_contains($name, '{{')) {
43
            return $name;
44
        }
45
46
        return $prefix . $this->quoteSimpleColumnName($name);
47
    }
48
49
    public function quoteSimpleColumnName(string $name): string
50
    {
51
        if (is_string($this->columnQuoteCharacter)) {
52
            $startingCharacter = $endingCharacter = $this->columnQuoteCharacter;
53
        } else {
54
            [$startingCharacter, $endingCharacter] = $this->columnQuoteCharacter;
55
        }
56
57
        return $name === '*' || str_contains($name, $startingCharacter) ? $name : $startingCharacter . $name
58
            . $endingCharacter;
59
    }
60
61
    public function quoteSimpleTableName(string $name): string
62
    {
63
        if (is_string($this->tableQuoteCharacter)) {
64
            $startingCharacter = $endingCharacter = $this->tableQuoteCharacter;
65
        } else {
66
            [$startingCharacter, $endingCharacter] = $this->tableQuoteCharacter;
67
        }
68
69
        return str_contains($name, $startingCharacter) ? $name : $startingCharacter . $name . $endingCharacter;
70
    }
71
72
    public function quoteSql(string $sql): string
73
    {
74
        return preg_replace_callback(
75
            '/({{(%?[\w\-. ]+%?)}}|\\[\\[([\w\-. ]+)]])/',
76
            function ($matches) {
77
                if (isset($matches[3])) {
78
                    return $this->quoteColumnName($matches[3]);
79
                }
80
81
                return str_replace('%', $this->tablePrefix, $this->quoteTableName($matches[2]));
82
            },
83
            $sql
84
        );
85
    }
86
87
    public function quoteTableName(string $name): string
88
    {
89
        if (str_starts_with($name, '(') && strpos($name, ')') === strlen($name) - 1) {
90
            return $name;
91
        }
92
93
        if (str_contains($name, '{{')) {
94
            return $name;
95
        }
96
97
        if (!str_contains($name, '.')) {
98
            return $this->quoteSimpleTableName($name);
99
        }
100
101
        $parts = $this->getTableNameParts($name);
102
103
        foreach ($parts as $i => $part) {
104
            $parts[$i] = $this->quoteSimpleTableName($part);
105
        }
106
107
        return implode('.', $parts);
108
    }
109
110
    public function quoteValue(int|string $value): int|string
111
    {
112
        if (!is_string($value)) {
113
            return $value;
114
        }
115
116
        return '\'' . str_replace('\'', '\'\'', addcslashes($value, "\000\032")) . '\'';
117
    }
118
119
    public function unquoteSimpleColumnName(string $name): string
120
    {
121
        if (is_string($this->columnQuoteCharacter)) {
122
            $startingCharacter = $this->columnQuoteCharacter;
123
        } else {
124
            $startingCharacter = $this->columnQuoteCharacter[0];
125
        }
126
127
        return !str_contains($name, $startingCharacter) ? $name : substr($name, 1, -1);
128
    }
129
130
    public function unquoteSimpleTableName(string $name): string
131
    {
132
        if (is_string($this->tableQuoteCharacter)) {
133
            $startingCharacter = $this->tableQuoteCharacter;
134
        } else {
135
            $startingCharacter = $this->tableQuoteCharacter[0];
136
        }
137
138
        return !str_contains($name, $startingCharacter) ? $name : substr($name, 1, -1);
139
    }
140
141
    /**
142
     * Splits full table name into parts
143
     *
144
     * @param string $name
145
     *
146
     * @return array
147
     */
148
    protected function getTableNameParts(string $name): array
149
    {
150
        return explode('.', $name);
151
    }
152
}
153