Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#829)
by Beatrycze
03:34
created

Mods   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 323
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 131
c 4
b 0
f 0
dl 0
loc 323
rs 4.5599
wmc 58

11 Methods

Rating   Name   Duplication   Size   Complexity  
A extractMetadata() 0 18 1
A getIdentifier() 0 2 1
A getPlaces() 0 12 5
A getObjectLocationMetadata() 0 5 1
A getSingleMetadata() 0 5 3
B getYears() 0 26 9
D getAuthors() 0 60 19
A getDescription() 0 2 1
A getLicense() 0 2 1
A getObjectNames() 0 3 1
C getHolders() 0 49 16

How to fix   Complexity   

Complex Class

Complex classes like Mods often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Mods, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Format;
14
15
use Kitodo\Dlf\Api\Orcid\Profile;
16
17
/**
18
 * Metadata MODS format class for the 'dlf' extension
19
 *
20
 * @author Sebastian Meyer <[email protected]>
21
 * @package TYPO3
22
 * @subpackage dlf
23
 * @access public
24
 */
25
class Mods implements \Kitodo\Dlf\Common\MetadataInterface
26
{
27
    /**
28
     * The metadata XML
29
     *
30
     * @var \SimpleXMLElement
31
     **/
32
    private $xml;
33
34
    /**
35
     * The metadata array
36
     *
37
     * @var array
38
     **/
39
    private $metadata;
40
41
    /**
42
     * This extracts the essential MODS metadata from XML
43
     *
44
     * @access public
45
     *
46
     * @param \SimpleXMLElement $xml: The XML to extract the metadata from
47
     * @param array &$metadata: The metadata array to fill
48
     *
49
     * @return void
50
     */
51
    public function extractMetadata(\SimpleXMLElement $xml, array &$metadata)
52
    {
53
        $this->xml = $xml;
54
        $this->metadata = $metadata;
55
56
        $this->xml->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
57
58
        $this->getAuthors();
59
        $this->getHolders();
60
        $this->getPlaces();
61
        $this->getYears();
62
        $this->getDescription();
63
        $this->getIdentifier();
64
        $this->getLicense();
65
        $this->getObjectNames();
66
        $this->getObjectLocationMetadata();
67
68
        $metadata = $this->metadata;
69
    }
70
71
    /**
72
     * Get "author" and "author_sorting".
73
     *
74
     * @access private
75
     *
76
     * @return void
77
     */
78
    private function getAuthors() {
79
        $authors = $this->xml->xpath('./mods:name[./mods:role/mods:roleTerm[@type="code" and @authority="marcrelator"]="aut"]');
80
81
        // Get "author" and "author_sorting" again if that was too sophisticated.
82
        if (empty($authors)) {
83
            // Get all names which do not have any role term assigned and assume these are authors.
84
            $authors = $this->xml->xpath('./mods:name[not(./mods:role)]');
85
        }
86
87
        if (!empty($authors)) {
88
            for ($i = 0, $j = count($authors); $i < $j; $i++) {
89
                $authors[$i]->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
90
91
                $identifier = $authors[$i]->xpath('./mods:nameIdentifier');
92
                if ($identifier[0]['type'] == 'orcid' && !empty((string) $identifier[0])) {
93
                    $orcidIdParts = explode('/', (string) $identifier[0]);
94
                    $orcidId = trim(end($orcidIdParts));
95
                    if (!str_contains($orcidId, 'orcid=')) {
96
                        $profile = new Profile($orcidId);
97
                        $this->metadata['author'][$i] = $profile->getFullName();
98
                    }
99
                } else {
100
                    // Check if there is a display form.
101
                    if (($displayForm = $authors[$i]->xpath('./mods:displayForm'))) {
102
                        $this->metadata['author'][$i] = (string) $displayForm[0];
103
                    } elseif (($nameParts = $authors[$i]->xpath('./mods:namePart'))) {
104
                        $name = [];
105
                        $k = 4;
106
                        foreach ($nameParts as $namePart) {
107
                            if (
108
                                isset($namePart['type'])
109
                                && (string) $namePart['type'] == 'family'
110
                            ) {
111
                                $name[0] = (string) $namePart;
112
                            } elseif (
113
                                isset($namePart['type'])
114
                                && (string) $namePart['type'] == 'given'
115
                            ) {
116
                                $name[1] = (string) $namePart;
117
                            } elseif (
118
                                isset($namePart['type'])
119
                                && (string) $namePart['type'] == 'termsOfAddress'
120
                            ) {
121
                                $name[2] = (string) $namePart;
122
                            } elseif (
123
                                isset($namePart['type'])
124
                                && (string) $namePart['type'] == 'date'
125
                            ) {
126
                                $name[3] = (string) $namePart;
127
                            } else {
128
                                $name[$k] = (string) $namePart;
129
                            }
130
                            $k++;
131
                        }
132
                        ksort($name);
133
                        $this->metadata['author'][$i] = trim(implode(', ', $name));
134
                    }
135
                    // Append "valueURI" to name using Unicode unit separator.
136
                    if (isset($authors[$i]['valueURI'])) {
137
                        $this->metadata['author'][$i] .= chr(31) . (string) $authors[$i]['valueURI'];
138
                    }
139
                }
140
            }
141
        }
142
    }
143
144
    /**
145
     * Get holder.
146
     *
147
     * @access private
148
     *
149
     * @return void
150
     */
151
    private function getHolders() {
152
        $holders = $this->xml->xpath('./mods:name[./mods:role/mods:roleTerm[@type="code" and @authority="marcrelator"]="prv"]');
153
154
        if (!empty($holders)) {
155
            for ($i = 0, $j = count($holders); $i < $j; $i++) {
156
                $holders[$i]->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
157
158
                //$identifier = $holders[$i]->xpath('./mods:nameIdentifier');
159
                if (1 != 1) {
160
                    //TODO: reading VIAF API
161
                } else {
162
                    // Check if there is a display form.
163
                    if (($displayForm = $holders[$i]->xpath('./mods:displayForm'))) {
164
                        $this->metadata['holder'][$i] = (string) $displayForm[0];
165
                    } elseif (($nameParts = $holders[$i]->xpath('./mods:namePart'))) {
166
                        $name = [];
167
                        $k = 4;
168
                        foreach ($nameParts as $namePart) {
169
                            if (
170
                                isset($namePart['type'])
171
                                && (string) $namePart['type'] == 'family'
172
                            ) {
173
                                $name[0] = (string) $namePart;
174
                            } elseif (
175
                                isset($namePart['type'])
176
                                && (string) $namePart['type'] == 'given'
177
                            ) {
178
                                $name[1] = (string) $namePart;
179
                            } elseif (
180
                                isset($namePart['type'])
181
                                && (string) $namePart['type'] == 'termsOfAddress'
182
                            ) {
183
                                $name[2] = (string) $namePart;
184
                            } elseif (
185
                                isset($namePart['type'])
186
                                && (string) $namePart['type'] == 'date'
187
                            ) {
188
                                $name[3] = (string) $namePart;
189
                            } else {
190
                                $name[$k] = (string) $namePart;
191
                            }
192
                            $k++;
193
                        }
194
                        ksort($name);
195
                        $this->metadata['holder'][$i] = trim(implode(', ', $name));
196
                    }
197
                    // Append "valueURI" to name using Unicode unit separator.
198
                    if (isset($authors[$i]['valueURI'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $authors seems to never exist and therefore isset should always be false.
Loading history...
199
                        $this->metadata['holder'][$i] .= chr(31) . (string) $authors[$i]['valueURI'];
200
                    }
201
                }
202
            }
203
        }
204
    }
205
206
    /**
207
     * Get "place" and "place_sorting".
208
     *
209
     * @access private
210
     *
211
     * @return void
212
     */
213
    private function getPlaces() {
214
        $places = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:place/mods:placeTerm');
215
        // Get "place" and "place_sorting" again if that was to sophisticated.
216
        if (empty($places)) {
217
            // Get all places and assume these are places of publication.
218
            $places = $this->xml->xpath('./mods:originInfo/mods:place/mods:placeTerm');
219
        }
220
        if (!empty($places)) {
221
            foreach ($places as $place) {
222
                $this->metadata['place'][] = (string) $place;
223
                if (!$this->metadata['place_sorting'][0]) {
224
                    $this->metadata['place_sorting'][0] = preg_replace('/[[:punct:]]/', '', (string) $place);
225
                }
226
            }
227
        }
228
    }
229
230
    /**
231
     * Get "year" and "year_sorting".
232
     *
233
     * @access private
234
     *
235
     * @return void
236
     */
237
    private function getYears() {
238
        // Get "year_sorting".
239
        if (($years_sorting = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateOther[@type="order" and @encoding="w3cdtf"]'))) {
240
            foreach ($years_sorting as $year_sorting) {
241
                $this->metadata['year_sorting'][0] = intval($year_sorting);
242
            }
243
        }
244
        // Get "year" and "year_sorting" if not specified separately.
245
        $years = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateIssued[@keyDate="yes"]');
246
        // Get "year" and "year_sorting" again if that was to sophisticated.
247
        if (empty($years)) {
248
            // Get all dates and assume these are dates of publication.
249
            $years = $this->xml->xpath('./mods:originInfo/mods:dateIssued');
250
        }
251
        if (!empty($years)) {
252
            foreach ($years as $year) {
253
                $this->metadata['year'][] = (string) $year;
254
                if (!$this->metadata['year_sorting'][0]) {
255
                    $year_sorting = str_ireplace('x', '5', preg_replace('/[^\d.x]/i', '', (string) $year));
256
                    if (
257
                        strpos($year_sorting, '.')
0 ignored issues
show
Bug introduced by
It seems like $year_sorting can also be of type array; however, parameter $haystack of strpos() 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

257
                        strpos(/** @scrutinizer ignore-type */ $year_sorting, '.')
Loading history...
258
                        || strlen($year_sorting) < 3
0 ignored issues
show
Bug introduced by
It seems like $year_sorting can also be of type array; however, parameter $string of strlen() 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

258
                        || strlen(/** @scrutinizer ignore-type */ $year_sorting) < 3
Loading history...
259
                    ) {
260
                        $year_sorting = ((intval(trim($year_sorting, '.')) - 1) * 100) + 50;
0 ignored issues
show
Bug introduced by
It seems like $year_sorting can also be of type array; however, parameter $string of trim() 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

260
                        $year_sorting = ((intval(trim(/** @scrutinizer ignore-type */ $year_sorting, '.')) - 1) * 100) + 50;
Loading history...
261
                    }
262
                    $this->metadata['year_sorting'][0] = intval($year_sorting);
263
                }
264
            }
265
        }
266
    }
267
268
    /**
269
     * Get "description" stored in recordInfoNote.
270
     *
271
     * @access private
272
     *
273
     * @return void
274
     */
275
    private function getDescription() {
276
        $this->getSingleMetadata('description', './mods:recordInfo/mods:recordInfoNote/text()');
277
    }
278
279
    /**
280
     * Get "identifier" - example: hotels (built public accommodations), AAT ID: 300007166.
281
     *
282
     * @access private
283
     *
284
     * @return void
285
     */
286
    private function getIdentifier() {
287
        $this->getSingleMetadata('identifier', './mods:identifier/text()');
288
    }
289
290
    /**
291
     * Get "license" - license on which object is published.
292
     *
293
     * @access private
294
     *
295
     * @return void
296
     */
297
    private function getLicense() {
298
        $this->getSingleMetadata('license', './mods:accessCondition/text()');
299
    }
300
301
    /**
302
     * Get names of the original object:
303
     *   - main name
304
     *   - alternative names
305
     *
306
     * @access private
307
     *
308
     * @return void
309
     */
310
    private function getObjectNames() {
311
        $this->getSingleMetadata('object_name', './mods:relatedItem/mods:titleInfo[not(@displayLabel="alternative")]/mods:title/text()');
312
        $this->getSingleMetadata('object_alternative_names', './mods:relatedItem/mods:titleInfo[@displayLabel="alternative"]/mods:title/text()');
313
    }
314
315
    /**
316
     * Get location information about the original object:
317
     *  - city (object_location)
318
     *  - geonames
319
     *  - wikidata
320
     *  - wikipedia
321
     *
322
     * @access private
323
     *
324
     * @return void
325
     */
326
    private function getObjectLocationMetadata() {
327
        $this->getSingleMetadata('object_location', './mods:relatedItem/mods:location/mods:physicalLocation/text()');
328
        $this->getSingleMetadata('geonames', './mods:relatedItem/mods:location/mods:url[@displayLabel="geonames"]/text()');
329
        $this->getSingleMetadata('wikidata', './mods:relatedItem/mods:location/mods:url[@displayLabel="wikidata"]/text()');
330
        $this->getSingleMetadata('wikipedia', './mods:relatedItem/mods:location/mods:url[@displayLabel="wikipedia"]/text()');
331
    }
332
333
    /**
334
     * Save to the metadata array the last found matching metadata.
335
     *
336
     * @access private
337
     *
338
     * @param string $metadataIndex: The index in the array by which metadata is going to be accessible
339
     * @param string $xpath: The xpath for searching metadata in MODS
340
     *
341
     * @return void
342
     */
343
    private function getSingleMetadata($metadataIndex, $xpath) {
344
        $results = $this->xml->xpath($xpath);
345
        if (!empty($results)) {
346
            foreach ($results as $result) {
347
                $this->metadata[$metadataIndex][0] = (string) $result;
348
            }
349
        }
350
    }
351
}
352