Passed
Pull Request — master (#123)
by Sebastian
03:55
created

Mods::getHolders()   C

Complexity

Conditions 15
Paths 6

Size

Total Lines 49
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 15
eloc 38
c 4
b 0
f 0
nc 6
nop 0
dl 0
loc 49
rs 5.9166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
                    $profile = new OrcidProfile((string) $identifier[0]);
89
                    $this->metadata['author'][$i] = $profile->getFullName();
90
                } else {
91
                    // Check if there is a display form.
92
                    if (($displayForm = $authors[$i]->xpath('./mods:displayForm'))) {
93
                        $this->metadata['author'][$i] = (string) $displayForm[0];
94
                    } elseif (($nameParts = $authors[$i]->xpath('./mods:namePart'))) {
95
                        $name = [];
96
                        $k = 4;
97
                        foreach ($nameParts as $namePart) {
98
                            if (
99
                                isset($namePart['type'])
100
                                && (string) $namePart['type'] == 'family'
101
                            ) {
102
                                $name[0] = (string) $namePart;
103
                            } elseif (
104
                                isset($namePart['type'])
105
                                && (string) $namePart['type'] == 'given'
106
                            ) {
107
                                $name[1] = (string) $namePart;
108
                            } elseif (
109
                                isset($namePart['type'])
110
                                && (string) $namePart['type'] == 'termsOfAddress'
111
                            ) {
112
                                $name[2] = (string) $namePart;
113
                            } elseif (
114
                                isset($namePart['type'])
115
                                && (string) $namePart['type'] == 'date'
116
                            ) {
117
                                $name[3] = (string) $namePart;
118
                            } else {
119
                                $name[$k] = (string) $namePart;
120
                            }
121
                            $k++;
122
                        }
123
                        ksort($name);
124
                        $this->metadata['author'][$i] = trim(implode(', ', $name));
125
                    }
126
                    // Append "valueURI" to name using Unicode unit separator.
127
                    if (isset($authors[$i]['valueURI'])) {
128
                        $this->metadata['author'][$i] .= chr(31) . (string) $authors[$i]['valueURI'];
129
                    }
130
                }
131
            }
132
        }
133
    }
134
135
    /**
136
     * Get holder.
137
     *
138
     * @access private
139
     *
140
     * @return void
141
     */
142
    private function getHolders() {
143
        $holders = $this->xml->xpath('./mods:name[./mods:role/mods:roleTerm[@type="code" and @authority="marcrelator"]="prv"]');
144
145
        if (!empty($holders)) {
146
            for ($i = 0, $j = count($holders); $i < $j; $i++) {
147
                $holders[$i]->registerXPathNamespace('mods', 'http://www.loc.gov/mods/v3');
148
149
                $identifier = $holders[$i]->xpath('./mods:name/mods:nameIdentifier[@type="viaf"]');
150
                if (!empty((string) $identifier[0])) {
151
                    $viaf = (string) $identifier[0];
152
                    $profile = new ViafProfile($viaf);
153
                    $this->metadata['holder'][$i] = $profile->getFullName();
154
                } else {
155
                    // Check if there is a display form.
156
                    if (($displayForm = $holders[$i]->xpath('./mods:displayForm'))) {
157
                        $this->metadata['holder'][$i] = (string) $displayForm[0];
158
                    } elseif (($nameParts = $holders[$i]->xpath('./mods:namePart'))) {
159
                        $name = [];
160
                        $k = 4;
161
                        foreach ($nameParts as $namePart) {
162
                            if (
163
                                isset($namePart['type'])
164
                                && (string) $namePart['type'] == 'family'
165
                            ) {
166
                                $name[0] = (string) $namePart;
167
                            } elseif (
168
                                isset($namePart['type'])
169
                                && (string) $namePart['type'] == 'given'
170
                            ) {
171
                                $name[1] = (string) $namePart;
172
                            } elseif (
173
                                isset($namePart['type'])
174
                                && (string) $namePart['type'] == 'termsOfAddress'
175
                            ) {
176
                                $name[2] = (string) $namePart;
177
                            } elseif (
178
                                isset($namePart['type'])
179
                                && (string) $namePart['type'] == 'date'
180
                            ) {
181
                                $name[3] = (string) $namePart;
182
                            } else {
183
                                $name[$k] = (string) $namePart;
184
                            }
185
                            $k++;
186
                        }
187
                        $k++;
188
                    }
189
                    ksort($name);
190
                    $this->metadata['holder'][$i] = trim(implode(', ', $name));
191
                }
192
            }
193
        }
194
    }
195
196
    /**
197
     * Get "place" and "place_sorting".
198
     *
199
     * @access private
200
     *
201
     * @return void
202
     */
203
    private function getPlaces() {
204
        $places = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:place/mods:placeTerm');
205
        // Get "place" and "place_sorting" again if that was to sophisticated.
206
        if (empty($places)) {
207
            // Get all places and assume these are places of publication.
208
            $places = $this->xml->xpath('./mods:originInfo/mods:place/mods:placeTerm');
209
        }
210
        if (!empty($places)) {
211
            foreach ($places as $place) {
212
                $this->metadata['place'][] = (string) $place;
213
                if (!$this->metadata['place_sorting'][0]) {
214
                    $this->metadata['place_sorting'][0] = preg_replace('/[[:punct:]]/', '', (string) $place);
215
                }
216
            }
217
        }
218
    }
219
220
    /**
221
     * Get "year" and "year_sorting".
222
     *
223
     * @access private
224
     *
225
     * @return void
226
     */
227
    private function getYears() {
228
        // Get "year_sorting".
229
        if (($years_sorting = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateOther[@type="order" and @encoding="w3cdtf"]'))) {
230
            foreach ($years_sorting as $year_sorting) {
231
                $this->metadata['year_sorting'][0] = intval($year_sorting);
232
            }
233
        }
234
        // Get "year" and "year_sorting" if not specified separately.
235
        $years = $this->xml->xpath('./mods:originInfo[not(./mods:edition="[Electronic ed.]")]/mods:dateIssued[@keyDate="yes"]');
236
        // Get "year" and "year_sorting" again if that was to sophisticated.
237
        if (empty($years)) {
238
            // Get all dates and assume these are dates of publication.
239
            $years = $this->xml->xpath('./mods:originInfo/mods:dateIssued');
240
        }
241
        if (!empty($years)) {
242
            foreach ($years as $year) {
243
                $this->metadata['year'][] = (string) $year;
244
                if (!$this->metadata['year_sorting'][0]) {
245
                    $year_sorting = str_ireplace('x', '5', preg_replace('/[^\d.x]/i', '', (string) $year));
246
                    if (
247
                        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

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

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

250
                        $year_sorting = ((intval(trim(/** @scrutinizer ignore-type */ $year_sorting, '.')) - 1) * 100) + 50;
Loading history...
251
                    }
252
                    $this->metadata['year_sorting'][0] = intval($year_sorting);
253
                }
254
            }
255
        }
256
    }
257
}
258