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

PDOExt::prepare()   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 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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
use LegoW\ReconnectingPDO;
14
15
class PDOExt extends ReconnectingPDO
16
{
17
    protected $_table_prefix;
18
    public function __construct($dsn, $user = null, $password = null, $driver_options = array(), $prefix = null)
19
    {
20
        $this->_table_prefix = $prefix ?? '';
21
        parent::__construct($dsn, $user, $password, $driver_options);
22
    }
23
24
    public function exec($statement)
25
    {
26
        $statement = $this->_tablePrefix($statement);
27
        return parent::exec($statement);
28
    }
29
    public function prepare($statement, $driver_options = array())
30
    {
31
        $statement = $this->_tablePrefix($statement);
32
        return parent::prepare($statement, $driver_options);
33
    }
34
    public function query($statement)
35
    {
36
        $statement = $this->_tablePrefix($statement);
37
        $args      = func_get_args();
38
        if (count($args) > 1) {
39
            return call_user_func_array(array($this, 'parent::query'), $args);
40
        } else {
41
            return parent::query($statement);
42
        }
43
    }
44
    protected function _tablePrefix($statement)
45
    {
46
      $statement  = str_replace("prfx_", $this->_table_prefix, $statement);
47
  		return $statement;
48
    }
49
}
50
51
/**
52
 * PDO Provider.
53
 *
54
 * @author Jonathan-Paul Marois <[email protected]>
55
 */
