Database::__construct()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
c 0
b 0
f 0
dl 0
loc 25
rs 9.7
cc 3
nc 2
nop 1
1
<?php
2
3
/* Copyright (C) 2024      Rafael San José      <[email protected]>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace Alxarafe\Base;
20
21
use Alxarafe\Lib\Messages;
22
use Alxarafe\Lib\Trans;
23
use Alxarafe\Tools\Debug;
24
use DebugBar\DataCollector\PDO\PDOCollector;
25
use DebugBar\DebugBarException;
26
use Illuminate\Database\Capsule\Manager as CapsuleManager;
27
use PDO;
28
use PDOException;
29
use stdClass;
30
31
/**
32
 * Create a PDO database connection
33
 *
34
 * @package Alxarafe\Base
35
 */
36
class Database extends CapsuleManager
37
{
38
    /**
39
     * Construct the database access
40
     *
41
     * @param stdClass $db
42
     *
43
     * @throws DebugBarException
44
     */
45
    public function __construct(stdClass $db)
46
    {
47
        parent::__construct();
48
49
        $this->addConnection([
50
            'driver' => $db->type,
51
            'host' => $db->host,
52
            'database' => $db->name,
53
            'username' => $db->user,
54
            'password' => $db->pass,
55
            'charset' => $db->charset,
56
            'collation' => $db->collation,
57
            'prefix' => $db->prefix,
58
        ]);
59
60
        $this->setAsGlobal();
61
        $this->bootEloquent();
62
63
        $debugBar = Debug::getDebugBar();
64
        if (!isset($debugBar) || $debugBar->hasCollector('pdo')) {
65
            return;
66
        }
67
68
        $pdo = $this->getConnection()->getPdo();
69
        $debugBar->addCollector(new PDOCollector($pdo));
70
    }
71
72
    public static function getDbDrivers(): array
73
    {
74
        return [
75
            'mysql' => 'MySQL',
76
            'pgsql' => 'PostgreSQL',
77
        ];
78
    }
79
80
    /**
81
     * Checks if the connection to the database is possible with the parameters
82
     * defined in the configuration file.
83
     *
84
     * @param stdClass $data
85
     * @param bool $create
86
     * @return bool
87
     */
88
    public static function checkDatabaseConnection(stdClass $data, bool $create = false): bool
89
    {
90
        if (!static::checkIfDatabaseExists($data, true)) {
91
            if (!$create) {
92
                return false;
93
            }
94
            if (!static::createDatabaseIfNotExists($data, true)) {
0 ignored issues
show
Unused Code introduced by
The call to Alxarafe\Base\Database::...teDatabaseIfNotExists() has too many arguments starting with true. ( Ignorable by Annotation )

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

94
            if (!static::/** @scrutinizer ignore-call */ createDatabaseIfNotExists($data, true)) {

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...
95
                return false;
96
            }
97
        }
98
        return true;
99
    }
100
101
    /**
102
     * Returns true if the database already exists.
103
     *
104
     * @param stdClass $data
105
     * @return bool
106
     */
107
    public static function checkIfDatabaseExists(stdClass $data, bool $quiet = false): bool
108
    {
109
        if (!static::checkConnection($data, true)) {
110
            return false;
111
        }
112
113
        $dsn = "$data->type:host=$data->host;dbname=$data->name;charset=$data->charset";
114
        try {
115
            new PDO($dsn, $data->user, $data->pass);
116
        } catch (PDOException $e) {
117
            if (!$quiet) {
118
                Messages::addError(Trans::_('error_message', ['message' => $e->getMessage()]));
119
            }
120
            return false;
121
        }
122
        return true;
123
    }
124
125
    /**
126
     * Checks if there is a connection to the database engine.
127
     *
128
     * @param stdClass $data
129
     * @param bool $quiet
130
     * @return bool
131
     */
132
    public static function checkConnection(stdClass $data, bool $quiet = false): bool
133
    {
134
        $dsn = "$data->type:host=$data->host";
135
        try {
136
            new PDO($dsn, $data->user, $data->pass);
137
        } catch (PDOException $e) {
138
            if (!$quiet) {
139
                Messages::addError(Trans::_('error_message', ['message' => $e->getMessage()]));
140
            }
141
            return false;
142
        }
143
        return true;
144
    }
145
146
    /**
147
     * Creates the database if it does not exist. Returns true if the creation succeeds.
148
     *
149
     * @param stdClass $data
150
     * @return bool
151
     */
152
    public static function createDatabaseIfNotExists(stdClass $data): bool
153
    {
154
        if (static::checkIfDatabaseExists($data, true)) {
155
            return true;
156
        }
157
158
        $dsn = "$data->type:host=$data->host";
159
        try {
160
            $pdo = new PDO($dsn, $data->user, $data->pass);
161
            $pdo->exec('CREATE DATABASE ' . $data->name);
162
            return true;
163
        } catch (PDOException $e) {
164
            Messages::addError($e->getMessage());
165
            Messages::addError(Trans::_('pdo_fail_db_creation', ['message' => $e->getMessage()]));
166
            return false;
167
        }
168
    }
169
}
170