Passed
Push — main ( 61a768...edc39f )
by Thierry
16:40 queued 14:46
created

Server::dropDatabase()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 10
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 = rtrim($this->driver->options('directory'), '/\\');
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
        $connection->open($database);
71
        $pageSize = 0;
72
        $statement = $connection->query('pragma page_size');
73
        if (is_a($statement, StatementInterface::class) && ($row = $statement->fetchRow())) {
74
            $pageSize = intval($row[0]);
75
        }
76
        $pageCount = 0;
77
        $statement = $connection->query('pragma page_count');
78
        if (is_a($statement, StatementInterface::class) && ($row = $statement->fetchRow())) {
79
            $pageCount = intval($row[0]);
80
        }
81
        return $pageSize * $pageCount;
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87
    public function databaseCollation(string $database, array $collations)
88
    {
89
        // there is no database list so $database == $this->driver->database()
90
        return $this->driver->result("PRAGMA encoding");
91
    }
92
93
    /**
94
     * @inheritDoc
95
     */
96
    public function collations()
97
    {
98
        $create = $this->util->input()->hasTable();
99
        return ($create) ? $this->driver->values("PRAGMA collation_list", 1) : [];
100
    }
101
102
    /**
103
     * Validate a name
104
     *
105
     * @param string $name
106
     *
107
     * @return bool
108
     */
109
    private function validateName(string $name)
110
    {
111
        // Avoid creating PHP files on unsecured servers
112
        return preg_match("~^[^\\0]*\\.({$this->extensions})\$~", $name) > 0;
113
    }
114
115
    /**
116
     * @inheritDoc
117
     */
118
    public function createDatabase(string $database, string $collation)
119
    {
120
        $options = $this->driver->options();
121
        $filename = $this->filename($database, $options);
122
        if (file_exists($filename)) {
123
            $this->driver->setError($this->trans->lang('File exists.'));
124
            return false;
125
        }
126
        if (!$this->validateName($filename)) {
127
            $this->driver->setError($this->trans->lang('Please use one of the extensions %s.',
128
                str_replace("|", ", ", $this->extensions)));
129
            return false;
130
        }
131
        try {
132
            $connection = $this->driver->createConnection(); // New connection
133
            $connection->open($database);
134
        } catch (Exception $ex) {
135
            $this->driver->setError($ex->getMessage());
136
            return false;
137
        }
138
        $connection->query('PRAGMA encoding = "UTF-8"');
139
        $connection->query('CREATE TABLE adminer (i)'); // otherwise creates empty file
140
        $connection->query('DROP TABLE adminer');
141
        return true;
142
    }
143
144
    /**
145
     * @inheritDoc
146
     */
147
    public function dropDatabase(string $database)
148
    {
149
        $filename = $this->filename($database, $this->driver->options());
150
        if (!@unlink($filename)) {
151
            $this->driver->setError($this->trans->lang('File exists.'));
152
            return false;
153
        }
154
        return true;
155
    }
156
157
    /**
158
     * @inheritDoc
159
     */
160
    public function renameDatabase(string $database, string $collation)
161
    {
162
        $options = $this->driver->options();
163
        $filename = $this->filename($database, $options);
164
        if (!$this->validateName($filename)) {
165
            $this->driver->setError($this->trans->lang('Please use one of the extensions %s.',
166
                str_replace("|", ", ", $this->extensions)));
167
            return false;
168
        }
169
        $this->driver->setError($this->trans->lang('File exists.'));
170
        return @rename($this->filename($this->driver->database(), $options), $filename);
171
    }
172
173
    /**
174
     * @inheritDoc
175
     */
176
    public function variables()
177
    {
178
        $variables = [];
179
        foreach ($this->variableNames as $key) {
180
            $variables[$key] = $this->driver->result("PRAGMA $key");
181
        }
182
        return $variables;
183
    }
184
185
    /**
186
     * @inheritDoc
187
     */
188
    public function statusVariables()
189
    {
190
        $variables = [];
191
        if (!($options = $this->driver->values("PRAGMA compile_options"))) {
192
            return [];
193
        }
194
        foreach ($options as $option) {
195
            $values = explode("=", $option, 2);
196
            $variables[$values[0]] = count($values) > 1 ? $values[1] : "true";
197
        }
198
        return $variables;
199
    }
200
}
201