56
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...
57
{
58
    /**
59
     * @var array Buffer.
60
     */
61
    private $args = array();
62
63 56
    /**
64
     * @var array
65 56
     */
66 4
    private $defaultArgs = array(
67 2
        'username' => '',
68 56
        'password' => ''
69 4
    );
70 2
71 56
    /**
72
     * @var int|string
73
     */
74
    private $defaultConnection = 0;
75
76 14
    /**
77
     * @var string
78 14
     */
79 28
    private $id = 'pdo';
80 28
81
    /**
82
     * @var string
83
     */
84
    private $instances = 'pdo.connections';
85
86
    /**
87
     * @var bool
88
     */
89 28
    private $isLoaded = false;
90
91 28
    /**
92
     * @var array
93
     */
94
    private $parameters = array();
95
96
    /**
97
     * @param string $id
98
     * @param string $instances
99
     */
100 52
    public function __construct($id = null, $instances = null)
101
    {
102 52
        if (strlen($id)) {
103
            $this->id = $id;
104
        }
105 52
        if (strlen($instances)) {
106
            $this->instances = $instances;
107 52
        }
108 24
    }
109
110
    /**
111 28
     * @return string
112 28
     */
113 28
    private function buildConnectionString(array $connection)
114 14
    {
115
        return implode(';', array_map(function ($key, $value) {
116
            return is_int($key) ? $value : $key . '=' . $value;
117
        }, array_keys($connection), $connection));
118
    }
119
120
    /**
121
     * @param string $driver
122
     * @param array  $connection
123 52
     *
124
     * @return string
125 52
     */
126 52
    private function buildDsn($driver, array $connection)
127 26
    {
128
        return $this->sanitizeDriver($driver) . ':' . $this->buildConnectionString($connection);
129 52
    }
130
131
    /**
132 52
     * @param \Pimple\Container $app
133
     * @param string            $name
134 52
     *
135 52
     * @return string
136
     */
137
    private function getArg(Container $app, $name)
138 52
    {
139
        return isset($this->args[$name]) ? $this->args[$name] : $this->getDefaultArg($app, $name);
140 52
    }
141 40
142 20
    private function getArgDsn(Container $app)
143 12
    {
144 12
        if (!empty($this->args['dsn'])) {
145
            return $this->args['dsn'];
146 52
        }
147
148 40
        return $this->buildDsn(
149
            !empty($this->args['driver']) ? $this->args['driver'] : $this->getDefaultArg($app, 'driver'),
150 40
            !is_array($this->args['connection']) ? array($this->args['connection']) : $this->args['connection']
151
        );
152 40
    }
153 24
154 28
    /**
155 16
     * @param \Pimple\Container $app
156 8
     * @param string            $name
157
     *
158 40
     * @return string|array
159 32
     */
160 16
    private function getDefaultArg(Container $app, $name)
161 40
    {
162 8
        if (!isset($this->defaultArgs[$name])) {
163 4
            $this->setDefaultArg($app, $name);
164 40
        }
165
166
        return $this->defaultArgs[$name];
167
    }
168
169
    private function loadParameters(Container $app)
170
    {
171 28
        if ($this->isLoaded) {
172
            return;
173 28
        }
174
175
        $this->isLoaded = true;
176 56
177
        if (empty($app['pdo.dsn']) || !is_array($app['pdo.dsn'])) {
178 56
            $this->loadSingletonParameters($app);
179 8
        } else {
180 8
            $this->parameters = $app['pdo.dsn'];
181 4
            $this->defaultConnection = array_keys($this->parameters)[0];
182 4
        }
183 56
    }
184
185
    private function loadSingletonParameters(Container $app)
186
    {
187
        $this->parameters[0] = array();
188
189 52
        if (!empty($app['pdo.dsn'])) {
190
            $this->parameters[0]['dsn'] = $app['pdo.dsn'];
191 52
        } elseif (!empty($app['pdo.connection'])) {
192 52
            $this->parameters[0]['connection'] = $app['pdo.connection'];
193 24
        }
194 52
195
        if (!empty($app['pdo.username'])) {
196 28
            $this->parameters[0]['username'] = $app['pdo.username'];
197
        }
198 26
        if (!empty($app['pdo.password'])) {
199 52
            $this->parameters[0]['password'] = $app['pdo.password'];
200
        }
201 52
        if (!empty($app['pdo.prefix'])) {
202
            $this->parameters[0]['prefix'] = $app['pdo.prefix'];
203 26
        }
204 52
    }
205
206 52
    /**
207 52
     * @param string $driver
208 26
     *
209 52
     * @return string
210 52
     */
211 52
    private function sanitizeDriver($driver)
212 52
    {
213 52
        return ('pdo_' == substr($driver, 0, 4)) ? substr($driver, 4) : $driver;
214 52
    }
215 26
216 26
    private function setAttributes(PDO $pdo, array $attributes)
217 26
    {
218
        if (count($attributes)) {
219 52
            foreach ($attributes as $attr => $value) {
220
                $pdo->setAttribute($attr, $value);
221
            }
222 56
        }
223
    }
224
225
    /**
226
     * @param \Pimple\Container $app
227
     * @param string            $name
228
     */
229 56
    private function setDefaultArg(Container $app, $name)
230 56
    {
231 56
        $this->defaultArgs[$name] = empty($app['pdo.' . $name]) ?
232 56
            array('driver' => 'mysql', 'attributes' => array(), 'options' => array())[$name] :
233 28
            $app['pdo.' . $name];
234 28
    }
235 56
236
    public function register(Container $app)
237 56
    {
238 56
        $app[$this->id] = function () use ($app) {
239 28
            $this->loadParameters($app);
240
241
            return $app[$this->instances][$this->defaultConnection];
242
        };
243
        $app[$this->instances] = function () use ($app) {
244
            $this->loadParameters($app);
245
246
            $instances = new Container();
247
            foreach ($this->parameters as $connection => $args) {
248
                $instances[$connection] = function () use ($app, $args) {
249
                    $this->args = $args;
250
                    return $app['pdo.connect'](
251
                        $this->getArgDsn($app),
252
                        $this->getArg($app, 'username'),
253
                        $this->getArg($app, 'password'),
254
                        $this->getArg($app, 'options'),
255
                        $this->getArg($app, 'attributes'),
256
                        $this->getArg($app, 'prefix')
257
                    );
258
                };
259
            }
260
261
            return $instances;
262
        };
263
264
        $app['pdo.connect'] = $app->protect(function (
265
            $dsn,
266
            $username = '',
267
            $password = '',
268
            array $options = array(),
269
            array $attributes = array(),
270
            $prefix = ''
271
        ) use ($app) {
272
            $pdo = new PDOExt(
273
                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...
274
                $username,
275
                $password,
276
                $options,
277
                $prefix
278
            );
279
            $this->setAttributes($pdo, $attributes);
280
281
            return $pdo;
282
        });
283
    }
284
}
285