Passed
Push — master ( ddb420...13a60b )
by Dispositif
02:30
created

WikidataAdapter::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 * This file is part of dispositif/wikibot application
4
 * 2019 © Philippe M. <[email protected]>
5
 * For the full copyright and MIT license information, please view the LICENSE file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Infrastructure;
11
12
use Exception;
13
use GuzzleHttp\Client;
14
use Normalizer;
15
16
/**
17
 * dirty scratch WikiData read requests
18
 * Class WikidataAdapter
19
 *
20
 * @package App\Infrastructure
21
 */
22
class WikidataAdapter
23
{
24
    private $client;
25
26
    public function __construct(?Client $client = null)
27
    {
28
        if (null === $client) {
29
            // lazy dependency factory :)
30
            $this->client = new Client(['timeout' => 5]);
31
        } else {
32
            $this->client = $client;
33
        }
34
    }
35
36
    /**
37
     * Get WD item, sitelink, VIAF from search by ISNI (author)
38
     *
39
     * @param string $isni
40
     *
41
     * @return null
42
     * @throws Exception
43
     */
44
    public function searchByISNI(string $isni): ?array
45
    {
46
        if (!$this->ISNIvalide($isni)) {
47
            new Exception('Invalid format for ISNI');
48
        }
49
50
        $sparql = sprintf(
51
            'SELECT distinct ?item ?itemLabel ?article ?isni ?viaf WHERE {
52
  ?item wdt:P213 "%s" .
53
  ?item wdt:P213 ?isni.
54
  ?item wdt:P214 ?viaf.
55
  ?article schema:about ?item ;
56
		schema:isPartOf <https://fr.wikipedia.org/>
57
  SERVICE wikibase:label {
58
    bd:serviceParam wikibase:language "fr" .
59
   }
60
}',
61
            $isni
62
        );
63
64
        $result = $this->sparqlRequest($sparql);
65
        if ($result && isset($result['results']) && isset($result['results'])
66
            && isset($result['results']['bindings'])
67
            && count($result['results']['bindings']) === 1
68
        ) {
69
            return $result['results']['bindings'][0];
70
        }
71
72
        return null;
73
    }
74
75
    /**
76
     * @param string $sparql
77
     *
78
     * @return array|null
79
     * @throws Exception
80
     */
81
    private function sparqlRequest(string $sparql): ?array
82
    {
83
        $url = 'https://query.wikidata.org/bigdata/namespace/wdq/sparql?'.http_build_query(
84
                [
85
                    'format' => 'json',
86
                    'query' => urlencode($sparql),
87
                ]
88
            );
89
90
        $response = $this->client->get($url);
91
        // todo : catch + return null ?
92
        if (200 !== $response->getStatusCode()) {
93
            throw new Exception('response error '.$response->getStatusCode());
94
        }
95
        $json = $response->getBody()->getContents();
96
97
        if (empty($json)) {
98
            return null;
99
        }
100
        $json = Normalizer::normalize($json);
101
102
        return json_decode($json, true) ?? null;
103
    }
104
105
    /**
106
     * todo move
107
     *
108
     * @param string $isni
109
     *
110
     * @return bool
111
     */
112
    private function ISNIvalide(string $isni): bool
113
    {
114
        return (!preg_match('#^0000(000[0-4])([0-9]{4})([0-9]{3}[0-9X])$#', $isni)) ? false : true;
115
    }
116
}
117