Test Setup Failed
Push — master ( 455f41...6456b5 )
by Gabriel
11:14 queued 12s
created

Connector   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
wmc 12
lcom 2
cbo 0
dl 0
loc 129
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A createConnection() 0 17 2
A createPdoConnection() 0 8 3
A isPersistentConnection() 0 5 2
A tryAgainIfCausedByLostConnection() 0 8 2
A getOptions() 0 6 1
A getDefaultOptions() 0 4 1
A setDefaultOptions() 0 4 1
1
<?php
2
3
namespace Nip\Database\Connectors;
4
5
use PDO;
6
7
/**
8
 * Class Connector
9
 * @package Nip\Database\Connectors
10
 */
11
class Connector
12
{
13
14
    /**
15
     * The default PDO connection options.
16
     *
17
     * @var array
18
     */
19
    protected $options = [
20
        PDO::ATTR_CASE => PDO::CASE_NATURAL,
21
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
22
        PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
23
        PDO::ATTR_STRINGIFY_FETCHES => false,
24
        PDO::ATTR_EMULATE_PREPARES => false,
25
    ];
26
27
    /**
28
     * Create a new PDO connection.
29
     *
30
     * @param string $dsn
31
     * @param array $config
32
     * @param array $options
33
     * @return \PDO
34
     *
35
     * @throws \Exception
36
     */
37
    public function createConnection($dsn, array $config, array $options)
38
    {
39
        [$username, $password] = [
0 ignored issues
show
Bug introduced by
The variable $username does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $password does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
40
            $config['username'] ?? null,
41
            $config['password'] ?? null,
42
        ];
43
44
        try {
45
            return $this->createPdoConnection(
46
                $dsn, $username, $password, $options
47
            );
48
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class Nip\Database\Connectors\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
49
            return $this->tryAgainIfCausedByLostConnection(
50
                $e, $dsn, $username, $password, $options
51
            );
52
        }
53
    }
54
55
    /**
56
     * Create a new PDO connection instance.
57
     *
58
     * @param string $dsn
59
     * @param string $username
60
     * @param string $password
61
     * @param array $options
62
     * @return \PDO
63
     */
64
    protected function createPdoConnection($dsn, $username, $password, $options)
65
    {
66
        if (class_exists(PDOConnection::class) && !$this->isPersistentConnection($options)) {
67
            return new PDOConnection($dsn, $username, $password, $options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Nip\Database..., $password, $options); (Nip\Database\Connectors\PDOConnection) is incompatible with the return type documented by Nip\Database\Connectors\...or::createPdoConnection of type PDO.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
68
        }
69
70
        return new PDO($dsn, $username, $password, $options);
71
    }
72
73
    /**
74
     * Determine if the connection is persistent.
75
     *
76
     * @param array $options
77
     * @return bool
78
     */
79
    protected function isPersistentConnection($options)
80
    {
81
        return isset($options[PDO::ATTR_PERSISTENT]) &&
82
            $options[PDO::ATTR_PERSISTENT];
83
    }
84
85
    /**
86
     * Handle an exception that occurred during connect execution.
87
     *
88
     * @param \Throwable $e
89
     * @param string $dsn
90
     * @param string $username
91
     * @param string $password
92
     * @param array $options
93
     * @return \PDO
94
     *
95
     * @throws \Exception
96
     */
97
    protected function tryAgainIfCausedByLostConnection(Throwable $e, $dsn, $username, $password, $options)
98
    {
99
        if ($this->causedByLostConnection($e)) {
0 ignored issues
show
Bug introduced by
The method causedByLostConnection() does not exist on Nip\Database\Connectors\Connector. Did you maybe mean tryAgainIfCausedByLostConnection()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
100
            return $this->createPdoConnection($dsn, $username, $password, $options);
101
        }
102
103
        throw $e;
104
    }
105
106
    /**
107
     * Get the PDO options based on the configuration.
108
     *
109
     * @param array $config
110
     * @return array
111
     */
112
    public function getOptions(array $config)
113
    {
114
        $options = $config['options'] ?? [];
115
116
        return array_diff_key($this->options, $options) + $options;
117
    }
118
119
    /**
120
     * Get the default PDO connection options.
121
     *
122
     * @return array
123
     */
124
    public function getDefaultOptions()
125
    {
126
        return $this->options;
127
    }
128
129
    /**
130
     * Set the default PDO connection options.
131
     *
132
     * @param array $options
133
     * @return void
134
     */
135
    public function setDefaultOptions(array $options)
136
    {
137
        $this->options = $options;
138
    }
139
}