Completed
Push — master ( 02d12e...885401 )
by Dispositif
02:42
created

BnfMapper   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 69
c 2
b 0
f 0
dl 0
loc 208
rs 10
wmc 29

9 Methods

Rating   Name   Duplication   Size   Complexity  
A convertPages() 0 8 3
A convertBnfIdent() 0 10 3
A getPublishDate() 0 12 3
A xpath2string() 0 16 5
A getLocation() 0 16 4
A getPublisher() 0 17 4
A process() 0 65 3
A lang2wiki() 0 7 2
A stripLangFR() 0 3 2
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\Domain\Publisher;
11
12
use App\Domain\Enums\Language;
13
use SimpleXMLElement;
14
15
/**
16
 * Class BnfMapper
17
 * http://catalogue.bnf.fr/api/SRU?version=1.2&operation=searchRetrieve&query=bib.isbn%2Badj%2B%25222844940404%2522.
18
 */
19
class BnfMapper extends AbstractBookMapper implements MapperInterface
20
{
21
    /**
22
     * @var SimpleXMLElement
23
     */
24
    private $xml;
25
26
    /**
27
     * XML in UniMarc format.
28
     * See http://api.bnf.fr/formats-bibliographiques-intermarc-unimarc
29
     * https://www.transition-bibliographique.fr/systemes-et-donnees/manuel-unimarc-format-bibliographique/.
30
     *
31
     * @param $xml
32
     *
33
     * @return array
34
     */
35
    public function process($xml): array
36
    {
37
        if (!$xml instanceof SimpleXMLElement) {
38
            return [];
39
        }
40
        $this->xml = $xml;
41
42
        // skip multi-records
43
        $nbResults = (int)$xml->xpath('//srw:numberOfRecords[1]')[0] ?? 0;
44
        if (1 !== $nbResults) {
45
            echo "BNF : $nbResults records (skip)\n";
46
47
            return [];
48
        }
49
50
        return [
51
            //            'bnf' => $this->convertBnfIdent(), // pertinent si isbn ?
52
            'isbn' => $this->xpath2string('//mxc:datafield[@tag="010"]/mxc:subfield[@code="a"][1]'),
53
            'isbn2' => $this->xpath2string('//mxc:datafield[@tag="010"]/mxc:subfield[@code="a"][2]'),
54
55
            // Langue
56
            'langue' => $this->lang2wiki($this->xpath2string('//mxc:datafield[@tag="101"]/mxc:subfield[@code="a"][1]')),
57
            // c : Langue de l’œuvre originale
58
            'langue originale' => $this->stripLangFR(
59
                $this->lang2wiki(
60
                    $this->xpath2string('//mxc:datafield[@tag="101"]/mxc:subfield[@code="c"][1]')
61
                )
62
            ),
63
            // g : Langue du titre propre (si différent)
64
            'langue titre' => $this->stripLangFR(
65
                $this->lang2wiki(
66
                    $this->xpath2string('//mxc:datafield[@tag="101"]/mxc:subfield[@code="g"][1]')
67
                )
68
            ),
69
            /*
70
             * Bloc 200.
71
             * https://www.transition-bibliographique.fr/wp-content/uploads/2019/11/B200-2018.pdf
72
             */ // a : Titre propre
73
            'titre' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="a"][1]'),
74
            // d : Titre parralèle (autre langue)
75
            'titre original' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="d"][1]'),
76
            // e : Complément du titre
77
            'sous-titre' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="e"][1]', ', '),
78
            // f : responsabilité principale "Pierre Durand, Paul Dupond" (XML de dingue pour ça...)
79
            'auteur1' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="f"]', ', '),
80
            // g : Mention de responsabilité suivante
81
            'auteur2' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="g"]', ', '),
82
            // h : Numéro de partie
83
            //            'volume' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="h"]'),
84
            // i : Titre de partie
85
            // v : numéro de volume
86
            'volume' => $this->xpath2string('//mxc:datafield[@tag="200"]/mxc:subfield[@code="v"][1]'),
87
88
            // 410 : collection
89
            'collection' => $this->xpath2string('//mxc:datafield[@tag="410"]/mxc:subfield[@code="a"][1]'),
90
91
            // Auteur : voir plutôt 7XX
92
            //  https://www.transition-bibliographique.fr/wp-content/uploads/2018/07/B7XX-6-2011.pdf
