Completed
Push — master ( 1b6743...e69112 )
by Jan-Petter
9s
created

DelayHandlerSQL   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
c 1
b 0
f 0
lcom 1
cbo 2
dl 0
loc 119
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A sleep() 0 14 3
A getMicroTime() 0 19 2
A increment() 0 14 1
1
<?php
2
namespace vipnytt\RobotsTxtParser\Client\SQL\Delay;
3
4
use PDO;
5
use vipnytt\RobotsTxtParser\Client\SQL\SQLInterface;
6
use vipnytt\RobotsTxtParser\Client\SQL\SQLTrait;
7
use vipnytt\RobotsTxtParser\Parser\UrlParser;
8
9
/**
10
 * Class DelayHandlerSQL
11
 *
12
 * @package vipnytt\RobotsTxtParser\Delay\SQL
13
 */
14
class DelayHandlerSQL implements SQLInterface
15
{
16
    use SQLTrait;
17
    use UrlParser;
18
19
    /**
20
     * @var PDO
21
     */
22
    private $pdo;
23
24
    /**
25
     * PDO driver
26
     * @var string
27
     */
28
    private $driver;
29
30
    /**
31
     * Base URI
32
     * @var string
33
     */
34
    private $base;
35
36
    /**
37
     * User-agent
38
     * @var string
39
     */
40
    private $userAgent;
41
42
    /**
43
     * Delay
44
     * @var float|int
45
     */
46
    private $delay;
47
48
    /**
49
     * Delay constructor.
50
     *
51
     * @param PDO $pdo
52
     * @param string $baseUri
53
     * @param string $userAgent
54
     * @param float|int $delay
55
     */
56
    public function __construct(PDO $pdo, $baseUri, $userAgent, $delay)
57
    {
58
        $this->pdo = $this->pdoInitialize($pdo);
59
        $this->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
60
        if ($this->driver != 'mysql') {
61
            trigger_error('Unsupported database. Currently only MySQL 5.6+ are officially supported. ' . self::README_SQL_DELAY, E_USER_WARNING);
62
        }
63
        $this->base = $this->urlBase($this->urlEncode($baseUri));
64
        $this->userAgent = $userAgent;
65
        $this->delay = $delay;
66
    }
67
68
    /**
69
     * Sleep
70
     *
71
     * @return float|int
72
     */
73
    public function sleep()
74
    {
75
        $start = microtime(true);
76
        $until = $this->getMicroTime();
77
        if (microtime(true) > $until) {
78
            return 0;
79
        }
80
        try {
81
            time_sleep_until($until);
82
        } catch (\Exception $warning) {
83
            // Timestamp already in the past
84
        }
85
        return microtime(true) - $start;
86
    }
87
88
    /**
89
     * Timestamp with milliseconds
90
     *
91
     * @return float|int|false
92
     */
93
    public function getMicroTime()
94
    {
95
        $this->increment();
96
        $query = $this->pdo->prepare(<<<SQL
97
SELECT microTime
98
FROM robotstxt__delay0
99
WHERE base = :base AND userAgent = :userAgent;
100
SQL
101
        );
102
        $query->bindParam(':base', $this->base, PDO::PARAM_STR);
103
        $query->bindParam(':userAgent', $this->userAgent, PDO::PARAM_STR);
104
        $query->execute();
105
106
        if ($query->rowCount() > 0) {
107
            $row = $query->fetch(PDO::FETCH_ASSOC);
108
            return $row['microTime'] / 1000000;
109
        }
110
        return 0;
111
    }
112
113
    /**
114
     * Set new delayUntil timestamp
115
     *
116
     * @return bool
117
     */
118
    private function increment()
119
    {
120
        $query = $this->pdo->prepare(<<<SQL
121
INSERT INTO robotstxt__delay0 (base, userAgent, microTime)
122
VALUES (:base, :userAgent, microTime + :delay)
123
ON DUPLICATE KEY UPDATE
124
  microTime = GREATEST((UNIX_TIMESTAMP(CURTIME(6)) + :delay) * 1000000, microTime + (:delay * 1000000));
125
SQL
126
        );
127
        $query->bindParam(':base', $this->base, PDO::PARAM_STR);
128
        $query->bindParam(':userAgent', $this->userAgent, PDO::PARAM_STR);
129
        $query->bindParam(':delay', $this->delay, PDO::PARAM_INT);
130
        return $query->execute();
131
    }
132
}
133