Server   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 74
dl 0
loc 178
rs 10
c 2
b 0
f 0
wmc 28

10 Methods

Rating   Name   Duplication   Size   Complexity  
A databases() 0 16 4
A statusVariables() 0 11 4
A validateName() 0 4 1
A databaseCollation() 0 4 1
A variables() 0 7 2
A dropDatabase() 0 8 2
A renameDatabase() 0 10 2
A collations() 0 4 2
A databaseSize() 0 17 6
A createDatabase() 0 24 4
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\Sqlite\Db;
4
5
use Lagdo\DbAdmin\Driver\Db\Server as AbstractServer;
6
use Lagdo\DbAdmin\Driver\Db\StatementInterface;
7
8
use DirectoryIterator;
9
use Exception;
10
11
use function is_a;
12
use function count;
13
use function rtrim;
14
use function intval;
15
use function preg_match;
16
use function file_exists;
17
use function str_replace;
18
use function unlink;
19
use function explode;
20
use function rename;
21
22
class Server extends AbstractServer
23
{
24
    use ConfigTrait;
25
26
    /**
27
     * The database file extensions
28
     *
29
     * @var string
30
     */
31
    protected $extensions = "db|sdb|sqlite";
32
33
    /**
34
     * @var array
35
     */
36
    protected $variableNames = ["auto_vacuum", "cache_size", "count_changes", "default_cache_size",
37
        "empty_result_callbacks", "encoding", "foreign_keys", "full_column_names", "fullfsync",
38
        "journal_mode", "journal_size_limit", "legacy_file_format", "locking_mode", "page_size",
39
        "max_page_count", "read_uncommitted", "recursive_triggers", "reverse_unordered_selects",
40
        "secure_delete", "short_column_names", "synchronous", "temp_store", "temp_store_directory",
41
        "schema_version", "integrity_check", "quick_check"];
42
43
    /**
44
     * @inheritDoc
45
     */
46
    public function databases(bool $flush)
47
    {
48
        $databases = [];
49
        $directory = $this->directory($this->driver->options());
50
        $iterator = new DirectoryIterator($directory);
51
        // Iterate on dir content
52
        foreach($iterator as $file)
53
        {
54
            // Skip everything except Sqlite files
55
            if(!$file->isFile() || !$this->validateName($filename = $file->getFilename()))
56
            {
57
                continue;
58
            }
59
            $databases[] = $filename;
60
        }
61
        return $databases;
62
    }
63
64
    /**
65
     * @inheritDoc
66
     */
67
    public function databaseSize(string $database)
68
    {
69
        $connection = $this->driver->createConnection(); // New connection
70
        if (!$connection->open($database)) {
71
            return 0;
72
        }
73
        $pageSize = 0;
74
        $statement = $connection->query('pragma page_size');
75
        if (is_a($statement, StatementInterface::class) && ($row = $statement->fetchRow())) {
76
            $pageSize = intval($row[0]);
77
        }
78
        $pageCount = 0;
79
        $statement = $connection->query('pragma page_count');
80
        if (is_a($statement, StatementInterface::class) && ($row = $statement->fetchRow())) {
81
            $pageCount = intval($row[0]);
82
        }
83
        return $pageSize * $pageCount;
84
    }
85
86
    /**
87
     * @inheritDoc
88
     */
89
    public function databaseCollation(string $database, array $collations)
90
    {
91
        // there is no database list so $database == $this->driver->database()
92
        return $this->driver->result("PRAGMA encoding");
93
    }
94
95
    /**
96
     * @inheritDoc
97
     */
98
    public function collations()
99
    {
100
        $create = $this->util->input()->hasTable();
101
        return ($create) ? $this->driver->values("PRAGMA collation_list", 1) : [];
102
    }
103
104
    /**
105
     * Validate a name
106
     *
107
     * @param string $name
108
     *
109
     * @return bool
110
     */
111
    private function validateName(string $name)
112
    {
113
        // Avoid creating PHP files on unsecured servers
114
        return preg_match("~^[^\\0]*\\.({$this->extensions})\$~", $name) > 0;
115
    }
116
117
    /**
118
     * @inheritDoc
119
     */
120
    public function createDatabase(string $database, string $collation)
121
    {
122
        $options = $this->driver->options();
123
        if ($this->fileExists($database, $options)) {
124
            $this->driver->setError($this->trans->lang('File exists.'));
125
            return false;
126
        }
127
        $filename = $this->filename($database, $options);
128
        if (!$this->validateName($filename)) {
129
            $this->driver->setError($this->trans->lang('Please use one of the extensions %s.',
130
                str_replace("|", ", ", $this->extensions)));
131
            return false;
132
        }
133
        try {
134
            $connection = $this->driver->createConnection(); // New connection
135
            $connection->open($database, '__create__');
136
            $connection->query('PRAGMA encoding = "UTF-8"');
137
            $connection->query('CREATE TABLE dbadmin (i)'); // otherwise creates empty file
138
            $connection->query('DROP TABLE dbadmin');
139
        } catch (Exception $ex) {
140
            $this->driver->setError($ex->getMessage());
141
            return false;
142
        }
143
        return true;
144
    }
145
146
    /**
147
     * @inheritDoc
148
     */
149
    public function dropDatabase(string $database)
150
    {
151
        $filename = $this->filename($database, $this->driver->options());
152
        if (!@unlink($filename)) {
153
            $this->driver->setError($this->trans->lang('File exists.'));
154
            return false;
155
        }
156
        return true;
157
    }
158
159
    /**
160
     * @inheritDoc
161
     */
162
    public function renameDatabase(string $database, string $collation)
163
    {
164
        $options = $this->driver->options();
165
        $filename = $this->filename($database, $options);
166
        if (!$this->validateName($filename)) {
167
            $this->driver->setError($this->trans->lang('Please use one of the extensions %s.',
168
                str_replace("|", ", ", $this->extensions)));
169
            return false;
170
        }
171
        return @rename($this->filename($this->driver->database(), $options), $filename);
172
    }
173
174
    /**
175
     * @inheritDoc
176
     */
177
    public function variables()
178
    {
179
        $variables = [];
180
        foreach ($this->variableNames as $key) {
181
            $variables[$key] = $this->driver->result("PRAGMA $key");
182
        }
183
        return $variables;
184
    }
185
186
    /**
187
     * @inheritDoc
188
     */
189
    public function statusVariables()
190
    {
191
        $variables = [];
192
        if (!($options = $this->driver->values("PRAGMA compile_options"))) {
193
            return [];
194
        }
195
        foreach ($options as $option) {
196
            $values = explode("=", $option, 2);
197
            $variables[$values[0]] = count($values) > 1 ? $values[1] : "true";
198
        }
199
        return $variables;
200
    }
201
}
202