Issues (3936)

Controller/ExternalMetadataImportController.php (11 issues)

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

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

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

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

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

750
        $this->/** @scrutinizer ignore-call */ 
751
               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...
751
    }
752
753
    /**
754
     *
755
     */
756
    protected function showImportedDocuments()
757
    {
758
        $this->session->setStoredAction($this->getCurrentAction(), $this->getCurrentController(),
759
            $this->uriBuilder->getRequest()->getRequestUri()
0 ignored issues
show
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

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

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

1032
            $this->/** @scrutinizer ignore-call */ 
1033
                   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...
1033
        } else {
1034
            $severity = AbstractMessage::WARNING;
1035
            $this->addFlashMessage($message, '', $severity);
1036
            $this->redirect('uploadStart');
1037
        }
1038
    }
1039
}
1040