Passed
Push — master ( 9f9e2a...75e8d8 )
by Dispositif
02:34
created

WikiBlameAdapter::searchDiff()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 16
c 1
b 0
f 1
dl 0
loc 24
rs 9.7333
cc 4
nc 6
nop 3
1
<?php
2
/*
3
 * This file is part of dispositif/wikibot application (@github)
4
 * 2019-2023 © Philippe M./Irønie  <[email protected]>
5
 * For the full copyright and MIT license information, view the license file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Infrastructure;
11
12
use App\Application\InfrastructurePorts\HttpClientInterface;
13
use App\Domain\Utils\DateUtil;
14
use App\Infrastructure\Monitor\NullLogger;
15
use Psr\Log\LoggerInterface;
16
17
/**
18
 * Find the last addition edit (and date) of a string in a wiki article.
19
 * Request on http://wikipedia.ramselehof.de/wikiblame.php
20
 * See also https://github.com/FlominatorTM/wikiblame
21
 */
22
class WikiBlameAdapter
23
{
24
    protected HttpClientInterface $client;
25
26
    public function __construct(private readonly LoggerInterface|NullLogger $log = new NullLogger())
27
    {
28
        $this->client = ServiceFactory::getHttpClient();
29
    }
30
31
    /**
32
     * return [
33
     *    "versionid" => (int) 103659068
34
     *    "dateraw" => "09 mai 2014"
35
     *    "datetime" => DateTime
36
     */
37
    public function searchDiff(string $article, string $string, bool $hasWikicode = false): ?array
38
    {
39
        $url = 'http://wikipedia.ramselehof.de/wikiblame.php?project=wikipedia&article='
40
            . str_replace(' ', '+', $article)
41
            . '&needle=' . urlencode($string)
42
            . '&lang=fr&limit=2000&offjahr=2024&offmon=1&offtag=1&offhour=23&offmin=55'
43
            . '&searchmethod=int&order=desc'
44
            . '&force_wikitags=' . ($hasWikicode ? 'on' : 'off')
45
            . '&user_lang=fr&ignorefirst=0';
46
47
        $response = $this->client->get($url);
48
49
        if ($response->getStatusCode() !== 200) {
50
            $this->log->warning('WikiBlame: ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase());
51
            return null;
52
        }
53
54
        $rawHtml = $response->getBody()->getContents();
55
        if (empty($rawHtml)) {
56
            $this->log->warning('WikiBlame: empty response');
57
            return null;
58
        }
59
60
        return $this->parseRawHtml($rawHtml);
61
    }
62
63
    private function parseRawHtml(string $rawHtml): ?array
64
    {
65
        if (!preg_match('#Insertion détectée entre le <a href="https:[^\"]+">[^<]+<\/a> et le <a href="https:[^\"]+&oldid=(\d+)">[\d:]+, ([^<]+)<\/a>: <a#', $rawHtml, $matches)) {
66
            $this->log->warning('WikiBlame: no result from HTML');
67
            return null;
68
        }
69
70
        return [
71
            'versionid' => (int)$matches[1],
72
            'dateraw' => $matches[2],
73
            'datetime' => DateUtil::simpleFrench2object($matches[2]),
74
        ];
75
    }
76
}