MySql::quoteQueryStringVariable()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Subreality\Dilmun\Enki;
4
5
use Subreality\Dilmun\LoggedClassTrait;
6
7
/**
8
 * Class MySql
9
 * @package Subreality\Dilmun\Enki
10
 */
11
class MySql implements EnkiInterface
12
{
13
    use LoggedClassTrait;
14
15
    /**
16
     * @var \PDO
17
     */
18
    private $pdo;
19
20
    /**
21
     * Provides a MySQL connection interface that catches a PDOException on failure.
22
     *
23
     * @param string $host  The host name for the MySQL connection
24
     * @param string $user  The username for the MySQL connection
25
     * @param string $pass  The password for the MySQL connection
26
     * @param string $name  The database name for the MySQL connection
27
     *
28
     * @return bool         Returns true if the connection was successful; returns false otherwise
29
     */
30 13
    public function connect($host, $user, $pass, $name)
31
    {
32 13
        $dsn = "mysql:host={$host};dbname={$name}";
33
34
        try {
35 13
            $this->pdo = new \PDO($dsn, $user, $pass);
36 12
            $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
37
38 12
            $connected = true;
39 13
        } catch (\PDOException $pdo_e) {
40 1
            $context = array();
41
42 1
            $context["exception"] = $pdo_e;
43
44 1
            $this->updateLog("error", "MySQL connection failed with the following message: {message}", $context);
45
            
46 1
            $connected = false;
47
        }
48
49 13
        return $connected;
50
    }
51
52
    /**
53
     * Destroys an existing PDO connection
54
     *
55
     * @return bool Returns true if the connection existed and was destroyed; returns false otherwise
56
     */
57 2
    public function disconnect()
58
    {
59 2
        if ($this->pdo instanceof \PDO) {
60 1
            $this->pdo = null;
61
62 1
            $disconnected = true;
63 1
        } else {
64 1
            $disconnected = false;
65
        }
66
67 2
        return $disconnected;
68
    }
69
70
    /**
71
     * Gets the column names for all primary keys for a table or returns false if no keys exist
72
     *
73
     * @param string $table The table from which keys will be retrieved
74
     *
75
     * @return string|false Returns a string of column names representing primary keys;
76
     *                      returns false if the table has no primary keys
77
     */
78 8
    public function getPrimaryKeys($table)
79
    {
80 8
        $keys_query = "SHOW KEYS FROM {$table} WHERE Key_name='PRIMARY'";
81
82 8
        $statement = $this->pdo->prepare($keys_query);
83
84 8
        $result = $this->statementWrapper($statement, "Trying to get keys failed with the following message: ");
85
86 8
        if ($result) {
87 5
            $keys = $this->processPrimaryKeyResult($result);
88 5
        } else {
89 3
            $keys = false;
90
        }
91
92 8
        return $keys;
93
    }
94
95
    /**
96
     * Retrieves a row represented by a single primary key
97
     *
98
     * @param int|string $id    A unique id for a table
99
     * @param string $table     The table from which a row will be retrieved
100
     *
101
     * @return array|false      Returns an associative array representing the row corresponding with the primary key;
102
     *                          returns false if the table does not exist, if the provided id does not correspond with a
103
     *                          record, or if the table has a compound primary key
104
     */
105 5
    public function getRowById($id, $table)
106
    {
107 5
        $id  = $this->quoteQueryStringVariable($id);
108 5
        $key = $this->getPrimaryKeys($table);
109
110 5
        $query = "SELECT * FROM {$table}
111 5
                    WHERE {$key} = {$id}";
112
113 5
        $statement = $this->pdo->prepare($query);
114
115 5
        $result = $this->statementWrapper($statement);
116
117 5
        if (empty($result)) {
118 3
            $row = false;
119 3
        } else {
120 2
            $row = $result[0];
121
        }
122
123 5
        return $row;
124
    }
125
126
    /**
127
     * Determines whether a given table exists
128
     *
129
     * @param string $table The table that will be checked for existence
130
     * @return bool         Returns true if the table exists; returns false otherwise
131
     */
132 2
    public function tableExists($table)
133
    {
134 2
        $table_query = "SHOW TABLES LIKE '{$table}'";
135
136 2
        $statement = $this->pdo->prepare($table_query);
137
138 2
        $statement->execute();
139
140 2
        $row_count = $statement->rowCount();
141
142 2
        if ($row_count == 0) {
0 ignored issues
show
Coding Style introduced by
The if-else statement can be simplified to return !($row_count == 0);.
Loading history...
143 1
            return false;
144
        } else {
145 1
            return true;
146
        }
147
    }
148
149
    /**
150
     * Processes the result set from a primary key query
151
     *
152
     * @see MySql::getPrimaryKeys()
153
     *
154
     * @param array $result An array representing the result of a primary key query
155
     *
156
     * @return string|false Returns a string column name if the result set contains only one primary key;
157
     *                      returns false otherwise
158
     */
159 5
    private function processPrimaryKeyResult($result)
160
    {
161 5
        $row_count = count($result);
162 5
        $this->updateLog("debug", "{$row_count} keys found");
163
164 5
        if ($row_count == 1) {
165 4
            $this->updateLog("debug", "Single key found; setting up key string");
166
167 4
            $keys = $result[0]['Column_name'];
168 4
        } else {
169 1
            $this->updateLog("debug", "No key or multiple keys found; returning false");
170
171 1
            $keys = false;
172
        }
173
174 5
        return $keys;
175
    }
176
177
    /**
178
     * Prepares a variable for a query string by surrounding it with single quotes if it's a string
179
     *
180
     * @param mixed $var    The variable to be assessed for quoting
181
     *
182
     * @return mixed        Returns the single-quoted variable if the variable is a string; returns the variable
183
     *                      otherwise
184
     */
185 5
    private function quoteQueryStringVariable($var)
186
    {
187 5
        if (is_string($var)) {
188 1
            $query_var = "'{$var}'";
189 1
        } else {
190 4
            $query_var = $var;
191
        }
192
193 5
        return $query_var;
194
    }
195
196
    /**
197
     * A wrapper for executing PDOStatement objects that either returns the statement execution result or
198
     * catches any PDOException thrown and updates the class logger with the exception message.
199
     *
200
     * @param \PDOStatement $statement  The statement to be executed
201
     * @param string|null $log_message  OPTIONAL: The message to be logged, in addition to the PDOException message
202
     *
203
     * @return array|false              Returns an associative array of the statement execution result of execution
204
     *                                  was successful; returns false otherwise
205
     */
206 8
    private function statementWrapper(\PDOStatement $statement, $log_message = null)
207
    {
208 8
        if ($log_message === null) {
209 5
            $log_message = "Statement execution error: ";
210 5
        }
211
        
212
        try {
213 8
            $statement->execute();
214 8
        } catch (\PDOException $pdo_e) {
215 3
            $context = array();
216
217 3
            $context["exception"] = $pdo_e;
218
219 3
            $this->updateLog("error", "{$log_message}: {message}", $context);
220
221 3
            return false;
222
        }
223
224 7
        $result = $statement->fetchAll(\PDO::FETCH_ASSOC);
225
        
226 7
        return $result;
227
    }
228
}
229