Passed
Push — master ( 060059...890940 )
by Radu
01:20
created

AbstractPdoDatabase::validateParam()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
namespace WebServCo\Framework\Database;
3
4
use WebServCo\Framework\Exceptions\DatabaseException;
5
6
abstract class AbstractPdoDatabase extends AbstractDatabase
7
{
8
    use \WebServCo\Framework\Traits\DatabaseTrait;
9
    use \WebServCo\Framework\Traits\DatabaseAddQueryTrait;
10
11
    abstract protected function getDataSourceName($host, $port, $dbname);
12
13
    public function __construct($settings = [])
14
    {
15
        parent::__construct($settings);
16
17
        try {
18
            $dsn = $this->getDataSourceName(
19
                $this->setting('connection/host', '127.0.0.1'),
20
                $this->setting('connection/port', null),
21
                $this->setting('connection/dbname', 'test')
22
            );
23
            $this->db = new \PDO(
24
                $dsn,
25
                $this->setting('connection/username', 'root'),
26
                $this->setting('connection/passwd', ''),
27
                [
28
                    \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
29
                    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
30
                    \PDO::ATTR_EMULATE_PREPARES => false,
31
                    \PDO::ATTR_PERSISTENT => false
32
                ]
33
            );
34
        } catch (\Exception $e) { // PDOException/RuntimeException/Exception
35
            throw new DatabaseException($e->getMessage());
36
        }
37
    }
38
39
    public function escape($string)
40
    {
41
        return $this->db->quote($string);
42
    }
43
44
    public function query($query, $params = [])
45
    {
46
        if (empty($query)) {
47
            throw new DatabaseException('No query specified');
48
        }
49
50
        try {
51
            if (!empty($params)) {
52
                $this->stmt = $this->db->prepare($query);
53
                $this->bindParams($params);
54
                $this->stmt->execute();
55
            } else {
56
                $this->stmt = $this->db->query($query);
57
            }
58
            $this->setLastInsertId();
59
            return $this->stmt;
60
        } catch (\PDOException $e) {
61
            throw new DatabaseException($e->getMessage(), $e);
62
        } catch (\RuntimeException $e) {
63
            throw new DatabaseException($e->getMessage(), $e);
64
        }
65
    }
66
67
    public function transaction($queries)
68
    {
69
        try {
70
            $this->db->beginTransaction();
71
            foreach ($queries as $item) {
72
                if (!isset($item[0])) {
73
                    throw new DatabaseException('No query specified');
74
                }
75
                $params = isset($item[1]) ? $item[1] : [];
76
                $this->query($item[0], $params);
77
            }
78
            $this->db->commit();
79
            return true;
80
        } catch (\Exception $e) { //PDOException/RuntimeException/Exception
81
            $this->db->rollBack();
82
            throw new DatabaseException($e->getMessage());
83
        }
84
    }
85
86
    public function numRows()
87
    {
88
        if (!($this->stmt instanceof \PDOStatement)) {
89
            throw new DatabaseException('No Statement object available.');
90
        }
91
        if ('mysql' == $this->setting('driver')) {
92
            return $this->stmt->rowCount();
93
        }
94
        $rows = $this->rows ?: $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
95
        return count($rows);
96
    }
97
98
    public function affectedRows()
99
    {
100
        if (!($this->stmt instanceof \PDOStatement)) {
101
            throw new DatabaseException('No Statement object available.');
102
        }
103
        return $this->stmt->rowCount();
104
    }
105
106
    public function getRows($query, $params = [])
107
    {
108
        $this->query($query, $params);
109
        $this->rows = $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
110
        return $this->rows;
111
    }
112
113
    public function getRow($query, $params = [])
114
    {
115
        $this->query($query, $params);
116
        return $this->stmt->fetch(\PDO::FETCH_ASSOC);
117
    }
118
119
    public function getColumn($query, $params = [], $columnNumber = 0)
120
    {
121
        $this->query($query, $params);
122
        return $this->stmt->fetchColumn($columnNumber);
123
    }
124
125
    protected function bindParams($data)
126
    {
127
        if (empty($data)) {
128
            return false;
129
        }
130
131
        if (!is_array($data)) {
132
            throw new DatabaseException('"Parameters" is not an array.');
133
        }
134
135
        $i = 1;
136
        foreach ($data as $item) {
137
            if (is_array($item)) {
138
                foreach ($item as $v) {
139
                    $this->validateParam($v);
140
                    $this->stmt->bindValue($i, $v, $this->getDataType($v));
141
                    $i++;
142
                }
143
            } else {
144
                $this->validateParam($item);
145
                $this->stmt->bindValue($i, $item, $this->getDataType($item));
146
                $i++;
147
            }
148
        }
149
        return true;
150
    }
151
152
    protected function validateParam($param)
153
    {
154
        if (is_array($param)) {
155
            throw new DatabaseException('Parameter is an array.');
156
        }
157
        return true;
158
    }
159
160
    protected function getDataType($variable)
161
    {
162
        $type = gettype($variable);
163
164
        switch ($type) {
165
            case 'NULL':
166
                return \PDO::PARAM_NULL;
167
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
168
            case 'integer':
169
                return \PDO::PARAM_INT;
170
                break;
171
            case 'boolean':
172
                // casuses data not to be inserted
173
                //return \PDO::PARAM_BOOL;
174
                //break;
175
            case 'string':
176
            case 'double':
177
            case 'array':
178
            case 'object':
179
            case 'resource':
180
            case 'resource (closed)':
181
            case 'unknown type':
182
            default:
183
                return \PDO::PARAM_STR;
184
                break;
185
        }
186
    }
187
188
    protected function setLastInsertId()
189
    {
190
        $this->lastInsertId = $this->db->lastInsertId();
191
    }
192
}
193