Test Failed
Push — master ( d5f951...5b0d59 )
by Gabor
08:43
created

SqlQueryAdapter::fetchData()   C

Complexity

Conditions 7
Paths 17

Size

Total Lines 50
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 28
nc 17
nop 2
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 7.1
6
 *
7
 * @copyright 2012 - 2018 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link http://www.gixx-web.com
11
 */
12
declare(strict_types = 1);
13
14
namespace WebHemi\Data\Query\SQL;
15
16
use InvalidArgumentException;
17
use PDO;
18
use RuntimeException;
19
use WebHemi\Data\Driver\DriverInterface;
20
use WebHemi\Data\Query\QueryInterface;
21
22
/**
23
 * Class SqlQueryAdapter
24
 */
25
class SqlQueryAdapter implements QueryInterface
26
{
27
    /**
28
     * @var PDO
29
     */
30
    private $driverAdapter;
31
32
    /**
33
     * @var array
34
     */
35
    private $identifierList = [];
36
37
    /**
38
     * QueryInterface constructor.
39
     *
40
     * @param DriverInterface $driverAdapter
41
     */
42
    public function __construct(DriverInterface $driverAdapter)
43
    {
44
        $this->driverAdapter = $driverAdapter;
0 ignored issues
show
Documentation Bug introduced by
It seems like $driverAdapter of type object<WebHemi\Data\Driver\DriverInterface> is incompatible with the declared type object<PDO> of property $driverAdapter.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
45
        $this->init();
46
    }
47
48
    /**
49
     * Collects all the valid statements.
50
     */
51
    private function init() : void
52
    {
53
        $statementFiles = glob(__DIR__.'/statements/*.sql', GLOB_BRACE);
54
55
        foreach ($statementFiles as $file) {
56
            $this->identifierList[basename($file, '.sql')] = $file;
57
        }
58
    }
59
60
    /**
61
     * Returns the Data Driver instance.
62
     *
63
     * @return DriverInterface
64
     */
65
    public function getDriver() : DriverInterface
66
    {
67
        return $this->driverAdapter;
68
    }
69
70
    /**
71
     * Returns all the query identifiers assigned to the query adapter.
72
     *
73
     * @return array
74
     */
75
    public function getQueryIdentifierList() : array
76
    {
77
        return $this->identifierList;
78
    }
79
80
    /**
81
     * Fetches data buy executing a query identified by ID.
82
     *
83
     * @param string $queryIdentifier
84
     * @param array $parameters
85
     * @throws InvalidArgumentException
86
     * @throws RuntimeException
87
     * @return null|array
88
     */
89
    public function fetchData(string $queryIdentifier, array $parameters = []) : ? array
90
    {
91
        $data = null;
92
93
        if (!isset($this->identifierList[$queryIdentifier])) {
94
            throw new InvalidArgumentException(
95
                sprintf('No such query found for this adapter: "%s"', $queryIdentifier),
96
                1000
97
            );
98
        }
99
100
        $query = file_get_contents($this->identifierList[$queryIdentifier]);
101
102
        // This nasty trick helps us to be able to parameterize the ORDER BY statement.
103
        if (isset($parameters[':orderBy'])) {
104
            $orderBy = $parameters[':orderBy'];
105
            unset($parameters[':orderBy']);
106
107
            $query = str_replace(':orderBy', $orderBy, $query);
108
        }
109
110
        $statement = $this->driverAdapter->prepare($query);
111
112
        foreach ($parameters as $parameter => $value) {
113
            $statement->bindValue($parameter, $value, $this->getValueType($value));
114
        }
115
116
        try {
117
            $executedSuccessful = $statement->execute();
118
        } catch (\Throwable $exception) {
119
            throw new RuntimeException(
120
                sprintf('Error executing query for "%s". %s', $queryIdentifier, $exception->getMessage()),
121
                1000
122
            );
123
        }
124
125
        if (!$executedSuccessful) {
126
            throw new RuntimeException(
127
                sprintf('Error running query: "%s"', $queryIdentifier),
128
                1001
129
            );
130
        }
131
        $result = $statement->fetchAll(PDO::FETCH_ASSOC);
132
133
        if (is_array($result)) {
134
            $data = $result;
135
        }
136
137
        return $data;
138
    }
139
140
    /**
141
     * Returns the PDO type of the value.
142
     *
143
     * @param mixed $value
144
     * @return int
145
     */
146
    private function getValueType($value) : int
147
    {
148
        $type = PDO::PARAM_STR;
149
150
        if (is_numeric($value)) {
151
            $type = PDO::PARAM_INT;
152
        } elseif (is_null($value)) {
153
            $type = PDO::PARAM_NULL;
154
        } elseif (is_bool($value)) {
155
            $type = PDO::PARAM_BOOL;
156
        }
157
158
        return $type;
159
    }
160
}
161