Passed
Pull Request — master (#195)
by
unknown
19:15
created

ApiController   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 480
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 204
c 4
b 0
f 0
dl 0
loc 480
rs 6
wmc 55

11 Methods

Rating   Name   Duplication   Size   Complexity  
B importDoiWithoutSavingAction() 0 38 6
B importBibtexWithoutSavingAction() 0 47 8
A addFisIdAction() 0 26 3
B suggestionAction() 0 31 7
B importRisWithoutSavingAction() 0 47 8
B createAction() 0 42 7
A showAction() 0 21 3
A importIsbnWithoutSavingAction() 0 34 5
A checkToken() 0 9 2
A __construct() 0 4 1
A importPubmedWithoutSavingAction() 0 34 5

How to fix   Complexity   

Complex Class

Complex classes like ApiController 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 ApiController, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace EWW\Dpf\Controller;
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
use EWW\Dpf\Domain\Model\Document;
18
use EWW\Dpf\Services\ImportExternalMetadata\BibTexFileImporter;
19
use EWW\Dpf\Services\ImportExternalMetadata\CrossRefImporter;
20
use EWW\Dpf\Services\ImportExternalMetadata\DataCiteImporter;
21
use EWW\Dpf\Services\ImportExternalMetadata\FileImporter;
22
use EWW\Dpf\Services\ImportExternalMetadata\K10plusImporter;
23
use EWW\Dpf\Services\ImportExternalMetadata\PubMedImporter;
24
use EWW\Dpf\Services\ImportExternalMetadata\RisWosFileImporter;
25
use TYPO3\CMS\Core\Messaging\AbstractMessage;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
28
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
29
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
30
use TYPO3\CMS\Core\Log\LogManager;
31
use EWW\Dpf\Services\ProcessNumber\ProcessNumberGenerator;
32
33
/**
34
 * DocumentController
35
 */
36
class ApiController extends ActionController
37
{
38
    /**
39
     * @var \TYPO3\CMS\Extbase\Mvc\View\JsonView
40
     */
41
    protected $view;
42
43
    /**
44
     * @var string
45
     */
46
    protected $defaultViewObjectName = \TYPO3\CMS\Extbase\Mvc\View\JsonView::class;
47
48
49
    /**
50
     * security
51
     *
52
     * @var \EWW\Dpf\Security\Security
53
     * @inject
54
     */
55
    protected $security = null;
56
57
    /**
58
     * documentRepository
59
     *
60
     * @var \EWW\Dpf\Domain\Repository\DocumentRepository
61
     * @inject
62
     */
63
    protected $documentRepository = null;
64
65
    /**
66
     * frontendUserRepository
67
     *
68
     * @var \EWW\Dpf\Domain\Repository\FrontendUserRepository
69
     * @inject
70
     */
71
    protected $frontendUserRepository = null;
72
73
    /**
74
     * documentManager
75
     *
76
     * @var \EWW\Dpf\Services\Document\DocumentManager
77
     * @inject
78
     */
79
    protected $documentManager = null;
80
81
    /**
82
     * clientRepository
83
     *
84
     * @var \EWW\Dpf\Domain\Repository\ClientRepository
85
     * @inject
86
     */
87
    protected $clientRepository;
88
89
    /**
90
     * persistence manager
91
     *
92
     * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
93
     * @inject
94
     */
95
    protected $persistenceManager;
96
97
    /**
98
     * signalSlotDispatcher
99
     *
100
     * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
101
     * @inject
102
     */
103
    protected $signalSlotDispatcher = null;
104
105
    /**
106
     * logger
107
     *
108
     * @var \TYPO3\CMS\Core\Log\Logger
109
     */
110
    protected $logger = null;
111
112
    protected $frontendUser = null;
113
114
115
    public function __construct()
116
    {
117
        /** @var $logger \TYPO3\CMS\Core\Log\Logger */
118
        $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
119
    }
120
121
    public function checkToken($token) {
122
        // check if token exists
123
        $frontendUser = $this->frontendUserRepository->findOneByApiToken($token);
0 ignored issues
show
Bug introduced by
The method findOneByApiToken() does not exist on EWW\Dpf\Domain\Repository\FrontendUserRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

123
        /** @scrutinizer ignore-call */ 
124
        $frontendUser = $this->frontendUserRepository->findOneByApiToken($token);
Loading history...
124
125
        if ($frontendUser) {
126
            $this->frontendUser = $frontendUser;
127
            return true;
128
        } else {
129
            return false;
130
        }
131
    }
132
133
    /**
134
     * @param string $document
135
     * @param string $token
136
     */
137
    public function showAction($document, $token) {
138
        if ($this->checkToken($token)) {
139
            /** @var Document $doc */
140
            $doc = $this->documentManager->read($document);
141
            //$doc = $this->documentRepository->findByIdentifier($document);
142
143
            if ($doc) {
0 ignored issues
show
introduced by
$doc is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
144
                $this->security->getUser()->getUid();
145
146
                /** @var $client \EWW\Dpf\Domain\Model\Client */
147
                $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
0 ignored issues
show
Bug introduced by
The method getPid() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
                $client = $this->clientRepository->findAllByPid($this->frontendUser->/** @scrutinizer ignore-call */ getPid())->current();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getPid() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
                $client = $this->clientRepository->findAllByPid($this->frontendUser->/** @scrutinizer ignore-call */ getPid())->current();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148
149
                $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
150
                $mapper->setMapping($client->getFisMapping());
151
                $jsonData = $mapper->getJson($doc);
152
                return $jsonData;
153
            }
154
155
            return '{"error": "No data found"}';
156
        }
157
        return '{"error": "Token failed"}';
158
    }
159
160
    /**
161
     * @param string $json
162
     * @param string $token
163
     */
164
    public function createAction($json, $token) {
165
        if ($this->checkToken($token)) {
166
            if ($json) {
167
                $jsonData = $json;
168
            }
169
170
            if (empty($jsonData)) {
171
                return '{"error": "invalid data"}';
172
            }
173
174
            $mapper = $this->objectManager->get(\EWW\Dpf\Services\Api\JsonToDocumentMapper::class);
175
176
            /** @var Document $document */
177
            $document = $mapper->getDocument($jsonData);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $jsonData does not seem to be defined for all execution paths leading up to this point.
Loading history...
178
179
            if ($this->tokenUserId) {
0 ignored issues
show
Bug Best Practice introduced by
The property tokenUserId does not exist on EWW\Dpf\Controller\ApiController. Did you maybe forget to declare it?
Loading history...
180
                $document->setCreator($this->security->getUser()->getUid());
181
            }
182
183
            // xml data fields are limited to 64 KB
184
            if (strlen($document->getXmlData()) >= 64 * 1024) {
185
                return '{"error": "Maximum document size exceeded"}';
186
            }
187
188
            $processNumber = $document->getProcessNumber();
189
            if (empty($processNumber)) {
190
                $processNumberGenerator = $this->objectManager->get(ProcessNumberGenerator::class);
191
                $processNumber = $processNumberGenerator->getProcessNumber();
192
                $document->setProcessNumber($processNumber);
193
            }
194
195
            $this->documentRepository->add($document);
196
            $this->persistenceManager->persistAll();
197
198
            // index the document
199
            $this->signalSlotDispatcher->dispatch(
200
                AbstractController::class, 'indexDocument', [$document]
201
            );
202
203
            return '{"success": "Document created", "id": "' . $document->getProcessNumber() . '"}';
204
        }
205
        return '{"error": "Token failed"}';
206
207
    }
208
209
    /**
210
     * @param string $document
211
     * @param string $id
212
     * @param string $token
213
     * @throws \Exception
214
     */
215
    public function addFisIdAction($document, $id, $token) {
216
        if ($this->checkToken($token)) {
217
            /** @var Document $doc */
218
            $doc = $this->documentManager->read($document);
219
220
            $internalFormat = new \EWW\Dpf\Helper\InternalFormat($doc->getXmlData());
221
            $internalFormat->setFisId($id);
222
            $doc->setXmlData($internalFormat->getXml());
223
224
            $processNumber = $doc->getProcessNumber();
225
            if (empty($processNumber)) {
226
                $processNumberGenerator = $this->objectManager->get(ProcessNumberGenerator::class);
227
                $processNumber = $processNumberGenerator->getProcessNumber();
228
                $doc->setProcessNumber($processNumber);
229
            }
230
231
            $this->documentManager->update($doc);
232
233
            // index the document
234
            $this->signalSlotDispatcher->dispatch(
235
                AbstractController::class, 'indexDocument', [$doc]
236
            );
237
238
            return '{"success": "Document '.$document.' added '.$id.'"}';
239
        }
240
        return '{"error": "Token failed"}';
241
242
    }
243
244
    /**
245
     * @param string $document
246
     * @param string $json
247
     * @param string $token
248
     * @param bool $restore
249
     * @return string
250
     */
251
    public function suggestionAction($document, $json, $token, $restore = false) {
252
        if ($this->checkToken($token)) {
253
            /** @var Document $doc */
254
            $doc = $this->documentManager->read($document);
255
256
            if ($json) {
257
                $jsonData = $json;
258
            }
259
260
            if (empty($jsonData) && $restore == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
261
                return '{"error": "invalid data"}';
262
            }
263
264
            $mapper = $this->objectManager->get(\EWW\Dpf\Services\Api\JsonToDocumentMapper::class);
265
266
            /** @var Document $editOrigDocument */
267
            $editOrigDocument = $mapper->editDocument($doc, $jsonData);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $jsonData does not seem to be defined for all execution paths leading up to this point.
Loading history...
268
269
            $suggestionDocument = $this->documentManager->addSuggestion($editOrigDocument);
270
271
            if ($restore) {
272
                $suggestionDocument->setTransferStatus("RESTORE");
273
            }
274
275
            if ($suggestionDocument) {
276
                return '{"success": "Suggestion created", "id": "' . $suggestionDocument->getDocumentIdentifier() . '"}';
277
            } else {
278
                return '{"failed": "Suggestion not created"}';
279
            }
280
        }
281
        return '{"error": "Token failed"}';
282
    }
283
284
    /**
285
     * @param string $doi
286
     * @param string $token
287
     */
288
    public function importDoiWithoutSavingAction(string $doi, $token) {
289
        if ($this->checkToken($token)) {
290
            $importer = $this->objectManager->get(CrossRefImporter::class);
291
            $externalMetadata = $importer->findByIdentifier($doi);
292
            if (!$externalMetadata) {
293
                $importer = $this->objectManager->get(DataCiteImporter::class);
294
                $externalMetadata = $importer->findByIdentifier($doi);
295
            }
296
297
            if ($externalMetadata) {
298
                // create document
299
                try {
300
                    /** @var Document $newDocument */
301
                    $newDocument = $importer->import($externalMetadata);
302
                    if ($newDocument) {
0 ignored issues
show
introduced by
$newDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
303
                        /** @var $client \EWW\Dpf\Domain\Model\Client */
304
                        $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
305
306
                        $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
307
                        $mapper->setMapping($client->getFisMapping());
308
                        $jsonData = $mapper->getJson($newDocument);
309
                        return $jsonData;
310
                    } else {
311
                        return '{"failed": "Import failed"}';
312
                    }
313
314
                } catch (\Throwable $throwable) {
315
316
                    $this->logger->error($throwable->getMessage());
317
                    return '{"failed": "' . $throwable->getMessage() . '"}';
318
                }
319
320
            } else {
321
                // error
322
                return '{"failed": "Nothing found"}';
323
            }
324
        }
325
        return '{"error": "Token failed"}';
326
    }
327
328
    /**
329
     * @param string $pmid
330
     * @param string $token
331
     * @return string
332
     */
333
    public function importPubmedWithoutSavingAction($pmid, $token) {
334
        if ($this->checkToken($token)) {
335
            $importer = $this->objectManager->get(PubMedImporter::class);
336
            $externalMetadata = $importer->findByIdentifier($pmid);
337
338
            if ($externalMetadata) {
339
                // create document
340
                try {
341
                    /** @var Document $newDocument */
342
                    $newDocument = $importer->import($externalMetadata);
343
                    if ($newDocument) {
0 ignored issues
show
introduced by
$newDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
344
                        /** @var $client \EWW\Dpf\Domain\Model\Client */
345
                        $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
346
347
                        $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
348
                        $mapper->setMapping($client->getFisMapping());
349
                        $jsonData = $mapper->getJson($newDocument);
350
                        return $jsonData;
351
                    } else {
352
                        return '{"failed": "Import failed"}';
353
                    }
354
355
                } catch (\Throwable $throwable) {
356
357
                    $this->logger->error($throwable->getMessage());
358
                    return '{"failed": "' . $throwable->getMessage() . '"}';
359
                }
360
361
            } else {
362
                // error
363
                return '{"failed": "Nothing found"}';
364
            }
365
        }
366
        return '{"error": "Token failed"}';
367
    }
368
369
    /**
370
     * @param string $isbn
371
     * @param string $token
372
     * @return string
373
     */
374
    public function importIsbnWithoutSavingAction($isbn, $token) {
375
        if ($this->checkToken($token)) {
376
            $importer = $this->objectManager->get(K10plusImporter::class);
377
            $externalMetadata = $importer->findByIdentifier(str_replace('- ', '', $isbn));
378
379
            if ($externalMetadata) {
380
                // create document
381
                try {
382
                    /** @var Document $newDocument */
383
                    $newDocument = $importer->import($externalMetadata);
384
                    if ($newDocument) {
0 ignored issues
show
introduced by
$newDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
385
                        /** @var $client \EWW\Dpf\Domain\Model\Client */
386
                        $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
387
388
                        $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
389
                        $mapper->setMapping($client->getFisMapping());
390
                        $jsonData = $mapper->getJson($newDocument);
391
                        return $jsonData;
392
                    } else {
393
                        return '{"failed": "Import failed"}';
394
                    }
395
396
                } catch (\Throwable $throwable) {
397
398
                    $this->logger->error($throwable->getMessage());
399
                    return '{"failed": "' . $throwable->getMessage() . '"}';
400
                }
401
402
            } else {
403
                // error
404
                return '{"failed": "Nothing found"}';
405
            }
406
        }
407
        return '{"error": "Token failed"}';
408
    }
409
410
    /**
411
     * @param string $bibtex content of a bibtex file
412
     * @param string $token
413
     * @return string
414
     */
415
    public function importBibtexWithoutSavingAction($bibtex, $token) {
416
417
        if ($this->checkToken($token)) {
418
            $importer = $this->objectManager->get(BibTexFileImporter::class);
419
420
            try {
421
                $externalMetadata = $importer->loadFile($bibtex, $this->settings['bibTexMandatoryFields'], true);
422
            } catch (\Throwable $throwable) {
423
                return '{"failed": "' . $throwable->getMessage() . '"}';
424
            }
425
426
            if ($externalMetadata) {
427
                // create document
428
                try {
429
                    /** @var Document $newDocument */
430
                    $newDocument = $importer->import($externalMetadata[0]);
431
                    if ($newDocument) {
0 ignored issues
show
introduced by
$newDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
432
                        /** @var $client \EWW\Dpf\Domain\Model\Client */
433
                        $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
434
435
                        $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
436
                        $mapper->setMapping($client->getFisMapping());
437
                        $jsonData = $mapper->getJson($newDocument);
438
                        return $jsonData;
439
                    } else {
440
                        return '{"failed": "Import failed"}';
441
                    }
442
443
                } catch (\Throwable $throwable) {
444
445
                    $this->logger->error($throwable->getMessage());
446
                    return '{"failed": "' . $throwable->getMessage() . '"}';
447
                }
448
449
            } else {
450
                $mandatoryErrors = $importer->getMandatoryErrors();
451
                $message = '';
452
                foreach ($mandatoryErrors as $mandatoryError) {
453
                    $message .= 'Konnte die Publikation Nr. ' . $mandatoryError['index'] . ' nicht importieren';
454
                    $message .= $mandatoryError['title'] ? ' (' . $mandatoryError['title'] . ')' : '';
455
                    $message .= ', da die folgenden Felder leer sind: ' . implode(',', $mandatoryError['fields']);
456
                }
457
                // error
458
                return '{"failed": "' . $message . '"}';
459
            }
460
        }
461
        return '{"error": "Token failed"}';
462
    }
463
464
    /**
465
     * @param string $ris
466
     * @param string $token
467
     * @return string
468
     */
469
    public function importRisWithoutSavingAction($ris, $token) {
470
        if ($this->checkToken($token)) {
471
            /** @var FileImporter $fileImporter */
472
            $importer = $this->objectManager->get(RisWosFileImporter::class);
473
474
            try {
475
                $externalMetadata = $importer->loadFile($ris, $this->settings['riswosMandatoryFields'], true);
476
            } catch (\Throwable $throwable) {
477
                return '{"failed": "' . $throwable->getMessage() . '"}';
478
            }
479
480
            if ($externalMetadata) {
481
                // create document
482
                try {
483
                    /** @var Document $newDocument */
484
                    $newDocument = $importer->import($externalMetadata[0]);
485
                    if ($newDocument) {
0 ignored issues
show
introduced by
$newDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
486
                        /** @var $client \EWW\Dpf\Domain\Model\Client */
487
                        $client = $this->clientRepository->findAllByPid($this->frontendUser->getPid())->current();
488
489
                        $mapper = new \EWW\Dpf\Services\Api\DocumentToJsonMapper();
490
                        $mapper->setMapping($client->getFisMapping());
491
                        $jsonData = $mapper->getJson($newDocument);
492
                        return $jsonData;
493
                    } else {
494
                        return '{"failed": "Import failed"}';
495
                    }
496
497
                } catch (\Throwable $throwable) {
498
499
                    $this->logger->error($throwable->getMessage());
500
                    return '{"failed": "' . $throwable->getMessage() . '"}';
501
                }
502
503
            } else {
504
                $mandatoryErrors = $importer->getMandatoryErrors();
505
                $message = '';
506
                foreach ($mandatoryErrors as $mandatoryError) {
507
                    $message .= 'Konnte die Publikation Nr. ' . $mandatoryError['index'] . ' nicht importieren';
508
                    $message .= $mandatoryError['title'] ? ' (' . $mandatoryError['title'] . ')' : '';
509
                    $message .= ', da die folgenden Felder leer sind: ' . implode(',', $mandatoryError['fields']);
510
                }
511
                // error
512
                return '{"failed": "' . $message . '"}';
513
            }
514
        }
515
        return '{"error": "Token failed"}';
516
    }
517
518
519
//    /**
520
//     * Resolves and checks the current action method name
521
//     *
522
//     * @return string Method name of the current action
523
//     */
524
//    protected function resolveActionMethodName()
525
//    {
526
//        switch ($this->request->getMethod()) {
527
//            case 'HEAD':
528
//            case 'GET':
529
//                $actionName = ($this->request->hasArgument('document')) ? 'show' : 'list';
530
//                break;
531
//            case 'POST':
532
//                $actionName = 'create';
533
//                break;
534
//            case 'PUT':
535
//            case 'DELETE':
536
//                $this->throwStatus(400, null, 'Bad Request.');
537
//            default:
538
//                $this->throwStatus(400, null, 'Bad Request.');
539
//        }
540
//
541
//        return $actionName . 'Action';
542
//    }
543
}
544