93
94
            // multi-zones
95
            'lieu' => $this->getLocation(),
96
            'éditeur' => $this->getPublisher(),
97
            'date' => $this->getPublishDate(),
98
            // 215
99
            'pages totales' => $this->convertPages(),
100
        ];
101
    }
102
103
    private function xpath2string(string $path, ?string $glue = ', '): ?string
104
    {
105
        $elements = $this->xml->xpath($path);
106
107
        $res = [];
108
        foreach ($elements as $element) {
109
            if (isset($element) && $element instanceof SimpleXMLElement) {
110
                $res[] = (string)$element;
111
            }
112
        }
113
114
        if (!empty($res)) {
115
            return implode($glue, $res);
0 ignored issues
show
Bug introduced by
It seems like $glue can also be of type null; however, parameter $glue of implode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
            return implode(/** @scrutinizer ignore-type */ $glue, $res);
Loading history...
116
        }
117
118
        return null;
119
    }
120
121
    /**
122
     * Strip FR lang
123
     *
124
     * @param string|null $lang
125
     *
126
     * @return string|null
127
     */
128
    private function stripLangFR(?string $lang = null): ?string
129
    {
130
        return ('fr' !== $lang) ? $lang : null;
131
    }
132
133
    /**
134
     * Convert number of pages.
135
     * "1 vol. (126 p.)".
136
     *
137
     * @return string|null
138
     */
139
    private function convertPages(): ?string
140
    {
141
        $raw = $this->xpath2string('//mxc:datafield[@tag="215"]/mxc:subfield[@code="a"]');
142
        if (!empty($raw) && preg_match('#([0-9]{2,}) p\.#', $raw, $matches) > 0) {
143
            return (string)$matches[1];
144
        }
145
146
        return null;
147
    }
148
149
    /**
150
     * todo gestion bilingue fr+en
151
     * ISO 639-1 http://www.loc.gov/standards/iso639-2/php/French_list.php.
152
     *
153
     * @param string|null $lang
154
     *
155
     * @return string|null
156
     */
157
    private function lang2wiki(?string $lang = null): ?string
158
    {
159
        if (!empty($lang)) {
160
            return Language::iso2b2wiki($lang);
161
        }
162
163
        return null;
164
    }
165
166
    private function getPublisher(): ?string
167
    {
168
        // zone 210
169
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="210"]/mxc:subfield[@code="c"]', ' / ')) {
170
            return $tac;
171
        }
172
        // 214 : nouvelle zone 2019
173
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="214"]/mxc:subfield[@code="c"]', ' / ')) {
174
            return $tac;
175
        }
176
177
        // 219 ancienne zone ?
178
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="219"]/mxc:subfield[@code="c"]', ' / ')) {
179
            return $tac;
180
        }
181
182
        return null;
183
    }
184
185
    private function getLocation(): ?string
186
    {
187
        // zone 210
188
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="210"]/mxc:subfield[@code="a"]', '/')) {
189
            return $tac;
190
        }
191
        // 214 : nouvelle zone 2019
192
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="214"]/mxc:subfield[@code="a"]', '/')) {
193
            return $tac;
194
        }
195
        // ancienne zone ?
196
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="219"]/mxc:subfield[@code="a"]', '/')) {
197
            return $tac;
198
        }
199
200
        return null;
201
    }
202
203
    private function getPublishDate(): ?string
204
    {
205
        // zone 210 d : Date de publication, de diffusion, etc.
206
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="210"]/mxc:subfield[@code="d"][1]')) {
207
            return $tac;
208
        }
209
        // 214 : nouvelle zone 2019
210
        if ($tac = $this->xpath2string('//mxc:datafield[@tag="214"]/mxc:subfield[@code="d"][1]')) {
211
            return $tac;
212
        }
213
214
        return null;
215
    }
216
217
    private function convertBnfIdent(): ?string
0 ignored issues
show
Unused Code introduced by
The method convertBnfIdent() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
218
    {
219
        // ark:/12148/cb453986124
220
        $raw = $this->xpath2string('//srw:recordIdentifier[1]/text()');
221
222
        if ($raw && preg_match('#ark:/[0-9]+/cb([0-9]+)#', $raw, $matches) > 0) {
223
            return (string)$matches[1];
224
        }
225
226
        return null;
227
    }
228
}
229