Completed
Pull Request — master (#4)
by Oyebanji Jacob
02:30
created

DatabaseConnection   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 4
Bugs 1 Features 1
Metric Value
wmc 10
c 4
b 1
f 1
lcom 2
cbo 3
dl 0
loc 154
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A tryAgainIfCausedByLostConnection() 0 8 2
A causedByLostConnection() 0 15 1
A __construct() 0 7 1
A getInstance() 0 8 2
A createConnection() 0 16 2
A getDefaultOptions() 0 4 1
A setDefaultOptions() 0 4 1
1
<?php
2
3
namespace Pyjac\ORM;
4
5
use PDO;
6
7
class DatabaseConnection implements DatabaseConnectionInterface
8
{
9
    /**
10
     * The instance of this class.
11
     *
12
     * @var Pyjac\ORM\DatabaseConnection.
13
     */
14
    private static $instance;
15
16
    /**
17
     * The PDO database connection in use.
18
     *
19
     * @var \PDO
20
     */
21
    public $databaseConnection;
22
23
    /**
24
     * The configuration values.
25
     *
26
     * @var array
27
     */
28
    private $config;
29
30
    /**
31
     * The default PDO connection options.
32
     *
33
     * @var array
34
     */
35
    protected $options = [
36
        PDO::ATTR_CASE              => PDO::CASE_NATURAL,
37
        PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
38
        PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,
39
        PDO::ATTR_STRINGIFY_FETCHES => false,
40
        PDO::ATTR_EMULATE_PREPARES  => false,
41
    ];
42
43
    /**
44
     * Create a new Database Connection.
45
     *
46
     * @param DatabaseConnectionStringFactoryInterface $dbConnStringFactory
47
     */
48
    public function __construct(DatabaseConnectionStringFactoryInterface $dbConnStringFactory)
49
    {
50
        //Read config file
51
        $this->config = parse_ini_file('config.ini');
52
        $dsn = $dbConnStringFactory->createDatabaseSourceString($this->config);
53
        $this->databaseConnection = $this->createConnection($dsn);
54
    }
55
56
    /**
57
     * Get the instance of the class.
58
     *
59
     * @return Pyjac\ORM\DatabaseConnection
60
     */
61
    public static function getInstance()
62
    {
63
        if (self::$instance === null) {
64
            self::$instance = new self(new DatabaseConnectionStringFactory());
65
        }
66
67
        return self::$instance;
68
    }
69
70
    /**
71
     * Create a new PDO connection.
72
     *
73
     * @param string $dsn
74
     *
75
     * @return \PDO
76
     */
77
    public function createConnection($dsn)
78
    {
79
        $username = $this->config['USERNAME'];
80
81
        $password = $this->config['PASSWORD'];
82
83
        try {
84
            $pdo = new PDO($dsn, $username, $password, $this->options);
85
        } catch (\Exception $e) {
86
            $pdo = $this->tryAgainIfCausedByLostConnection(
87
                $e, $dsn, $username, $password, $this->options
88
            );
89
        }
90
91
        return $pdo;
92
    }
93
94
    /**
95
     * Get the default PDO connection options.
96
     *
97
     * @return array
98
     */
99
    public function getDefaultOptions()
100
    {
101
        return $this->options;
102
    }
103
104
    /**
105
     * Set the default PDO connection options.
106
     *
107
     * @param array $options
108
     *
109
     * @return void
110
     */
111
    public function setDefaultOptions(array $options)
112
    {
113
        $this->options = $options;
114
    }
115
116
    /**
117
     * Handle a exception that occurred during connect execution.
118
     *
119
     * @param \Exception $e
120
     * @param string     $dsn
121
     * @param string     $username
122
     * @param string     $password
123
     * @param array      $options
124
     *
125
     * @throws \Exception
126
     *
127
     * @return \PDO
128
     */
129
    protected function tryAgainIfCausedByLostConnection(\Exception $e, $dsn, $username, $password, $options)
130
    {
131
        if ($this->causedByLostConnection($e)) {
132
            return new PDO($dsn, $username, $password, $options);
133
        }
134
135
        throw $e;
136
    }
137
138
    /**
139
     * Determine if the given exception was caused by a lost connection.
140
     *
141
     * @param \Exception $e
142
     *
143
     * @return bool
144
     */
145
    protected function causedByLostConnection(\Exception $e)
146
    {
147
        $message = $e->getMessage();
148
149
        return Helpers::contains($message, [
150
            'server has gone away',
151
            'no connection to the server',
152
            'Lost connection',
153
            'is dead or not enabled',
154
            'Error while sending',
155
            'decryption failed or bad record mac',
156
            'SSL connection has been closed unexpectedly',
157
            'Deadlock found when trying to get lock',
158
        ]);
159
    }
160
}
161