Test Failed
Pull Request — master (#1)
by
unknown
15:34
created

PDOExt::exec()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * PDO service provider for the Silex micro-framework.
4
 *
5
 * @see http://php.net/manual/book.pdo.php
6
 */
7
8
namespace LiquidBox\Silex\Provider;
9
10
use PDO;
11
use Pimple\Container;
12
use Pimple\ServiceProviderInterface;
13
14
class PDOExt extends PDO
15
{
16
    protected $_table_prefix;
17
    public function __construct($dsn, $user = null, $password = null, $driver_options = array(), $prefix = null)
18
    {
19
        $this->_table_prefix = $prefix ?? '';
20
        parent::__construct($dsn, $user, $password, $driver_options);
21
    }
22
23
    public function exec($statement)
24
    {
25
        $statement = $this->_tablePrefix($statement);
26
        return parent::exec($statement);
27
    }
28
    public function prepare($statement, $driver_options = array())
29
    {
30
        $statement = $this->_tablePrefix($statement);
31
        return parent::prepare($statement, $driver_options);
32
    }
33
    public function query($statement)
34
    {
35
        $statement = $this->_tablePrefix($statement);
36
        $args      = func_get_args();
37
        if (count($args) > 1) {
38
            return call_user_func_array(array($this, 'parent::query'), $args);
39
        } else {
40
            return parent::query($statement);
41
        }
42
    }
43
    protected function _tablePrefix($statement)
44
    {
45
      $statement  = str_replace("prfx_", $this->_table_prefix, $statement);
46
  		return $statement;
47
    }
48
}
49
50
/**
51
 * PDO Provider.
52
 *
53
 * @author Jonathan-Paul Marois <[email protected]>
54
 */
55
class PdoServiceProvider implements ServiceProviderInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
56
{
57
    /**
58
     * @var array Buffer.
59
     */
60
    private $args = array();
61
62
    /**
63
     * @var array
64
     */
65
    private $defaultArgs = array(
66
        'username' => '',
67
        'password' => ''
68
    );
69
70
    /**
71
     * @var int|string
72
     */
73
    private $defaultConnection = 0;
74
75
    /**
76
     * @var string
77
     */
78
    private $id = 'pdo';
79
80
    /**
81
     * @var string
82
     */
83
    private $instances = 'pdo.connections';
84
85
    /**
86
     * @var bool
87
     */
88
    private $isLoaded = false;
89
90
    /**
91
     * @var array
92
     */
93
    private $parameters = array();
94
95
    /**
96
     * @param string $id
97
     * @param string $instances
98
     */
99 28
    public function __construct($id = null, $instances = null)
100
    {
101 28
        if (strlen($id)) {
102 2
            $this->id = $id;
103
        }
104 28
        if (strlen($instances)) {
105 2
            $this->instances = $instances;
106
        }
107 28
    }
108
109
    /**
110
     * @return string
111
     */
112
    private function buildConnectionString(array $connection)
113
    {
114 14
        return implode(';', array_map(function ($key, $value) {
115 14
            return is_int($key) ? $value : $key . '=' . $value;
116 14
        }, array_keys($connection), $connection));
117
    }
118
119
    /**
120
     * @param string $driver
121
     * @param array  $connection
122
     *
123
     * @return string
124
     */
125 14
    private function buildDsn($driver, array $connection)
126
    {
127 14
        return $this->sanitizeDriver($driver) . ':' . $this->buildConnectionString($connection);
128
    }
129
130
    /**
131
     * @param \Pimple\Container $app
132
     * @param string            $name
133
     *
134
     * @return string
135
     */
136 26
    private function getArg(Container $app, $name)
137
    {
138 26
        return isset($this->args[$name]) ? $this->args[$name] : $this->getDefaultArg($app, $name);
139
    }
140
141 26
    private function getArgDsn(Container $app)
142
    {
143 26
        if (!empty($this->args['dsn'])) {
144 12
            return $this->args['dsn'];
145
        }
146
147 14
        return $this->buildDsn(
148 14
            !empty($this->args['driver']) ? $this->args['driver'] : $this->getDefaultArg($app, 'driver'),
149 14
            !is_array($this->args['connection']) ? array($this->args['connection']) : $this->args['connection']
150
        );
151
    }
152
153
    /**
154
     * @param \Pimple\Container $app
155
     * @param string            $name
156
     *
157
     * @return string|array
158
     */
159 26
    private function getDefaultArg(Container $app, $name)
160
    {
161 26
        if (!isset($this->defaultArgs[$name])) {
162 26
            $this->setDefaultArg($app, $name);
163
        }
164
165 26
        return $this->defaultArgs[$name];
166
    }
167
168 26
    private function loadParameters(Container $app)
169
    {
170 26
        if ($this->isLoaded) {
171 26
            return;
172
        }
173
174 26
        $this->isLoaded = true;
175
176 26
        if (empty($app['pdo.dsn']) || !is_array($app['pdo.dsn'])) {
177 20
            $this->loadSingletonParameters($app);
178
        } else {
179 6
            $this->parameters = $app['pdo.dsn'];
180 6
            $this->defaultConnection = array_keys($this->parameters)[0];
181
        }
182 26
    }
183
184 20
    private function loadSingletonParameters(Container $app)
185
    {
186 20
        $this->parameters[0] = array();
187
188 20
        if (!empty($app['pdo.dsn'])) {
189 12
            $this->parameters[0]['dsn'] = $app['pdo.dsn'];
190 8
        } elseif (!empty($app['pdo.connection'])) {
191 8
            $this->parameters[0]['connection'] = $app['pdo.connection'];
192
        }
193
194 20
        if (!empty($app['pdo.username'])) {
195 16
            $this->parameters[0]['username'] = $app['pdo.username'];
196
        }
197 20
        if (!empty($app['pdo.password'])) {
198 4
            $this->parameters[0]['password'] = $app['pdo.password'];
199
        }
200 20
        if (!empty($app['pdo.prefix'])) {
201
            $this->parameters[0]['prefix'] = $app['pdo.prefix'];
202
        }
203 20
    }
204
205
    /**
206
     * @param string $driver
207
     *
208
     * @return string
209
     */
210 14
    private function sanitizeDriver($driver)
211
    {
212 14
        return ('pdo_' == substr($driver, 0, 4)) ? substr($driver, 4) : $driver;
213
    }
214
215
    private function setAttributes(PDO $pdo, array $attributes)
216
    {
217
        if (count($attributes)) {
218
            foreach ($attributes as $attr => $value) {
219
                $pdo->setAttribute($attr, $value);
220
            }
221
        }
222
    }
223
224
    /**
225
     * @param \Pimple\Container $app
226
     * @param string            $name
227
     */
228 26
    private function setDefaultArg(Container $app, $name)
229
    {
230 26
        $this->defaultArgs[$name] = empty($app['pdo.' . $name]) ?
231 26
            array('driver' => 'mysql', 'attributes' => array(), 'options' => array())[$name] :
232 12
            $app['pdo.' . $name];
233 26
    }
234
235
    public function register(Container $app)
236
    {
237 26
        $app[$this->id] = function () use ($app) {
238 26
            $this->loadParameters($app);
239
240 26
            return $app[$this->instances][$this->defaultConnection];
241
        };
242 26
        $app[$this->instances] = function () use ($app) {
243 26
            $this->loadParameters($app);
244
245 26
            $instances = new Container();
246 26
            foreach ($this->parameters as $connection => $args) {
247 26
                $instances[$connection] = function () use ($app, $args) {
248 26
                    $this->args = $args;
249 26
                    return $app['pdo.connect'](
250 26
                        $this->getArgDsn($app),
251 26
                        $this->getArg($app, 'username'),
252 26
                        $this->getArg($app, 'password'),
253 26
                        $this->getArg($app, 'options'),
254 26
                        $this->getArg($app, 'attributes'),
255 26
                        $this->getArg($app, 'prefix')
256
                    );
257 26
                };
258
            }
259
260 26
            return $instances;
261
        };
262
263 28
        $app['pdo.connect'] = $app->protect(function (
264
            $dsn,
265
            $username = '',
266
            $password = '',
267
            array $options = array(),
268
            array $attributes = array(),
269
            $prefix = ''
270
        ) use ($app) {
271 2
            $pdo = new PDO(
272 2
                is_array($dsn) ? $this->buildDsn($this->getDefaultArg($app, 'driver'), $dsn) : $dsn,
0 ignored issues
show
Bug introduced by
It seems like $this->getDefaultArg($app, 'driver') targeting LiquidBox\Silex\Provider...ovider::getDefaultArg() can also be of type array; however, LiquidBox\Silex\Provider...iceProvider::buildDsn() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
273 2
                $username,
274 2
                $password,
275 2
                $options,
276 2
                $prefix
277
            );
278
            $this->setAttributes($pdo, $attributes);
279
280
            return $pdo;
281 28
        });
282
    }
283
}
284