Passed
Push — main ( 9d4bb7...8f881d )
by Thierry
11:37 queued 09:25
created

Driver::initConnection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 11
rs 10
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\PgSql;
4
5
use Lagdo\DbAdmin\Driver\Exception\AuthException;
6
use Lagdo\DbAdmin\Driver\Driver as AbstractDriver;
7
use Lagdo\DbAdmin\Driver\Db\Connection as AbstractConnection;
8
9
class Driver extends AbstractDriver
10
{
11
    /**
12
     * Driver features
13
     *
14
     * @var array
15
     */
16
    private $features = ['database', 'table', 'columns', 'sql', 'indexes', 'descidx',
17
        'comment', 'view', 'scheme', 'routine', 'processlist', 'sequence', 'trigger',
18
        'type', 'variables', 'drop_col', 'kill', 'dump', 'fkeys_sql'];
19
20
    /**
21
     * Data types
22
     *
23
     * @var array
24
     */
25
    private $types = [ //! arrays
26
        'Numbers' => ["smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1,
27
            "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20],
28
        'Date and time' => ["date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0],
29
        'Strings' => ["character" => 0, "character varying" => 0, "text" => 0,
30
            "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0],
31
        'Binary' => ["bit" => 0, "bit varying" => 0, "bytea" => 0],
32
        'Network' => ["cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0],
33
        'Geometry' => ["box" => 0, "circle" => 0, "line" => 0, "lseg" => 0,
34
            "path" => 0, "point" => 0, "polygon" => 0],
35
    ];
36
37
    /**
38
     * Number variants
39
     *
40
     * @var array
41
     */
42
    // private $unsigned = [];
43
44
    /**
45
     * Operators used in select
46
     *
47
     * @var array
48
     */
49
    private $operators = ["=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE",
50
        "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"]; // no "SQL" to avoid CSRF
51
52
    /**
53
     * Functions used in select
54
     *
55
     * @var array
56
     */
57
    private $functions = ["char_length", "lower", "round", "to_hex", "to_timestamp", "upper"];
58
59
    /**
60
     * Grouping functions used in select
61
     *
62
     * @var array
63
     */
64
    private $grouping = ["avg", "count", "count distinct", "max", "min", "sum"];
65
66
    /**
67
     * Functions used to edit data
68
     *
69
     * @var array
70
     */
71
    private $editFunctions = [[
72
        "char" => "md5",
73
        "date|time" => "now",
74
    ],[
75
        // $this->numberRegex() => "+/-",
76
        "date|time" => "+ interval/- interval", //! escape
77
        "char|text" => "||",
78
    ]];
79
80
    /**
81
     * @inheritDoc
82
     */
83
    public function name()
84
    {
85
        return "PostgreSQL";
86
    }
87
88
    /**
89
     * Initialize a new connection
90
     *
91
     * @param AbstractConnection $connection
92
     *
93
     * @return AbstractConnection
94
     */
95
    private function initConnection(AbstractConnection $connection)
96
    {
97
        if ($this->connection === null) {
98
            $this->connection = $connection;
99
            $this->server = new Db\Server($this, $this->util, $this->trans);
100
            $this->database = new Db\Database($this, $this->util, $this->trans);
101
            $this->table = new Db\Table($this, $this->util, $this->trans);
102
            $this->query = new Db\Query($this, $this->util, $this->trans);
103
            $this->grammar = new Db\Grammar($this, $this->util, $this->trans);
104
        }
105
        return $connection;
106
    }
107
108
    /**
109
     * @inheritDoc
110
     * @throws AuthException
111
     */
112
    public function createConnection()
113
    {
114
        if (!$this->options('prefer_pdo', false) && extension_loaded("pgsql")) {
0 ignored issues
show
Unused Code introduced by
The call to Lagdo\DbAdmin\Driver\Driver::options() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

114
        if (!$this->/** @scrutinizer ignore-call */ options('prefer_pdo', false) && extension_loaded("pgsql")) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
115
            $connection = new Db\PgSql\Connection($this, $this->util, $this->trans, 'PgSQL');
116
            return $this->initConnection($connection);
117
        }
118
        if (extension_loaded("pdo_pgsql")) {
119
            $connection = new Db\Pdo\Connection($this, $this->util, $this->trans, 'PDO_PgSQL');
120
            return $this->initConnection($connection);
121
        }
122
        throw new AuthException($this->trans->lang('No package installed to connect to a PostgreSQL server.'));
123
    }
124
125
    /**
126
     * @inheritDoc
127
     */
128
    public function connect(string $database, string $schema)
129
    {
130
        parent::connect($database, $schema);
131
132
        if ($this->minVersion(9.3)) {
133
            $this->features[] = 'materializedview';
134
        }
135
136
        if ($this->minVersion(9.2)) {
137
            $this->config->structuredTypes[$this->trans->lang('Strings')][] = "json";
138
            $this->config->types["json"] = 4294967295;
139
            if ($this->minVersion(9.4)) {
140
                $this->config->structuredTypes[$this->trans->lang('Strings')][] = "jsonb";
141
                $this->config->types["jsonb"] = 4294967295;
142
            }
143
        }
144
145
        foreach ($this->userTypes() as $type) { //! get types from current_schemas('t')
146
            if (!isset($this->config->types[$type])) {
147
                $this->config->types[$type] = 0;
148
                $this->config->structuredTypes[$this->trans->lang('User types')][] = $type;
149
            }
150
        }
151
    }
152
153
    /**
154
     * @inheritDoc
155
     */
156
    public function support(string $feature)
157
    {
158
        return in_array($feature, $this->features);
159
    }
160
161
    /**
162
     * @inheritDoc
163
     */
164
    protected function initConfig()
165
    {
166
        $this->config->jush = 'pgsql';
167
        $this->config->drivers = ["PgSQL", "PDO_PgSQL"];
168
        $this->config->setTypes($this->types, $this->trans);
169
        // $this->config->unsigned = [];
170
        $this->config->operators = $this->operators;
171
        $this->config->functions = $this->functions;
172
        $this->config->grouping = $this->grouping;
173
        $this->config->editFunctions = $this->editFunctions;
174
        $this->config->editFunctions[1][$this->numberRegex()] = "+/-";
175
    }
176
177
    /**
178
     * @inheritDoc
179
     */
180
    public function error()
181
    {
182
        $message = parent::error();
183
        if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $message, $match)) {
184
            $match = array_pad($match, 5, '');
185
            $message = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' .
186
                strlen($match[3]) . '})(.*)~', '\1<b>\2</b>', $match[2]) . $match[4];
187
        }
188
        return $message;
189
    }
190
}
191