ConnectionFactory::createPdoResolver()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 7
ccs 0
cts 0
cp 0
crap 12
rs 10
1
<?php
2
3
namespace Nip\Database\Connections;
4
5
use InvalidArgumentException;
6
use Nip\Config\Config;
7
use Nip\Container\Container;
8
use Nip\Database\Connectors\MySqlConnector;
9
use Nip\Utility\Arr;
10
use PDOException;
11
12
/**
13
 * Class ConnectionFactory
14
 * @package Nip\Database\Connectors
15
 */
16
class ConnectionFactory
17
{
18
    /**
19
     * The IoC container instance.
20
     *
21
     * @var Container
22
     */
23
    protected $container;
24
25
    /**
26
     * Create a new connection factory instance.
27
     *
28
     * @param  Container $container
29
     */
30
    public function __construct(Container $container = null)
31
    {
32
        $this->container = $container ? $container : Container::getInstance();
33
    }
34
35
    /**
36
     * Establish a PDO connection based on the configuration.
37
     *
38
     * @param  array $config
39
     * @param  string $name
40
     * @return Connection
41
     */
42
    public function make($config, $name = null)
43
    {
44
        $config = $this->parseConfig($config, $name);
45
46
//        if (isset($config['read'])) {
47
//            return $this->createReadWriteConnection($config);
48
//        }
49
        return $this->createSingleConnection($config);
50
    }
51
52
    /**
53
     * Parse and prepare the database configuration.
54
     *
55
     * @param  array $config
56
     * @param  string $name
57
     * @return array
58
     */
59
    protected function parseConfig($config, $name)
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

59
    protected function parseConfig($config, /** @scrutinizer ignore-unused */ $name)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
60
    {
61
        return $config;
62
//        return Arr::add(Arr::add($config, 'prefix', ''), 'name', $name);
63
    }
64
65
    /**
66
     * Create a single database connection instance.
67
     *
68
     * @param  array $config
69
     * @return Connection
70
     */
71
    protected function createSingleConnection($config)
72
    {
73
        $pdo = $this->createPdoResolver($config);
74
        if (!isset($config['driver'])) {
75
            $config['driver'] = 'mysql';
76
        }
77
        $connection = $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config);
0 ignored issues
show
Bug introduced by
$pdo of type Closure is incompatible with the type boolean expected by parameter $connection of Nip\Database\Connections...ory::createConnection(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
        $connection = $this->createConnection($config['driver'], /** @scrutinizer ignore-type */ $pdo, $config['database'], $config['prefix'], $config);
Loading history...
78
        $connection->connect($config['host'], $config['username'], $config['password'], $config['database']);
79
80
        return $connection;
81
    }
82
83
    /**
84
     * Create a new connection instance.
85
     *
86
     * @param  string $driver
87
     * @param  boolean $connection
88
     * @param  string $database
89
     * @param  string $prefix
90
     * @param  array $config
91
     * @return Connection
92
     *
93
     * @throws \InvalidArgumentException
94
     */
95
    protected function createConnection($driver, $connection, $database, $prefix = '', $config = [])
96
    {
97
//        if ($resolver = Connection::getResolver($driver)) {
98
//            return $resolver($connection, $database, $prefix, $config);
99
//        }
100
        switch ($driver) {
101
            case 'mysql':
102
                return new MySqlConnection($connection, $database, $prefix, $config);
0 ignored issues
show
Bug introduced by
$connection of type boolean is incompatible with the type Closure|PDO expected by parameter $pdo of Nip\Database\Connections...nnection::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

102
                return new MySqlConnection(/** @scrutinizer ignore-type */ $connection, $database, $prefix, $config);
Loading history...
103
        }
104
105
        throw new InvalidArgumentException("Unsupported driver [$driver]");
106
    }
107
108
    /**
109
     * Create a new Closure that resolves to a PDO instance.
110
     *
111
     * @param  array|Config  $config
112
     * @return \Closure
113
     */
114
    protected function createPdoResolver($config)
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

114
    protected function createPdoResolver(/** @scrutinizer ignore-unused */ $config)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
115
    {
116
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Closure.
Loading history...
117
        $config = $config instanceof Config ? $config->toArray() : $config;
0 ignored issues
show
Unused Code introduced by
$config = $config instan...ig->toArray() : $config is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
118
        return array_key_exists('host', $config)
119
            ? $this->createPdoResolverWithHosts($config)
120
            : $this->createPdoResolverWithoutHosts($config);
121
    }
122
123
    /**
124
     * Create a new Closure that resolves to a PDO instance with a specific host or an array of hosts.
125
     *
126
     * @param  array  $config
127
     * @return \Closure
128
     *
129
     * @throws \PDOException
130
     */
131
    protected function createPdoResolverWithHosts(array $config)
132
    {
133
        return function () use ($config) {
134
            foreach (Arr::shuffle($hosts = $this->parseHosts($config)) as $key => $host) {
135
                $config['host'] = $host;
136
137
                try {
138
                    return $this->createConnector($config)->connect($config);
139
                } catch (PDOException $e) {
140
                    continue;
141
                }
142
            }
143
144
            throw $e;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e seems to be defined by a foreach iteration on line 134. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
145
        };
146
    }
147
148
    /**
149
     * Parse the hosts configuration item into an array.
150
     *
151
     * @param  array  $config
152
     * @return array
153
     *
154
     * @throws \InvalidArgumentException
155
     */
156
    protected function parseHosts(array $config)
157
    {
158
        $hosts = Arr::wrap($config['host']);
159
160
        if (empty($hosts)) {
161
            throw new InvalidArgumentException('Database hosts array is empty.');
162
        }
163
164
        return $hosts;
165
    }
166
167
    /**
168
     * Create a new Closure that resolves to a PDO instance where there is no configured host.
169
     *
170
     * @param  array  $config
171
     * @return \Closure
172
     */
173
    protected function createPdoResolverWithoutHosts(array $config)
174
    {
175
        return function () use ($config) {
176
            return $this->createConnector($config)->connect($config);
177
        };
178
    }
179
180
    /**
181
     * Create a connector instance based on the configuration.
182
     *
183
     * @param  array  $config
184
     * @return \Illuminate\Database\Connectors\ConnectorInterface|MySqlConnector
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Connectors\ConnectorInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
185
     *
186
     * @throws \InvalidArgumentException
187
     */
188
    public function createConnector(array $config)
189
    {
190
        if (! isset($config['driver'])) {
191
            throw new InvalidArgumentException('A driver must be specified.');
192
        }
193
194
//        if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
195
//            return $this->container->make($key);
196
//        }
197
198
        switch ($config['driver']) {
199
            case 'mysql':
200
                return new MySqlConnector();
201
        }
202
203
        throw new InvalidArgumentException("Unsupported driver [{$config['driver']}].");
204
    }
205
}
206