Test Failed
Pull Request — master (#1)
by
unknown
22:43 queued 08:36
created

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