Passed
Pull Request — master (#195)
by
unknown
07:40
created

AbstractImporter   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 299
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 86
dl 0
loc 299
rs 9.76
c 2
b 0
f 0
wmc 33

10 Methods

Rating   Name   Duplication   Size   Complexity  
A typeItems() 0 11 2
A deactivateProcessNumberGeneration() 0 3 1
A getXsltFilePath() 0 16 3
A createDocument() 0 28 3
A __construct() 0 4 1
A import() 0 19 3
A transformToInternalXml() 0 30 4
B determineIdentifierType() 0 35 11
A activateProcessNumberGeneration() 0 3 1
A determineDocumentType() 0 25 4
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 EWW\Dpf\Domain\Model\ExternalMetadata;
20
use EWW\Dpf\Services\Transformer\DocumentTransformer;
21
use EWW\Dpf\Services\ProcessNumber\ProcessNumberGenerator;
22
use EWW\Dpf\Domain\Model\Document;
23
use EWW\Dpf\Domain\Model\DocumentType;
24
use EWW\Dpf\Domain\Workflow\DocumentWorkflow;
25
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
26
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
27
use TYPO3\CMS\Core\Utility\GeneralUtility;
28
use TYPO3\CMS\Core\Log\LogManager;
29
30
31
abstract class AbstractImporter
32
{
33
    /**
34
     * objectManager
35
     *
36
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
37
     * @inject
38
     */
39
    protected $objectManager = null;
40
41
    /**
42
     * clientRepository
43
     *
44
     * @var \EWW\Dpf\Domain\Repository\ClientRepository
45
     * @inject
46
     */
47
    protected $clientRepository = null;
48
49
    /**
50
     * documentTypeRepository
51
     *
52
     * @var \EWW\Dpf\Domain\Repository\DocumentTypeRepository
53
     * @inject
54
     */
55
    protected $documentTypeRepository = null;
56
57
    /**
58
     * clientConfigurationManager
59
     *
60
     * @var \EWW\Dpf\Configuration\ClientConfigurationManager
61
     * @inject
62
     */
63
    protected $clientConfigurationManager;
64
65
    /**
66
     * security
67
     *
68
     * @var \EWW\Dpf\Security\Security
69
     * @inject
70
     */
71
    protected $security = null;
72
73
    /**
74
     * logger
75
     *
76
     * @var \TYPO3\CMS\Core\Log\Logger
77
     */
78
    protected $logger = null;
79
80
    /**
81
     * @var bool
82
     */
83
    protected $generateProcessNumber = true;
84
85
    public function __construct()
86
    {
87
        /** @var $logger \TYPO3\CMS\Core\Log\Logger */
88
        $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
89
    }
90
91
    /**
92
     * Returns the list of publication types: ( ['type','"type"'] ).
93
     * @param array $types
94
     * @return array
95
     */
96
    public static function typeItems($types)
97
    {
98
        $items = [];
99
100
        foreach ($types as $type) {
101
            $items[] = [
102
                $type, '"'.$type.'"'
103
            ];
104
        }
105
106
        return $items;
107
    }
108
109
    /**
110
     * @param ExternalMetadata $metadata
111
     * @param DocumentType $documentType
112
     * @return Document
113
     * @throws \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException
114
     */
115
    public function import($metadata, $documentType = null)
116
    {
117
        $publicationType = $metadata->getPublicationType();
118
119
        if (empty($documentType)) {
120
            $documentType = $this->determineDocumentType($publicationType);
121
        }
122
123
        $xml = $this->transformToInternalXml($metadata->getData(), $documentType);
124
125
        if ($xml) {
126
            /** @var Document $document */
127
            $document = $this->createDocument($xml, $documentType);
128
            $document->setDocumentType($documentType);
0 ignored issues
show
Bug introduced by
It seems like $documentType can also be of type null; however, parameter $documentType of EWW\Dpf\Domain\Model\Document::setDocumentType() does only seem to accept EWW\Dpf\Domain\Model\DocumentType, 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

128
            $document->setDocumentType(/** @scrutinizer ignore-type */ $documentType);
Loading history...
129
130
            return $document;
131
        }
132
133
        return null;
134
    }
135
136
    /**
137
     * @param string $xml
138
     * @param DocumentType $documentType
139
     * @return string|null $metadataXml
140
     */
141
    public function transformToInternalXml($xml, $documentType)
142
    {
143
        /** @var DocumentTransformer $documentTransformer */
144
        $documentTransformer = new DocumentTransformer();
145
146
        $internalXml = '';
147
148
        if ($xml && $documentType instanceof DocumentType) {
149
150
            // $ownerId is currently not needed for the purpose of importing new documents
151
            //$ownerId = $this->clientConfigurationManager->getOwnerId();
152
153
            $transformParams = [
154
                'document_type' => $documentType->getName(),
155
                // Currently not needed parameters for the purpose of importing new documents
156
                //'record_state' => $remoteState,
157
                //'owner_id' => $ownerId,
158
                //'process_number' => $processNumber,
159
            ];
160
161
            $xsltFilePath = $this->getXsltFilePath($documentType);
162
163
            if ($xsltFilePath) {
164
                $internalXml = $documentTransformer->transform($xsltFilePath, $xml, $transformParams);
165
            }
166
167
            return($internalXml);
168
        }
169
170
        return null;
171
    }
172
173
    /**
174
     * @param string $xmlData
175
     * @param DocumentType $documentType
176
     * @return Document
177
     * @throws \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException
178
     */
179
    protected function createDocument($xmlData, $documentType)
180
    {
181
        /* @var $newDocument \EWW\Dpf\Domain\Model\Document */
182
        $newDocument    =  $this->objectManager->get(Document::class);
183
184
        $internalFormat = new \EWW\Dpf\Helper\InternalFormat($xmlData);
185
186
        // xml data fields are limited to 64 KB
187
        if (strlen($internalFormat->getXml()) >= 64 * 1024) {
188
            throw new \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException("Maximum document size exceeded.");
189
        }
190
191
        $newDocument->setTitle($internalFormat->getTitle());
192
        $newDocument->setAuthors($internalFormat->getAuthors());
193
        $newDocument->setDocumentType($documentType);
194
195
        $newDocument->setXmlData($internalFormat->getXml());
196
        $newDocument->setCreator($this->security->getUser()->getUid());
197
198
        $newDocument->setState(DocumentWorkflow::STATE_NEW_NONE);
199
200
        if ($this->generateProcessNumber) {
201
            $processNumberGenerator = $this->objectManager->get(ProcessNumberGenerator::class);
202
            $processNumber = $processNumberGenerator->getProcessNumber();
203
            $newDocument->setProcessNumber($processNumber);
204
        }
205
206
        return $newDocument;
207
    }
208
209
    /**
210
     * @return \EWW\Dpf\Domain\Model\TransformationFile
211
     */
212
    protected abstract function getDefaultXsltTransformation();
213
214
    /**
215
     * @return string
216
     */
217
    protected abstract function getDefaultXsltFilePath();
218
219
    /**
220
     * @param DocumentType $documentType
221
     * @return string
222
     */
223
    protected function getXsltFilePath(DocumentType $documentType)
224
    {
225
        /** @var \EWW\Dpf\Domain\Model\TransformationFile $xsltTransformationFile */
226
        $xsltTransformationFile = $documentType->getCrossrefTransformation()->current();
227
228
        if (empty($xsltTransformationFile)) {
229
            $xsltTransformationFile = $this->getDefaultXsltTransformation();
230
        }
231
232
        if ($xsltTransformationFile) {
0 ignored issues
show
introduced by
$xsltTransformationFile is of type EWW\Dpf\Domain\Model\TransformationFile, thus it always evaluated to true.
Loading history...
233
            return PATH_site . 'fileadmin' . $xsltTransformationFile->getFile()->getOriginalResource()->getIdentifier();
234
        } else {
235
            return $this->getDefaultXsltFilePath();
236
        }
237
238
        return '';
0 ignored issues
show
Unused Code introduced by
return '' is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
239
    }
240
241
    /**
242
     * @return string
243
     */
244
    protected abstract function getImporterName();
245
246
247
    /**
248
     * @param string $publicationType
249
     * @return DocumentType|null
250
     */
251
    protected function determineDocumentType($publicationType) : ?DocumentType
252
    {
253
        $documentType = null;
254
255
        // Get the target document type.
256
        if ($publicationType) {
257
            $documentType = $this->documentTypeRepository->findOneByExternalType(
258
                $publicationType, $this->getImporterName().'_types'
259
            );
260
        }
261
262
        if (!$documentType) {
263
            $configurationManager = $this->objectManager->get(ConfigurationManager::class);
264
            $settings = $configurationManager->getConfiguration(
265
                ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS
266
            );
267
268
            if (array_key_exists('defaultImportDocumentType', $settings)) {
269
                $documentType = $this->documentTypeRepository->findByUid(
270
                    $settings['defaultImportDocumentType'][$this->getImporterName()]
271
                );
272
            }
273
        }
274
        
275
        return $documentType;
276
    }
277
278
279
    /**
280
     * Determines whether the identifier is a DOI, ISBN or PMID.
281
     *
282
     * @param $identifier
283
     * @return null|string
284
     */
285
    static function determineIdentifierType($identifier)
286
    {
287
        // DOI
288
        if (strpos($identifier,'10.') === 0) {
289
            return 'DOI';
290
        }
291
292
        // ISBN
293
        $length = strlen(str_replace(['-',' '], '', $identifier));
294
295
        if ($length === 13) {
296
            if (strpos($identifier, '978') === 0 ||  strpos($identifier, '979') === 0) {
297
                return 'ISBN';
298
            }
299
        }
300
301
        if ($length === 10) {
302
            return 'ISBN';
303
        }
304
305
        $length = strlen(trim($identifier));
306
        if ($length === 9) {
307
            if (strpos($identifier, '-') === 4) {
308
                return 'ISSN';
309
            }
310
        }
311
312
        // PMID
313
        if (is_numeric($identifier) && intval($identifier) == $identifier) {
314
            if (strlen($identifier) < 10) {
315
                return 'PMID';
316
            }
317
        }
318
319
        return null;
320
    }
321
322
    public function activateProcessNumberGeneration()
323
    {
324
        $this->generateProcessNumber = true;
325
    }
326
327
    public function deactivateProcessNumberGeneration()
328
    {
329
        $this->generateProcessNumber = false;
330
    }
331
}
332