Completed
Push — master ( 6eb58a...ff20ae )
by Jan-Petter
03:32
created

DatabaseHandler::initialCheck()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 9.2
cc 4
eloc 12
nc 4
nop 1
1
<?php
2
namespace vipnytt\RobotsTxtParser\Handler;
3
4
use PDO;
5
use vipnytt\RobotsTxtParser\Client;
6
use vipnytt\RobotsTxtParser\Exceptions\SQLException;
7
8
/**
9
 * Class DatabaseHandler
10
 *
11
 * @package vipnytt\RobotsTxtParser\Handler
12
 */
13
final class DatabaseHandler
14
{
15
    /**
16
     * Cache table name
17
     */
18
    const TABLE_CACHE = 'robotstxt__cache1';
19
20
    /**
21
     * Delay table name
22
     */
23
    const TABLE_DELAY = 'robotstxt__delay0';
24
25
    /**
26
     * MySQL driver name
27
     */
28
    const DRIVER_MYSQL = 'mysql';
29
30
    /**
31
     * Configuration data
32
     */
33
    private $config = [
34
        null => [ // Class initialization 
35
            self::DRIVER_MYSQL => [
36
                'session_get' => 'SELECT @robotstxt;',
37
                'session_set' => 'SET @robotstxt = 1;',
38
            ],
39
        ],
40
        self::TABLE_CACHE => [
41
            'readme' => 'https://github.com/VIPnytt/RobotsTxtParser/blob/master/docs/sql/cache.md',
42
            self::DRIVER_MYSQL => [
43
                'file' => __DIR__ . '/../../res/Cache/MySQL.sql',
44
                'query' => 'SELECT 1 FROM robotstxt__cache1 LIMIT 1;',
45
                'session_get' => 'SELECT @robotstxt_cache;',
46
                'session_set' => 'SET @robotstxt_cache = 1;',
47
            ],
48
        ],
49
        self::TABLE_DELAY => [
50
            'readme' => 'https://github.com/VIPnytt/RobotsTxtParser/blob/master/docs/sql/delay.md',
51
            self::DRIVER_MYSQL => [
52
                'file' => __DIR__ . '/../../res/Delay/MySQL.sql',
53
                'query' => 'SELECT 1 FROM robotstxt__delay0 LIMIT 1;',
54
                'session_get' => 'SELECT @robotstxt_delay;',
55
                'session_set' => 'SET @robotstxt_delay = 1;',
56
            ],
57
        ]
58
    ];
59
60
    /**
61
     * Database handler
62
     * @var PDO
63
     */
64
    private $pdo;
65
66
    /**
67
     * Driver
68
     * @var string
69
     */
70
    private $driver;
71
72
    /**
73
     * Delay manager
74
     * @var Client\Delay\ManagerInterface
75
     */
76
    private $delayManager;
77
78
    /**
79
     * DriverHandler constructor.
80
     *
81
     * @param PDO $pdo
82
     */
83
    public function __construct(PDO $pdo)
84
    {
85
        $this->pdo = $pdo;
86
        $this->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
87
        if (!$this->getSessionVar(null)) {
88
            if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_SILENT) {
89
                $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
90
            }
91
            $this->pdo->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
92
            $this->pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);
93
            $this->driverDependents();
94
            $this->setSessionVar(null);
95
        }
96
    }
97
98
    /**
99
     * Get session variable
100
     *
101
     * @param string|null $table
102
     * @return bool
103
     */
104
    private function getSessionVar($table)
105
    {
106
        if (!isset($this->config[$table][$this->driver]['session_get'])) {
107
            return false;
108
        }
109
        $query = $this->pdo->query($this->config[$table][$this->driver]['session_get']);
110
        return (
111
            $query->rowCount() > 0 &&
112
            $query->fetchColumn(0) !== null
113
        );
114
    }
115
116
    /**
117
     * Driver special treatment
118
     *
119
     * @return bool
120
     */
121
    private function driverDependents()
122
    {
123
        switch ($this->driver) {
124
            case self::DRIVER_MYSQL:
125
                $this->pdo->exec('SET NAMES utf8');
126
                break;
127
        }
128
        return true;
129
    }
130
131
    /**
132
     * Set session variable
133
     *
134
     * @param string|null $table
135
     * @return bool
136
     */
137
    private function setSessionVar($table)
138
    {
139
        if (!isset($this->config[$table][$this->driver]['session_set'])) {
140
            return false;
141
        }
142
        return $this->pdo->exec($this->config[$table][$this->driver]['session_set']);
143
    }
144
145
    /**
146
     * Delay client
147
     *
148
     * @param string $baseUri
149
     * @param string $userAgent
150
     * @param float|int $delay
151
     * @return Client\Delay\ClientInterface
152
     * @throws SQLException
153
     */
154 View Code Duplication
    public function delayClient($baseUri, $userAgent, $delay)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
    {
156
        switch ($this->driver) {
157
            case self::DRIVER_MYSQL:
158
                $this->initialCheck(self::TABLE_DELAY);
159
                return new Client\Delay\MySQL\Client($this->pdo, $baseUri, $userAgent, $delay);
160
        }
161
        throw new SQLException('Unsupported database. ' . $this->config[self::TABLE_DELAY]['readme']);
162
    }
163
164
    /**
165
     * Initial table setup check
166
     *
167
     * @param string $table
168
     * @return bool
169
     * @throws SQLException
170
     */
171
    private function initialCheck($table)
172
    {
173
        if ($this->getSessionVar($table)) {
174
            return true;
175
        }
176
        try {
177
            $this->pdo->query($this->config[$table][$this->driver]['query']);
178
        } catch (\Exception $exception1) {
179
            try {
180
                $this->pdo->query(file_get_contents($this->config[$table][$this->driver]['file']));
181
            } catch (\Exception $exception2) {
182
                throw new SQLException('Missing table `' . key($this->config[$table]) . '`. Setup instructions: ' . $this->config[$table]['readme']);
183
            }
184
        }
185
        $this->setSessionVar($table);
186
        return true;
187
    }
188
189
    /**
190
     * Cache manager
191
     *
192
     * @param array $curlOptions
193
     * @param int|null $byteLimit
194
     * @return Client\Cache\MySQL\Manager
195
     * @throws SQLException
196
     */
197 View Code Duplication
    public function cacheManager(array $curlOptions, $byteLimit)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
    {
199
        switch ($this->driver) {
200
            case self::DRIVER_MYSQL:
201
                $this->initialCheck(self::TABLE_CACHE);
202
                return new Client\Cache\MySQL\Manager($this->pdo, $curlOptions, $byteLimit);
203
        }
204
        throw new SQLException('Unsupported database. ' . $this->config[self::TABLE_CACHE]['readme']);
205
    }
206
207
    /**
208
     * Delay manager
209
     *
210
     * @return Client\Delay\ManagerInterface
211
     * @throws SQLException
212
     */
213
    public function delayManager()
214
    {
215
        if ($this->delayManager !== null) {
216
            return $this->delayManager;
217
        }
218
        switch ($this->driver) {
219
            case self::DRIVER_MYSQL:
220
                $this->initialCheck(self::TABLE_DELAY);
221
                return $this->delayManager = new Client\Delay\MySQL\Manager($this->pdo);
222
        }
223
        throw new SQLException('Unsupported database. ' . $this->config[self::TABLE_DELAY]['readme']);
224
    }
225
}
226