Passed
Pull Request — master (#123)
by Sebastian
04:20 queued 32s
created

Mods::getAuthorFromOrcidApi()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 11
rs 10
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 as OrcidProfile;
16
use Kitodo\Dlf\Api\Viaf\Profile as ViafProfile;
17
18
/**
19
 * Metadata MODS format class for the 'dlf' extension
20
 *
21
 * @author Sebastian Meyer <[email protected]>
22
 * @package TYPO3
23
 * @subpackage dlf
24
 * @access public
25
 */
26
class Mods implements \Kitodo\Dlf\Common\MetadataInterface
27
{
28
    /**
29
     * The metadata XML
30
     *
31
     * @var \SimpleXMLElement
32
     **/
33
    private $xml;
34
35
    /**
36
     * The metadata array
37
     *
38
     * @var array
39
     **/
40
    private $metadata;
41
42
    /**
43
     * This extracts the essential MODS metadata from XML
44
     *
45
     * @access public
46
     *
47
     * @param \SimpleXMLElement $xml: The XML to extract the metadata from
48
     * @param array &$metadata: The metadata array to fill
49
     *
50
     * @return void
51
     */
52
    public function extractMetadata(\SimpleXMLElement $xml, array &$metadata)
53
    {
54
        $this->xml = $xml;
55
        $this->metadata = $metadata;
56
57
        $this->xml->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
58
59
        $this->getAuthors();
60
        $this->getHolders();
61
        $this->getPlaces();
62
        $this->getYears();
63
64
        $metadata = $this->metadata;
65
    }
66
67
    /**
68
     * Get "author" and "author_sorting".
69
     *
70
     * @access private
71
     *
72
     * @return void
73
     */
74
    private function getAuthors() {
75
        $authors = $this->xml->xpath('./mods:name[./mods:role/mods:roleTerm[@type="code" and @authority="marcrelator"]="aut"]');
76
77
        // Get "author" and "author_sorting" again if that was too sophisticated.
78
        if (empty($authors)) {
79
            // Get all names which do not have any role term assigned and assume these are authors.
80
            $authors = $this->xml->xpath('./mods:name[not(./mods:role)]');
81
        }
82
        if (!empty($authors)) {
83
            for ($i = 0, $j = count($authors); $i < $j; $i++) {
84
                $authors[$i]->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
85
86
                $identifier = $authors[$i]->xpath('./mods:name/mods:nameIdentifier[@type="orcid"]');
87
                if (!empty((string) $identifier[0])) {
88
                    $this->getAuthorFromOrcidApi((string) $identifier[0], $authors, $i);
89
                } else {
90
                    $this->getAuthorFromXml($authors, $i);
91
                }
92
            }
93
        }
94
    }
95
96
    private function getAuthorFromOrcidApi($orcidId, $authors, $i) {
97
        $profile = new OrcidProfile($orcidId);
98
        $name = $profile->getFullName();
99
        if (!empty($name)) {
100
            $this->metadata['author'][$i] = [
101
                'name' => $name,
102
                'url' => 'https://orcid.org/' . $orcidId
103
            ];
104
        } else {
105
            //fallback into display form
106
            $this->getAuthorFromXmlDisplayForm($authors, $i);
107
        }
108
    }
109
110
    private function getAuthorFromXml($authors, $i) {
111
        $this->getAuthorFromXmlDisplayForm($authors, $i);
112
113
        $nameParts = $authors[$i]->xpath('./mods:namePart');
114
115
        if (empty($this->metadata['author'][$i]) && $nameParts) {
116
            $name = [];
117
            $k = 4;
118
            foreach ($nameParts as $namePart) {
119
                if (
120
                    isset($namePart['type'])
121
                    && (string) $namePart['type'] == 'family'
122
                ) {
123
                    $name[0] = (string) $namePart;
124
                } elseif (
125
                    isset($namePart['type'])
126
                    && (string) $namePart['type'] == 'given'
127
                ) {
128
                    $name[1] = (string) $namePart;
129
                } elseif (
130
                    isset($namePart['type'])
131
                    && (string) $namePart['type'] == 'termsOfAddress'
132
                ) {
133
                    $name[2] = (string) $namePart;
134
                } elseif (
135
                    isset($namePart['type'])
136
                    && (string) $namePart['type'] == 'date'
137
                ) {
138
                    $name[3] = (string) $namePart;
139
                } else {
140
                    $name[$k] = (string) $namePart;
141
                }
142
                $k++;
143
            }
144
            ksort($name);
145
            $this->metadata['author'][$i] = trim(implode(', ', $name));
146
        }
147
        // Append "valueURI" to name using Unicode unit separator.
148
        if (isset($authors[$i]['valueURI'])) {
149
            $this->metadata['author'][$i] .= chr(31) . (string) $authors[$i]['valueURI'];
150
        }
151
    }
152
153
    private function getAuthorFromXmlDisplayForm($authors, $i) {
154
        $displayForm = $authors[$i]->xpath('./mods:displayForm');
155
        if ($displayForm) {
156
            $this->metadata['author'][$i] = (string) $displayForm[0];
157
        }
158
    }
159
160
    /**
161
     * Get holder.
162
     *
163
     * @access private
164
     *
165
     * @return void
166
     */
167
    private function getHolders() {
168
        $holders = $this->xml->xpath('./mods:name[./mods:role/mods:roleTerm[@type="code" and @authority="marcrelator"]="prv"]');
169
170
        if (!empty($holders)) {
171
            for ($i = 0, $j = count($holders); $i < $j; $i++) {
172
                $holders[$i]->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
173
174
                $identifier = $holders[$i]->xpath('./mods:name/mods:nameIdentifier[@type="viaf"]');
175
                if (!empty((string) $identifier[0])) {
176
                    $this->getHolderFromViafApi((string) $identifier[0], $holders, $i);
177
                } else {
178
                    $this->getHolderFromXml($holders, $i);
179
                }
180
            }
181
        }
182
    }
183
184
    private function getHolderFromViafApi($viafId, $holders, $i) {
185
        $profile = new ViafProfile($viafId);
186
        $name = $profile->getFullName();
187
        if (!empty($name)) {
188
            $this->metadata['holder'][$i] = [
189
                'name' => $name,
190
                'url' => 'http://viaf.org/viaf/' . $viafId
191
            ];
192
        } else {
193
            //fallback into display form
194
            $this->getHolderFromXmlDisplayForm($holders, $i);
195
        }
196
    }
197
198
    private function getHolderFromXml($holders, $i) {
199
        $this->getHolderFromXmlDisplayForm($holders, $i);
200
        // Append "valueURI" to name using Unicode unit separator.
201
        if (isset($holders[$i]['valueURI'])) {
202
            $this->metadata['holder'][$i] .= chr(31) . (string) $holders[$i]['valueURI'];
203
        }
204
    }
205
206
    private function getHolderFromXmlDisplayForm($holders, $i) {
207
        // Check if there is a display form.
208
        $displayForm = $holders[$i]->xpath('./mods:displayForm');
209
        if ($displayForm) {
210
            $this->metadata['holder'][$i] = (string) $displayForm[0];
211
        }
212
    }
213
214
    /**
215
     * Get "place" and "place_sorting".
216
     *
217
     * @access private
218
     *
219
     * @return void
220
     */
221
    private function getPlaces() {
222
        $places = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:place/mods:placeTerm');
223
        // Get "place" and "place_sorting" again if that was to sophisticated.
224
        if (empty($places)) {
225
            // Get all places and assume these are places of publication.
226
            $places = $this->xml->xpath('./mods:originInfo/mods:place/mods:placeTerm');
227
        }
228
        if (!empty($places)) {
229
            foreach ($places as $place) {
230
                $this->metadata['place'][] = (string) $place;
231
                if (!$this->metadata['place_sorting'][0]) {
232
                    $this->metadata['place_sorting'][0] = preg_replace('/[[:punct:]]/', '', (string) $place);
233
                }
234
            }
235
        }
236
    }
237
238
    /**
239
     * Get "year" and "year_sorting".
240
     *
241
     * @access private
242
     *
243
     * @return void
244
     */
245
    private function getYears() {
246
        // Get "year_sorting".
247
        if (($years_sorting = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateOther[@type="order" and @encoding="w3cdtf"]'))) {
248
            foreach ($years_sorting as $year_sorting) {
249
                $this->metadata['year_sorting'][0] = intval($year_sorting);
250
            }
251
        }
252
        // Get "year" and "year_sorting" if not specified separately.
253
        $years = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateIssued[@keyDate="yes"]');
254
        // Get "year" and "year_sorting" again if that was to sophisticated.
255
        if (empty($years)) {
256
            // Get all dates and assume these are dates of publication.
257
            $years = $this->xml->xpath('./mods:originInfo/mods:dateIssued');
258
        }
259
        if (!empty($years)) {
260
            foreach ($years as $year) {
261
                $this->metadata['year'][] = (string) $year;
262
                if (!$this->metadata['year_sorting'][0]) {
263
                    $year_sorting = str_ireplace('x', '5', preg_replace('/[^\d.x]/i', '', (string) $year));
264
                    if (
265
                        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

265
                        strpos(/** @scrutinizer ignore-type */ $year_sorting, '.')
Loading history...
266
                        || 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

266
                        || strlen(/** @scrutinizer ignore-type */ $year_sorting) < 3
Loading history...
267
                    ) {
268
                        $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

268
                        $year_sorting = ((intval(trim(/** @scrutinizer ignore-type */ $year_sorting, '.')) - 1) * 100) + 50;
Loading history...
269
                    }
270
                    $this->metadata['year_sorting'][0] = intval($year_sorting);
271
                }
272
            }
273
        }
274
    }
275
}
276