Passed
Pull Request — master (#195)
by
unknown
17:55
created

uploadedDocumentsAction()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 23
c 2
b 0
f 0
nc 6
nop 1
dl 0
loc 36
rs 9.2408
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\CrossRefMetadata;
18
use EWW\Dpf\Domain\Model\Document;
19
use EWW\Dpf\Domain\Model\PubMedMetadata;
20
use EWW\Dpf\Security\Security;
21
use EWW\Dpf\Domain\Workflow\DocumentWorkflow;
22
use TYPO3\CMS\Core\Messaging\AbstractMessage;
23
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
24
use EWW\Dpf\Domain\Model\ExternalMetadata;
25
use EWW\Dpf\Services\ImportExternalMetadata\Importer;
26
use EWW\Dpf\Services\ImportExternalMetadata\FileImporter;
27
use EWW\Dpf\Services\ImportExternalMetadata\CrossRefImporter;
28
use EWW\Dpf\Services\ImportExternalMetadata\DataCiteImporter;
29
use EWW\Dpf\Services\ImportExternalMetadata\PubMedImporter;
30
use EWW\Dpf\Services\ImportExternalMetadata\K10plusImporter;
31
use EWW\Dpf\Session\BulkImportSessionData;
32
use EWW\Dpf\Services\ImportExternalMetadata\BibTexFileImporter;
33
use EWW\Dpf\Services\ImportExternalMetadata\RisWosFileImporter;
34
use EWW\Dpf\Services\ImportExternalMetadata\RisReader;
35
use EWW\Dpf\Services\ImportExternalMetadata\PublicationIdentifier;
36
37
/**
38
 * ExternalDataImportController
39
 */
40
class ExternalMetadataImportController extends AbstractController
41
{
42
    /**
43
     * ExternalMetadataRepository
44
     *
45
     * @var \EWW\Dpf\Domain\Repository\ExternalMetadataRepository
46
     * @inject
47
     */
48
    protected $externalMetadataRepository = null;
49
50
    /**
51
     * documentRepository
52
     *
53
     * @var \EWW\Dpf\Domain\Repository\DocumentRepository
54
     * @inject
55
     */
56
    protected $documentRepository = null;
57
58
    /**
59
     * documentTypeRepository
60
     *
61
     * @var \EWW\Dpf\Domain\Repository\DocumentTypeRepository
62
     * @inject
63
     */
64
    protected $documentTypeRepository = null;
65
66
    /**
67
     * persistence manager
68
     *
69
     * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
70
     * @inject
71
     */
72
    protected $persistenceManager;
73
74
    /**
75
     * elasticSearch
76
     *
77
     * @var \EWW\Dpf\Services\ElasticSearch\ElasticSearch
78
     * @inject
79
     */
80
    protected $elasticSearch = null;
81
82
    /**
83
     * queryBuilder
84
     *
85
     * @var \EWW\Dpf\Services\ElasticSearch\QueryBuilder
86
     * @inject
87
     */
88
    protected $queryBuilder = null;
89
90
    /**
91
     * bookmarkRepository
92
     *
93
     * @var \EWW\Dpf\Domain\Repository\BookmarkRepository
94
     * @inject
95
     */
96
    protected $bookmarkRepository = null;
97
98
    /**
99
     * workflow
100
     *
101
     * @var \EWW\Dpf\Domain\Workflow\DocumentWorkflow
102
     */
103
    protected $workflow;
104
105
    /**
106
     * metadataGroupRepository
107
     *
108
     * @var \EWW\Dpf\Domain\Repository\MetadataGroupRepository
109
     * @inject
110
     */
111
    protected $metadataGroupRepository;
112
113
114
    /**
115
     * DocumentController constructor.
116
     */
117
    public function __construct()
118
    {
119
        parent::__construct();
120
    }
121
122
    /**
123
     * @param string $crossRefQuery
124
     * @param string $pubMedQuery
125
     */
126
    public function bulkStartAction($crossRefQuery = '', $pubMedQuery = '')
127
    {
128
        /** @var BulkImportSessionData $bulkImportSessionData */
129
        $bulkImportSessionData = $this->session->getBulkImportData();
130
131
        $crossRefAuthorSearch = $bulkImportSessionData->getCrossRefSearchField() === 'author';
132
        $pubMedAuthorSearch = $bulkImportSessionData->getPubMedSearchField() === 'author';
133
134
        $this->externalMetadataRepository->clearExternalMetadataByFeUserUid($this->security->getUser()->getUid());
135
        $this->view->assign('crossRefAuthorSearch', $crossRefAuthorSearch);
136
        $this->view->assign('pubMedAuthorSearch', $pubMedAuthorSearch);
137
        $this->view->assign('crossRefQuery', $crossRefQuery);
138
        $this->view->assign('pubMedQuery', $pubMedQuery);
139
    }
140
141
    /**
142
     * @param string $query
143
     */
144
    public function bulkSearchCrossRefAction($query = '')
145
    {
146
        /** @var BulkImportSessionData $bulkImportSessionData */
147
        $bulkImportSessionData = $this->session->getBulkImportData();
148
149
        $currentPage = null;
150
        $pagination = $this->getParametersSafely('@widget_0');
151
        if ($pagination) {
152
            $currentPage = $pagination['currentPage'];
153
            $query = $bulkImportSessionData->getCrossRefQuery();
154
        } else {
155
            if (empty($query)) {
156
                $this->redirect('bulkStart');
157
            }
158
159
            $bulkImportSessionData->setCrossRefQuery($query);
160
            $currentPage = 1;
161
        }
162
163
        $offset = empty($currentPage)? 0 : ($currentPage-1) * $this->itemsPerPage();
164
165
        /** @var Importer $importer */
166
        $importer = $this->objectManager->get(CrossRefImporter::class);
167
        $results = $importer->search(
168
            $query,
169
            $this->itemsPerPage(),
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Services\ImportE...data\Importer::search() has too many arguments starting with $this->itemsPerPage(). ( Ignorable by Annotation )

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

169
        /** @scrutinizer ignore-call */ 
170
        $results = $importer->search(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
170
            $offset,
171
            $bulkImportSessionData->getCrossRefSearchField()
172
        );
173
174
        $bulkImportSessionData->setCurrentMetadataItems(($results? $results['items'] : []));
175
        $this->session->setBulkImportData($bulkImportSessionData);
176
177
        if ($results) {
178
            $this->forward(
179
                'bulkResults',
180
                null,
181
                null,
182
                [
183
                    'results' => $results,
184
                    'query' => $query,
185
                    'importSourceName' => 'Crossref',
186
                    'currentPage' => $currentPage
187
                ]
188
            );
189
        } else {
190
191
            $message = LocalizationUtility::translate(
192
                'manager.importMetadata.nothingFound', 'dpf'
193
            );
194
195
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
196
197
            $this->forward(
198
                'bulkStart',
199
                null,
200
                null,
201
                [
202
                    'crossRefQuery' => $bulkImportSessionData->getCrossRefQuery()
203
                ]
204
            );
205
        }
206
    }
207
208
    /**
209
     * @param string $query
210
     */
211
    public function bulkSearchPubMedAction($query = '')
212
    {
213
        /** @var BulkImportSessionData $bulkImportSessionData */
214
        $bulkImportSessionData = $this->session->getBulkImportData();
215
216
        $currentPage = null;
217
        $pagination = $this->getParametersSafely('@widget_0');
218
        if ($pagination) {
219
            $currentPage = $pagination['currentPage'];
220
            $query = $bulkImportSessionData->getPubMedQuery();
221
        } else {
222
            if (empty($query)) {
223
                $this->redirect('bulkStart');
224
            }
225
226
            $bulkImportSessionData->setPubMedQuery($query);
227
            $currentPage = 1;
228
        }
229
230
        $offset = empty($currentPage)? 0 : ($currentPage-1) * $this->itemsPerPage();
231
232
        /** @var Importer $importer */
233
        $importer = $this->objectManager->get(PubMedImporter::class);
234
        $results = $importer->search(
235
            $query,
236
            $this->itemsPerPage(),
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Services\ImportE...data\Importer::search() has too many arguments starting with $this->itemsPerPage(). ( Ignorable by Annotation )

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

236
        /** @scrutinizer ignore-call */ 
237
        $results = $importer->search(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
237
            $offset,
238
            $bulkImportSessionData->getPubMedSearchField()
239
        );
240
241
        $bulkImportSessionData->setCurrentMetadataItems(($results? $results['items'] : []));
242
        $this->session->setBulkImportData($bulkImportSessionData);
243
244
        if ($results) {
245
            $this->forward(
246
                'bulkResults',
247
                null,
248
                null,
249
                [
250
                    'results' => $results,
251
                    'query' => $query,
252
                    'importSourceName' => 'PubMed',
253
                    'currentPage' => $currentPage
254
                ]
255
            );
256
        } else {
257
258
            $message = LocalizationUtility::translate(
259
                'manager.importMetadata.nothingFound', 'dpf'
260
            );
261
262
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
263
264
            $this->forward(
265
                'bulkStart',
266
                null,
267
                null,
268
                [
269
                    'pubMedQuery' => $bulkImportSessionData->getPubMedQuery()
270
                ]
271
            );
272
        }
273
    }
274
275
    /**
276
     * @param string $importSourceName
277
     * @param string $query
278
     * @param array $results
279
     * @param int $currentPage
280
     */
281
    public function bulkResultsAction($importSourceName, $query, $results = null, $currentPage = 1)
282
    {
283
        $externalMetadata = $this->externalMetadataRepository->findByFeUser($this->security->getUser()->getUid());
0 ignored issues
show
Bug introduced by
The method findByFeUser() does not exist on EWW\Dpf\Domain\Repositor...ernalMetadataRepository. 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

283
        /** @scrutinizer ignore-call */ 
284
        $externalMetadata = $this->externalMetadataRepository->findByFeUser($this->security->getUser()->getUid());
Loading history...
284
        $checkedPublicationIdentifiers = [];
285
286
        /** @var ExternalMetadata $data */
287
        foreach ($externalMetadata as $data) {
288
            $checkedPublicationIdentifiers[] = $data->getPublicationIdentifier();
289
        }
290
291
        $this->view->assign('importSourceName', $importSourceName);
292
        $this->view->assign('totalResults', $results['total-results']);
293
        $this->view->assign('itemsPerPage', $this->itemsPerPage());
294
        $this->view->assign('currentPage', $currentPage);
295
        $this->view->assign('query', $query);
296
        $this->view->assign('checkedPublicationIdentifiers', $checkedPublicationIdentifiers);
297
        $this->view->assign('results', $results);
298
    }
299
300
    /**
301
     *
302
     */
303
    function bulkImportAction()
304
    {
305
        $importCounter = ['imported' => 0, 'bookmarked' => 0, 'total' => 0];
306
307
        try {
308
            $externalMetadata = $this->externalMetadataRepository->findByFeUser($this->security->getUser()->getUid());
309
310
            $importedDocuments = [];
311
            $importedDocumentIdentifiers = [];
312
313
            /** @var ExternalMetadata $externalMetadataItem */
314
            foreach ($externalMetadata as $externalMetadataItem) {
315
316
                /** @var  Importer $importer */
317
                $importer = $this->objectManager->get($externalMetadataItem->getSource());
318
319
                // Check if the publication already exists in kitodo
320
                if ($this->findDocumentInKitodo($externalMetadataItem->getPublicationIdentifier())) {
321
                    $existingWorkspaceDocument = $this->findDocumentInWorkspace(
322
                        $externalMetadataItem->getPublicationIdentifier()
323
                    );
324
                    if (empty($existingWorkspaceDocument)) {
325
                        $this->bookmarkRepository->addBookmark(
326
                            $existingWorkspaceDocument['_id'],
327
                            $this->security->getUser()->getUid()
328
                        );
329
                        $importCounter['bookmarked'] += 1;
330
                    }
331
332
                } else {
333
334
                    if (!$this->findDocumentInWorkspace($externalMetadataItem->getPublicationIdentifier())) {
335
                        /** @var Document $newDocument */
336
                        $newDocument = $importer->import($externalMetadataItem);
337
338
                        if ($newDocument instanceof Document) {
339
                            $this->documentRepository->add($newDocument);
340
                            $this->externalMetadataRepository->remove($externalMetadataItem);
341
                            $importedDocuments[] = $newDocument;
342
                            $importCounter['imported'] += 1;
343
                        }
344
                    }
345
                }
346
            }
347
348
            $this->persistenceManager->persistAll();
349
350
            // Documents can only be indexed after they have been persisted as we need a valid UID.
351
            /** @var Document $importedDocument */
352
            foreach ($importedDocuments as $importedDocument) {
353
                // index the document
354
                $this->signalSlotDispatcher->dispatch(
355
                    AbstractController::class, 'indexDocument', [$importedDocument]
356
                );
357
                $importedDocumentIdentifiers[] = $importedDocument->getDocumentIdentifier();
358
            }
359
360
            /** @var BulkImportSessionData $bulkImportSessionData */
361
            $bulkImportSessionData = $this->session->getBulkImportData();
362
            $bulkImportSessionData->setLatestImportIdentifiers($importedDocumentIdentifiers);
363
            $this->session->setBulkImportData($bulkImportSessionData);
364
365
        } catch(\Throwable $throwable) {
366
            $this->logger->error($throwable->getMessage());
367
368
            $message = LocalizationUtility::translate(
369
                'manager.importMetadata.publicationNotImported', 'dpf'
370
            );
371
372
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
373
        }
374
375
        $this->redirect(
376
            'bulkImportedDocuments',
377
            null,
378
            null,
379
            ['from' => 0, 'importCounter' => $importCounter]);
380
    }
381
382
    /**
383
     * Cancels the bulk import result list view.
384
     *
385
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
386
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
387
     */
388
    function cancelBulkImportAction()
389
    {
390
        $this->redirect('bulkStart');
391
    }
392
393
394
    /**
395
     * Shows the form to find a publication by an identifier
396
     * @param string $identifier
397
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
398
     */
399
    public function findAction($identifier = '')
400
    {
401
        $this->externalMetadataRepository->clearExternalMetadataByFeUserUid($this->security->getUser()->getUid());
402
        $this->view->assign('identifier', $identifier);
403
    }
404
405
    /**
406
     * Retrieves and caches the the metadata related to the given identifier.
407
     *
408
     * @param string $identifier
409
     */
410
    public function retrieveAction($identifier)
411
    {
412
        $identifier = trim($identifier);
413
414
        if (empty($identifier)) {
415
            $this->redirect('find');
416
        }
417
418
        // Check if the document already exists in the workspace or my publications,
419
        // if this is the case, nothing will be imported, the find results will be shown again
420
        // and an error message will be displayed.
421
        if ($this->findDocumentInWorkspace($identifier)) {
422
            if ($this->security->getUserRole() == Security::ROLE_LIBRARIAN) {
423
                $message = LocalizationUtility::translate(
424
                    'manager.importMetadata.alreadyInWorkspace', 'dpf'
425
                );
426
            } else {
427
                $message = LocalizationUtility::translate(
428
                    'manager.importMetadata.alreadyInMyPublications', 'dpf'
429
                );
430
            }
431
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
432
433
            $this->redirect('find', null, null, ['identifier' => $identifier]);
434
        }
435
436
        // Check if the document already exists in kitodo.
437
        /** @var array $existingDocument */
438
        if ($existingDocument = $this->findDocumentInKitodo($identifier)) {
439
440
            $this->bookmarkRepository->addBookmark(
441
                $existingDocument['_id'],
442
                $this->security->getUser()->getUid()
443
            );
444
445
            if ($this->security->getUserRole() == Security::ROLE_LIBRARIAN) {
446
                $message = LocalizationUtility::translate(
447
                    'manager.importMetadata.alreadyInSystemWorkspace', 'dpf'
448
                );
449
            } else {
450
                $message = LocalizationUtility::translate(
451
                    'manager.importMetadata.alreadyInSystemMyPublications', 'dpf'
452
                );
453
            }
454
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
455
456
            $this->redirect('find', null, null, ['identifier' => $identifier]);
457
        }
458
459
        /** @var \EWW\Dpf\Services\ImportExternalMetadata\Importer $importer */
460
        $importer = null;
461
462
        // Choose the right data provider depending on the identifier type and retrieve the metadata.
463
        $identifierType = PublicationIdentifier::determineIdentifierType($identifier);
464
465
        if ($identifierType === 'DOI') {
466
            $importer = $this->objectManager->get(CrossRefImporter::class);
467
            $externalMetadata = $importer->findByIdentifier($identifier);
468
            if (!$externalMetadata) {
469
                $importer = $this->objectManager->get(DataCiteImporter::class);
470
                $externalMetadata = $importer->findByIdentifier($identifier);
471
            }
472
        } elseif ($identifierType === 'PMID') {
473
            $importer = $this->objectManager->get(PubMedImporter::class);
474
            $externalMetadata = $importer->findByIdentifier($identifier);
475
        } elseif ($identifierType === 'ISBN') {
476
            $importer = $this->objectManager->get(K10plusImporter::class);
477
            $externalMetadata = $importer->findByIdentifier(str_replace('- ', '', $identifier));
478
        } else {
479
            $externalMetadata = null;
480
        }
481
482
        if ($externalMetadata) {
483
            // Save the metadata for further processing
484
            $this->externalMetadataRepository->add($externalMetadata);
485
            $this->persistenceManager->persistAll();
486
        }
487
488
        if ($externalMetadata) {
489
            $this->redirect(
490
                'import',
491
                null,
492
                null,
493
                ['externalMetadata'=>$externalMetadata]
494
            );
495
        } else {
496
            $message = LocalizationUtility::translate(
497
                'manager.importMetadata.nothingFound', 'dpf'
498
            );
499
500
            $this->addFlashMessage(
501
                $message,
502
                '',
503
                AbstractMessage::ERROR
504
            );
505
            $this->redirect('find', null, null, ['identifier' => $identifier]);
506
        }
507
508
    }
509
510
    /**
511
     * The import dialog
512
     *
513
     * @param ExternalMetadata $externalMetadata
514
     */
515
    public function importAction(ExternalMetadata $externalMetadata)
516
    {
517
        $this->view->assign('identifierType',
518
            PublicationIdentifier::determineIdentifierType($externalMetadata->getPublicationIdentifier())
519
        );
520
        $this->view->assign('externalMetadata', $externalMetadata);
521
    }
522
523
    /**
524
     * @param ExternalMetadata $externalMetadata
525
     */
526
    public function createDocumentAction(ExternalMetadata $externalMetadata)
527
    {
528
        /** @var  Importer $importer */
529
        $importer = $this->objectManager->get($externalMetadata->getSource());
530
531
532
        try {
533
            /** @var Document $newDocument */
534
            $newDocument = $importer->import($externalMetadata);
535
536
            if ($newDocument instanceof Document) {
0 ignored issues
show
introduced by
$newDocument is always a sub-type of EWW\Dpf\Domain\Model\Document.
Loading history...
537
538
                $this->documentRepository->add($newDocument);
539
                $this->persistenceManager->persistAll();
540
541
                // index the document
542
                $this->signalSlotDispatcher->dispatch(
543
                    AbstractController::class, 'indexDocument', [$newDocument]
544
                );
545
546
                $this->externalMetadataRepository->remove($externalMetadata);
547
548
                if ($this->security->getUserRole() == Security::ROLE_LIBRARIAN) {
549
                    $message = LocalizationUtility::translate(
550
                        'manager.importMetadata.publicationAddedToWorkspace', 'dpf'
551
                    );
552
                } else {
553
                    $message = LocalizationUtility::translate(
554
                        'manager.importMetadata.publicationAddedToMyPublications', 'dpf'
555
                    );
556
                }
557
                $this->addFlashMessage($message, '', AbstractMessage::OK);
558
559
                $this->redirect('showDetails', 'Document', null, ['document' => $newDocument]);
560
561
            } else {
562
                $message = LocalizationUtility::translate(
563
                    'manager.importMetadata.publicationNotImported', 'dpf'
564
                );
565
566
                $this->addFlashMessage($message, '', AbstractMessage::ERROR);
567
                $this->redirect('find');
568
            }
569
570
        } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
571
            // A redirect always throws this exception, but in this case, however,
572
            // redirection is desired and should not lead to an exception handling
573
        } catch(\Throwable $throwable) {
574
575
            $this->logger->error($throwable->getMessage());
576
577
            $message = LocalizationUtility::translate(
578
                'manager.importMetadata.publicationNotImported', 'dpf'
579
            );
580
581
           $this->addFlashMessage($message, '', AbstractMessage::ERROR);
582
           $this->redirect('find');
583
        }
584
    }
585
586
    /**
587
     * Finds a document with the given $identifier in the current users "Workspace" or "My publicstions"
588
     *
589
     * @param $identifier
590
     * @return array
591
     */
592
    protected function findDocumentInWorkspace($identifier)
593
    {
594
        $bookmarkIdentifiers = [];
595
        foreach ($this->bookmarkRepository->findByFeUserUid($this->security->getUser()->getUid()) as $bookmark) {
0 ignored issues
show
Bug introduced by
The method findByFeUserUid() does not exist on EWW\Dpf\Domain\Repository\BookmarkRepository. 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

595
        foreach ($this->bookmarkRepository->/** @scrutinizer ignore-call */ findByFeUserUid($this->security->getUser()->getUid()) as $bookmark) {
Loading history...
596
            $bookmarkIdentifiers[] = $bookmark->getDocumentIdentifier();
597
        }
598
599
        if ($this->security->getUserRole() == Security::ROLE_LIBRARIAN) {
600
            // "Workspace" of a librarian
601
            $workspaceFilter = [
602
                'bool' => [
603
                    'must' => [
604
                        [
605
                            'bool' => [
606
                                'must' => [
607
                                    [
608
                                        'term' => [
609
                                            'creator' => $this->security->getUser()->getUid()
610
                                        ]
611
                                    ],
612
                                    [
613
                                        'bool' => [
614
                                            'should' => [
615
                                                [
616
                                                    'term' => [
617
                                                        'state' => DocumentWorkflow::STATE_NEW_NONE
618
                                                    ]
619
                                                ]
620
                                            ]
621
                                        ]
622
                                    ]
623
                                ]
624
                            ]
625
                        ]
626
                    ]
627
                ]
628
            ];
629
        } else {
630
            // "My publications" of a researcher
631
            $workspaceFilter = [
632
                'bool' => [
633
                    'must' => [
634
                        [
635
                            'term' => [
636
                                'creator' => $this->security->getUser()->getUid()
637
                            ]
638
                        ]
639
                    ]
640
                ]
641
            ];
642
        }
643
644
        $query = $this->queryBuilder->buildQuery(
645
            1, $workspaceFilter, 0,
646
            $bookmarkIdentifiers, [], [], null, null,
647
            'identifier:"'.$identifier.'"'
648
        );
649
650
        try {
651
652
            $results =  $this->elasticSearch->search($query, 'object');
653
            if (is_array($results) && $results['hits']['total']['value'] > 0) {
654
                return $results['hits']['hits'][0];
655
            }
656
657
        } catch (\Exception $e) {
658
659
            $message = LocalizationUtility::translate(
660
                'manager.importMetadata.searchError', 'dpf'
661
            );
662
663
            $this->addFlashMessage(
664
                $message, '', AbstractMessage::ERROR
665
            );
666
        }
667
668
        return [];
669
    }
670
671
    /**
672
     * Finds a document with the given $identifier in the kitodo index
673
     *
674
     * @param $identifier
675
     * @return array
676
     */
677
    protected function findDocumentInKitodo($identifier) {
678
679
        $workspaceFilter = [
680
            'bool' => [
681
                'must_not' => [
682
                    [
683
                        'term' => [
684
                            'state' => DocumentWorkflow::STATE_NEW_NONE
685
                        ]
686
                    ]
687
                ]
688
            ]
689
        ];
690
691
        // Search if the document already exists in kitodo.
692
        $query = $this->queryBuilder->buildQuery(
693
            1, $workspaceFilter , 0, [], [], [], null, null, 'identifier:"'.$identifier.'"'
694
        );
695
        $results = $this->elasticSearch->search($query, 'object');
696
697
        if (is_array($results) && $results['hits']['total']['value'] > 0) {
698
            return $results['hits']['hits'][0];
699
        }
700
701
        return [];
702
    }
703
704
    /**
705
     * @param array $importCounter
706
     */
707
    public function bulkImportedDocumentsAction($importCounter = ['imported' => 0, 'bookmarked' => 0, 'total' => 0])
708
    {
709
710
        $publicationSingular = LocalizationUtility::translate('manager.importMetadata.publication.singular', 'dpf');
711
        $publicationPlural = LocalizationUtility::translate('manager.importMetadata.publication.plural', 'dpf');
712
713
        if ($this->security->getUserRole() === Security::ROLE_LIBRARIAN) {
714
            $messageKey = 'manager.bulkImport.importMessage.libarian';
715
        } else {
716
            $messageKey = 'manager.bulkImport.importMessage.researcher';
717
        }
718
719
        $message = LocalizationUtility::translate(
720
            $messageKey,
721
            'dpf',
722
            [
723
                0 => $importCounter['imported'],
724
                1 => ($importCounter['imported'] == 1? $publicationSingular : $publicationPlural),
725
                2 => $importCounter['bookmarked'],
726
                3 => ($importCounter['bookmarked'] == 1? $publicationSingular : $publicationPlural)
727
            ]
728
        );
729
730
        if ($importCounter['imported'] > 0 || $importCounter['bookmarked'] > 0) {
731
            $severity = AbstractMessage::INFO;
732
        } else {
733
            $severity = AbstractMessage::WARNING;
734
        }
735
736
        $this->addFlashMessage(
737
            $message, '', $severity
738
        );
739
740
        if ($importCounter['imported'] > 0 || $importCounter['bookmarked'] > 0) {
741
            if ($this->security->getUserRole() != Security::ROLE_LIBRARIAN) {
742
                $importNoteMessage = LocalizationUtility::translate('manager.bulkImport.importNote', 'dpf');
743
                $this->addFlashMessage(
744
                    $importNoteMessage, '', AbstractMessage::INFO
745
                );
746
            }
747
        }
748
749
        $this->showImportedDocuments($importCounter);
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Controller\Exter...showImportedDocuments() has too many arguments starting with $importCounter. ( Ignorable by Annotation )

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

749
        $this->/** @scrutinizer ignore-call */ 
750
               showImportedDocuments($importCounter);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
750
    }
751
752
    /**
753
     *
754
     */
755
    protected function showImportedDocuments()
756
    {
757
        $this->session->setStoredAction($this->getCurrentAction(), $this->getCurrentController(),
758
            $this->uriBuilder->getRequest()->getRequestUri()
0 ignored issues
show
introduced by
The method getRequestUri() does not exist on TYPO3\CMS\Extbase\Mvc\Request. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

758
            $this->uriBuilder->getRequest()->/** @scrutinizer ignore-call */ getRequestUri()
Loading history...
759
        );
760
761
        $currentPage = null;
762
        $pagination = $this->getParametersSafely('@widget_0');
763
        if ($pagination) {
764
            $currentPage = $pagination['currentPage'];
765
        } else {
766
            $currentPage = 1;
767
        }
768
769
        // \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($test);
770
771
        /** @var BulkImportSessionData $bulkImportSessionData */
772
        $bulkImportSessionData = $this->session->getBulkImportData();
773
        $importedIdentifiers = $bulkImportSessionData->getLatestImportIdentifiers();
774
775
        $workspaceFilter = [
776
            'bool' => [
777
                'must' => [
778
                    [
779
                        'terms' => [
780
                            '_id' => array_values(array_filter($importedIdentifiers))
781
                        ]
782
                    ]
783
                ]
784
            ]
785
        ];
786
787
        $query = $this->queryBuilder->buildQuery(
788
            $this->itemsPerPage(),
789
            $workspaceFilter,
790
            (empty($currentPage)? 0 : ($currentPage-1) * $this->itemsPerPage())
791
        );
792
793
        try {
794
            $results = $this->elasticSearch->search($query, 'object');
795
            $this->view->assign('currentPage', $currentPage);
796
            $this->view->assign('documentCount', $results['hits']['total']['value']);
797
            $this->view->assign('documents', $results['hits']['hits']);
798
            $this->view->assign('itemsPerPage', $this->itemsPerPage());
799
            $this->view->assign('currentFisPersId', $this->security->getFisPersId());
800
801
            $personGroup = $this->metadataGroupRepository->findPersonGroup();
802
            $this->view->assign('personGroup', $personGroup->getUid());
803
804
        } catch (\Throwable $e) {
805
806
            $message = LocalizationUtility::translate(
807
                'manager.importMetadata.searchError', 'dpf'
808
            );
809
810
            $this->addFlashMessage(
811
                $message, '', AbstractMessage::ERROR
812
            );
813
        }
814
    }
815
816
    /**
817
     * Returns the number of items to be shown per page.
818
     *
819
     * @return int
820
     */
821
    protected function itemsPerPage()
822
    {
823
        /** @var BulkImportSessionData $bulkImportSessionData */
824
        $bulkImportSessionData = $this->session->getBulkImportData();
825
826
        if ($bulkImportSessionData->getItemsPerPage()) {
827
            return $bulkImportSessionData->getItemsPerPage();
828
        }
829
830
        if ($this->settings['bulkImportPagination']['itemsPerPage']) {
831
            return $this->settings['bulkImportPagination']['itemsPerPage'];
832
        }
833
834
        return 10;
835
    }
836
837
    /**
838
     * @param string $error
839
     */
840
    public function uploadStartAction($error = '')
841
    {
842
        switch ($error) {
843
            case 'INVALID_FORMAT':
844
                $message = LocalizationUtility::translate(
845
                    'manager.uploadImport.invalidFormat', 'dpf'
846
                );
847
                $this->addFlashMessage($message, '', AbstractMessage::ERROR);
848
                break;
849
            case 'UPLOAD_ERROR':
850
                $message = LocalizationUtility::translate(
851
                    'manager.uploadImport.uploadError', 'dpf'
852
                );
853
                $this->addFlashMessage($message, '', AbstractMessage::ERROR);
854
                break;
855
        }
856
857
        $this->externalMetadataRepository->clearExternalMetadataByFeUserUid($this->security->getUser()->getUid());
858
    }
859
860
    /**
861
     * @param string $fileType (bibtex or riswos)
862
     * @param array $uploadFile
863
     */
864
    public function uploadImportFileAction($fileType, $uploadFile = [])
865
    {
866
        $this->externalMetadataRepository->clearExternalMetadataByFeUserUid($this->security->getUser()->getUid());
867
868
        $uploadFileUrl = new \EWW\Dpf\Helper\UploadFileUrl;
869
        $uploadFilePath = PATH_site . $uploadFileUrl->getDirectory() . "/importFile.".md5($this->security->getUser()->getUid());
870
871
        if ($uploadFile['error'] === UPLOAD_ERR_OK) {
872
            \TYPO3\CMS\Core\Utility\GeneralUtility::upload_copy_move($uploadFile['tmp_name'], $uploadFilePath);
873
            //$finfo       = finfo_open(FILEINFO_MIME_TYPE);
874
            //$contentType = finfo_file($finfo, $uploadFilePath);
875
            //finfo_close($finfo);
876
        } elseif ($uploadFile['error'] == UPLOAD_ERR_NO_FILE) {
877
            $this->redirect('uploadStart');
878
        } else {
879
            $this->redirect('uploadStart', null, null, ['error' => 'UPLOAD_ERROR']);
880
        }
881
882
        try {
883
884
            if ($fileType == 'bibtex') {
885
                /** @var FileImporter $fileImporter */
886
                $fileImporter = $this->objectManager->get(BibTexFileImporter::class);
887
                $results = $fileImporter->loadFile($uploadFilePath, $this->settings['bibTexMandatoryFields']);
888
            } elseif ($fileType == 'riswos') {
889
                /** @var FileImporter $fileImporter */
890
                $fileImporter = $this->objectManager->get(RisWosFileImporter::class);
891
                $results = $fileImporter->loadFile($uploadFilePath, $this->settings['riswosMandatoryFields']);
892
            } else {
893
                $results = [];
894
            }
895
896
            foreach ($results as $externalMetadata) {
897
                $this->externalMetadataRepository->add($externalMetadata);
898
            }
899
900
            if ($mandatoryErrors = $fileImporter->getMandatoryErrors()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fileImporter does not seem to be defined for all execution paths leading up to this point.
Loading history...
901
                foreach (
902
                    $mandatoryErrors as $mandatoryError
903
                ) {
904
                    $message = LocalizationUtility::translate(
905
                        "manager.uploadImport.incompleteData",
906
                        [
0 ignored issues
show
Bug introduced by
array($mandatoryError['i...datoryError['fields'])) of type array<integer,mixed|string> is incompatible with the type null|string expected by parameter $extensionName of TYPO3\CMS\Extbase\Utilit...ionUtility::translate(). ( Ignorable by Annotation )

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

906
                        /** @scrutinizer ignore-type */ [
Loading history...
907
                            $mandatoryError['index'],
908
                            ($mandatoryError['title'] ? ' (' . $mandatoryError['title'] . ')' : ''),
909
                            implode(',', $mandatoryError['fields'])
910
                        ]
911
                    );
912
                    $this->addFlashMessage($message, '', AbstractMessage::ERROR);
913
                }
914
            } elseif ($results) {
915
                    $this->redirect(
916
                        'importUploadedData',
917
                        null,
918
                        null,
919
                        ['uploadFilePath' => $uploadFilePath]
920
                    );
921
            } else {
922
                $this->redirect('uploadStart', null, null, ['error' => 'INVALID_FORMAT']);
923
            }
924
        } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $exception) {
925
            // A redirect always throws this exception, but in this case, however,
926
            // redirection is desired and should not lead to an exception handling
927
        } catch (\RenanBr\BibTexParser\Exception\ParserException $exception) {
928
            $this->redirect('uploadStart', null, null, ['error' => 'INVALID_FORMAT']);
929
        }
930
931
    }
932
933
    /**
934
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
935
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
936
     */
937
    public function importUploadedDataAction()
938
    {
939
        try {
940
            $externalMetadata = $this->externalMetadataRepository->findByFeUser($this->security->getUser()->getUid());
941
942
            $importedDocuments = [];
943
            $importedDocumentIdentifiers = [];
944
945
            /** @var ExternalMetadata $externalMetadataItem */
946
            foreach ($externalMetadata as $externalMetadataItem) {
947
948
                /** @var  Importer $importer */
949
                $importer = $this->objectManager->get($externalMetadataItem->getSource());
950
951
                /** @var Document $newDocument */
952
                $newDocument = $importer->import($externalMetadataItem);
953
954
                if ($newDocument instanceof Document) {
955
                    $this->documentRepository->add($newDocument);
956
                    $this->externalMetadataRepository->remove($externalMetadataItem);
957
                    $importedDocuments[] = $newDocument;
958
                }
959
            }
960
961
            $this->persistenceManager->persistAll();
962
963
            // Documents can only be indexed after they have been persisted as we need a valid UID.
964
            /** @var Document $importedDocument */
965
            foreach ($importedDocuments as $importedDocument) {
966
                // index the document
967
                $this->signalSlotDispatcher->dispatch(
968
                    AbstractController::class, 'indexDocument', [$importedDocument]
969
                );
970
                $importedDocumentIdentifiers[] = $importedDocument->getDocumentIdentifier();
971
            }
972
973
            /** @var BulkImportSessionData $bulkImportSessionData */
974
            $bulkImportSessionData = $this->session->getBulkImportData();
975
            $bulkImportSessionData->setLatestImportIdentifiers($importedDocumentIdentifiers);
976
            $this->session->setBulkImportData($bulkImportSessionData);
977
978
        } catch(\Throwable $throwable) {
979
            $this->logger->error($throwable->getMessage());
980
981
            $message = LocalizationUtility::translate(
982
                'manager.importMetadata.publicationNotImported', 'dpf'
983
            );
984
985
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
986
        }
987
988
        $this->redirect(
989
            'uploadedDocuments',
990
            null,
991
            null,
992
            ['from' => 0, 'importCounter' => sizeof($importedDocumentIdentifiers)]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $importedDocumentIdentifiers does not seem to be defined for all execution paths leading up to this point.
Loading history...
993
    }
994
995
996
    /**
997
     * @param int $importCounter
998
     */
999
    public function uploadedDocumentsAction($importCounter = 0)
1000
    {
1001
        $publicationSingular = LocalizationUtility::translate('manager.importMetadata.publication.singular', 'dpf');
1002
        $publicationPlural = LocalizationUtility::translate('manager.importMetadata.publication.plural', 'dpf');
1003
1004
        if ($importCounter != 1) {
1005
            $messageKey = 'manager.uploadImport.importMessage.plural';
1006
        } else {
1007
            $messageKey = 'manager.uploadImport.importMessage.singular';
1008
        }
1009
1010
        $message = LocalizationUtility::translate(
1011
            $messageKey,
1012
            'dpf',
1013
            [
1014
                0 => $importCounter,
1015
                1 => ($importCounter == 1? $publicationSingular : $publicationPlural)
1016
            ]
1017
        );
1018
1019
        if ($importCounter > 0) {
1020
            $severity = AbstractMessage::INFO;
1021
            $this->addFlashMessage($message, '', $severity);
1022
1023
            if ($this->security->getUserRole() != Security::ROLE_LIBRARIAN) {
1024
                $importNoteMessage = LocalizationUtility::translate('manager.uploadImport.importNote', 'dpf');
1025
                $this->addFlashMessage(
1026
                    $importNoteMessage, '', AbstractMessage::INFO
1027
                );
1028
            }
1029
            
1030
            $this->showImportedDocuments($importCounter);
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Controller\Exter...showImportedDocuments() has too many arguments starting with $importCounter. ( Ignorable by Annotation )

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

1030
            $this->/** @scrutinizer ignore-call */ 
1031
                   showImportedDocuments($importCounter);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1031
        } else {
1032
            $severity = AbstractMessage::WARNING;
1033
            $this->addFlashMessage($message, '', $severity);
1034
            $this->redirect('uploadStart');
1035
        }
1036
    }
1037
}
1038