Base::refresh()   B
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.3626
c 0
b 0
f 0
cc 7
nc 4
nop 0
1
<?php
2
/**
3
 * vipnytt/RobotsTxtParser
4
 *
5
 * @link https://github.com/VIPnytt/RobotsTxtParser
6
 * @license https://github.com/VIPnytt/RobotsTxtParser/blob/master/LICENSE The MIT License (MIT)
7
 */
8
9
namespace vipnytt\RobotsTxtParser\Client\Cache\MySQL;
10
11
use vipnytt\RobotsTxtParser\Client\Cache\BaseCore;
12
use vipnytt\RobotsTxtParser\Exceptions;
13
use vipnytt\RobotsTxtParser\RobotsTxtInterface;
14
use vipnytt\RobotsTxtParser\TxtClient;
15
use vipnytt\RobotsTxtParser\UriClient;
16
17
/**
18
 * Class Base
19
 *
20
 * @see https://vipnytt.github.io/RobotsTxtParser/methods/Cache.html for documentation
21
 * @package vipnytt\RobotsTxtParser\Handler\Cache\MySQL
22
 */
23
class Base extends BaseCore implements RobotsTxtInterface
24
{
25
    /**
26
     * Debug - Get raw data
27
     *
28
     * @return array
29
     */
30
    public function debug()
31
    {
32
        $query = $this->pdo->prepare(<<<SQL
33
SELECT *
34
FROM robotstxt__cache1
35
WHERE base = :base;
36
SQL
37
        );
38
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
39
        $query->execute();
40
        return $query->rowCount() > 0 ? $query->fetch(\PDO::FETCH_ASSOC) : [];
41
    }
42
43
    /**
44
     * Parser client
45
     *
46
     * @return TxtClient
47
     * @throws Exceptions\OutOfSyncException
48
     * @throws Exceptions\DatabaseException
49
     */
50
    public function client()
51
    {
52
        $query = $this->pdo->prepare(<<<SQL
53
SELECT
54
  content,
55
  statusCode,
56
  nextUpdate,
57
  effective,
58
  worker,
59
  UNIX_TIMESTAMP()
60
FROM robotstxt__cache1
61
WHERE base = :base;
62
SQL
63
        );
64
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
65
        $query->execute();
66
        if ($query->rowCount() > 0) {
67
            $row = $query->fetch(\PDO::FETCH_ASSOC);
68
            $this->clockSyncCheck($row['UNIX_TIMESTAMP()'], self::OUT_OF_SYNC_TIME_LIMIT);
69
            if ($row['nextUpdate'] >= $row['UNIX_TIMESTAMP()']) {
70
                $this->markAsActive($row['worker']);
71
                return new TxtClient($this->base, $row['statusCode'], $row['content'], self::ENCODING, $row['effective'], $this->byteLimit);
72
            }
73
        }
74
        $query = $this->pdo->prepare(<<<SQL
75
UPDATE robotstxt__cache1
76
SET worker = 0
77
WHERE base = :base;
78
SQL
79
        );
80
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
81
        $query->execute();
82
        return $this->refresh();
83
    }
84
85
    /**
86
     * Mark robots.txt as active
87
     *
88
     * @param int|null $workerID
89
     * @return bool
90
     */
91
    private function markAsActive($workerID = 0)
92
    {
93
        if ($workerID == 0) {
94
            $query = $this->pdo->prepare(<<<SQL
95
UPDATE robotstxt__cache1
96
SET worker = NULL
97
WHERE base = :base AND worker = 0;
98
SQL
99
            );
100
            $query->bindValue('base', $this->base, \PDO::PARAM_STR);
101
            return $query->execute();
102
        }
103
        return true;
104
    }
105
106
    /**
107
     * Update the robots.txt
108
     *
109
     * @return UriClient
110
     * @throws Exceptions\DatabaseException
111
     */
112
    public function refresh()
113
    {
114
        $client = new UriClient($this->base, $this->curlOptions, $this->byteLimit);
115
        $effective = $client->getEffectiveUri();
116
        if ($effective == $this->base) {
117
            $effective = null;
118
        }
119
        $statusCode = $client->getStatusCode();
120
        $nextUpdate = $client->nextUpdate();
121
        if (strpos($this->base, 'http') === 0 &&
122
            (
123
                $statusCode === null ||
124
                (
125
                    $statusCode >= 500 &&
126
                    $statusCode < 600
127
                )
128
            ) &&
129
            $this->displacePush($nextUpdate)
130
        ) {
131
            return $client;
132
        }
133
        $validUntil = $client->validUntil();
134
        $content = $client->render()->compressed(self::RENDER_LINE_SEPARATOR);
135
        $query = $this->pdo->prepare(<<<SQL
136
INSERT INTO robotstxt__cache1 (base, content, statusCode, validUntil, nextUpdate, effective)
137
VALUES (:base, :content, :statusCode, :validUntil, :nextUpdate, :effective)
138
ON DUPLICATE KEY UPDATE content = :content, statusCode = :statusCode, validUntil = :validUntil,
139
  nextUpdate = :nextUpdate, effective = :effective, worker = 0;
140
SQL
141
        );
142
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
143
        $query->bindValue('content', $content, \PDO::PARAM_STR);
144
        $query->bindValue('statusCode', $statusCode, \PDO::PARAM_INT | \PDO::PARAM_NULL);
145
        $query->bindValue('validUntil', $validUntil, \PDO::PARAM_INT);
146
        $query->bindValue('nextUpdate', $nextUpdate, \PDO::PARAM_INT);
147
        $query->bindValue('effective', $effective, \PDO::PARAM_STR | \PDO::PARAM_NULL);
148
        $query->execute();
149
        return $client;
150
    }
151
152
    /**
153
     * Displace push timestamp
154
     *
155
     * @param int $nextUpdate
156
     * @return bool
157
     * @throws Exceptions\OutOfSyncException
158
     */
159
    private function displacePush($nextUpdate)
160
    {
161
        $query = $this->pdo->prepare(<<<SQL
162
SELECT
163
  validUntil,
164
  UNIX_TIMESTAMP()
165
FROM robotstxt__cache1
166
WHERE base = :base;
167
SQL
168
        );
169
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
170
        $query->execute();
171
        if ($query->rowCount() > 0) {
172
            $row = $query->fetch(\PDO::FETCH_ASSOC);
173
            $this->clockSyncCheck($row['UNIX_TIMESTAMP()'], self::OUT_OF_SYNC_TIME_LIMIT);
174
            if ($row['validUntil'] > $row['UNIX_TIMESTAMP()']) {
175
                $nextUpdate = min($row['validUntil'], $nextUpdate);
176
                $query = $this->pdo->prepare(<<<SQL
177
UPDATE robotstxt__cache1
178
SET nextUpdate = :nextUpdate, worker = 0
179
WHERE base = :base;
180
SQL
181
                );
182
                $query->bindValue('base', $this->base, \PDO::PARAM_STR);
183
                $query->bindValue('nextUpdate', $nextUpdate, \PDO::PARAM_INT);
184
                return $query->execute();
185
            }
186
        }
187
        return false;
188
    }
189
190
    /**
191
     * Invalidate cache
192
     *
193
     * @return bool
194
     */
195
    public function invalidate()
196
    {
197
        $query = $this->pdo->prepare(<<<SQL
198
DELETE FROM robotstxt__cache1
199
WHERE base = :base;
200
SQL
201
        );
202
        $query->bindValue('base', $this->base, \PDO::PARAM_STR);
203
        return $query->execute();
204
    }
205
}
206