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

tryAgainIfCausedByLostConnection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 5
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