Passed
Pull Request — master (#195)
by
unknown
06:45
created

CrossRefImporter::findByIdentifier()   A

Complexity

Conditions 5
Paths 13

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 19
c 1
b 0
f 0
nc 13
nop 1
dl 0
loc 32
rs 9.3222
1
<?php
2
namespace EWW\Dpf\Services\ImportExternalMetadata;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
\Httpful\Bootstrap::init();
18
19
use \Httpful\Request;
20
use Symfony\Component\Serializer\Encoder\XmlEncoder;
21
use EWW\Dpf\Domain\Model\CrossRefMetadata;
22
use EWW\Dpf\Domain\Model\ExternalMetadata;
23
24
class CrossRefImporter extends AbstractImporter implements Importer
25
{
26
    /**
27
     * @var string
28
     */
29
    protected $apiUrl = "https://api.crossref.org";
30
31
    /**
32
     * @var string
33
     */
34
    protected $resource = "/works";
35
36
    /**
37
     * Returns the list of all publication types
38
     *
39
     * @return array
40
     */
41
    public static function types()
42
    {
43
        return [
44
            'book-section',
45
            'monograph',
46
            'report',
47
            'peer-review',
48
            'book-track',
49
            'journal-article',
50
            'book-part',
51
            'other',
52
            'book',
53
            'journal-volume',
54
            'book-set',
55
            'reference-entry',
56
            'proceedings-article',
57
            'journal',
58
            'component',
59
            'book-chapter',
60
            'proceedings-series',
61
            'report-series',
62
            'proceedings',
63
            'standard',
64
            'reference-book',
65
            'posted-content',
66
            'journal-issue',
67
            'dissertation',
68
            'dataset',
69
            'book-series',
70
            'edited-book',
71
            'standard-series'
72
        ];
73
    }
74
75
    /**
76
     * @param string $identifier
77
     * @return ExternalMetadata|null
78
     */
79
    public function findByIdentifier($identifier)
80
    {
81
        try {
82
            $response = Request::get($this->apiUrl . $this->resource . "/".$identifier)->send();
83
84
            if (!$response->hasErrors() && $response->code == 200) {
85
                $jsonString = $response->__toString();
86
                if ($jsonString) {
87
                    $data = json_decode($response->__toString(),true);
88
                    $encoder = new XmlEncoder();
89
90
                    /** @var CrossRefMetadata $crossRefMetadata */
91
                    $crossRefMetadata = $this->objectManager->get(CrossRefMetadata::class);
92
93
                    $crossRefMetadata->setSource(get_class($this));
94
                    $crossRefMetadata->setFeUser($this->security->getUser()->getUid());
95
                    $crossRefMetadata->setData($encoder->encode($data, 'xml'));
96
                    $crossRefMetadata->setPublicationIdentifier($identifier);
97
98
                    return $crossRefMetadata;
99
                }
100
101
            } else {
102
                return null;
103
            }
104
105
        } catch (\Throwable $throwable) {
106
            $this->logger->error($throwable->getMessage());
107
            throw $throwable;
108
        }
109
110
        return null;
111
    }
112
113
114
    /**
115
     * @param string $query
116
     * @param int $rows
117
     * @param int $offset
118
     * @param string $searchField
119
     * @return array|mixed
120
     * @throws \Throwable
121
     */
122
    public function search($query, $rows = 10, $offset = 0, $searchField = 'author')
123
    {
124
        $requestUri = $this->apiUrl . $this->resource . '?rows='.$rows;
125
126
        if ($offset > 0) $requestUri .= '&offset=' . $offset;
127
128
        if ($searchField) {
129
           $requestUri .= '&query.'.$searchField.'='.urlencode($query);
130
        } else {
131
            switch (PublicationIdentifier::determineIdentifierType(trim($query))) {
132
                case 'DOI':
133
                    $requestUri .= "&filter=doi:".urlencode(trim($query));
134
                    break;
135
                case 'ISBN':
136
                    $isbn = str_replace(['-',' '], '', $query);
137
                    $requestUri .= "&filter=isbn:".$isbn;
138
                    break;
139
                case 'ISSN':
140
                    $requestUri .= "&filter=issn:".trim($query);
141
                    break;
142
                default:
143
                    $requestUri .= "&query=".urlencode($query);
144
                    break;
145
            }
146
        }
147
148
        try {
149
            $response = Request::get($requestUri)->send();
150
151
            if (!$response->hasErrors() && $response->code == 200) {
152
153
                $jsonString = $response->__toString();
154
                if ($jsonString) {
155
156
                    $data = json_decode($response->__toString(),true);
157
                    $encoder = new XmlEncoder();
158
159
                    if ($data['message']['total-results'] < 1) {
160
                        return [];
161
                    }
162
163
                    foreach ($data['message']['items'] as $item) {
164
165
                        /** @var CrossRefMetadata $crossRefMetadata */
166
                        $crossRefMetadata = $this->objectManager->get(CrossRefMetadata::class);
167
168
                        $crossRefMetadata->setSource(get_class($this));
169
                        $crossRefMetadata->setFeUser($this->security->getUser()->getUid());
170
                        $crossRefMetadata->setData($encoder->encode(['message' => $item], 'xml'));
171
                        $crossRefMetadata->setPublicationIdentifier($item['DOI']);
172
173
                        $results['items'][$crossRefMetadata->getPublicationIdentifier()] = $crossRefMetadata;
174
                    }
175
176
                    $results['total-results'] = $data['message']['total-results'];
177
                    $results['items-per-page'] = $data['message']['items-per-page'];
178
179
                    // Because the CrossRef api does not allow an offset more than 10000 we need to limit the result total
180
                    $maxPages = ceil(10000 / $results['items-per-page']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $results seems to be defined by a foreach iteration on line 163. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
181
                    $pages = ceil($results['total-results'] / $results['items-per-page']);
182
                    if ($pages > $maxPages) {
183
                        $results['total-results'] = $maxPages *  $results['items-per-page'];
184
                    }
185
186
                    return $results;
187
                }
188
189
            } else {
190
                return [];
191
            }
192
193
        } catch (\Throwable $throwable) {
194
            $this->logger->error($throwable->getMessage());
195
            throw $throwable;
196
        }
197
198
        return [];
199
    }
200
201
202
    /**
203
     * @return \EWW\Dpf\Domain\Model\TransformationFile
204
     */
205
    protected function getDefaultXsltTransformation() : ?\EWW\Dpf\Domain\Model\TransformationFile
206
    {
207
        /** @var \EWW\Dpf\Domain\Model\Client $client */
208
        $client = $this->clientRepository->findAll()->current();
209
210
        /** @var \EWW\Dpf\Domain\Model\TransformationFile $xsltTransformationFile */
211
        return $client->getCrossrefTransformation()->current();
212
    }
213
214
    /**
215
     * @return string
216
     */
217
    protected function getDefaultXsltFilePath() : string
218
    {
219
        return \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName(
220
                'EXT:dpf/Resources/Private/Xslt/crossref-default.xsl'
221
        );
222
    }
223
224
    /**
225
     * @return string
226
     */
227
    protected function getImporterName()
228
    {
229
        return 'crossref';
230
    }
231
232
}
233