Passed
Pull Request — master (#166)
by
unknown
10:28 queued 47s
created

WorkspaceController::listWorkspaceAction()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 21
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 31
rs 9.2728
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\Bookmark;
18
use EWW\Dpf\Domain\Model\Document;
19
use EWW\Dpf\Security\DocumentVoter;
20
use EWW\Dpf\Security\Security;
21
use EWW\Dpf\Services\Email\Notifier;
22
use EWW\Dpf\Domain\Workflow\DocumentWorkflow;
23
use TYPO3\CMS\Core\Messaging\AbstractMessage;
24
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
25
26
/**
27
 * Controller for the "workspace"/"my publications" area.
28
 */
29
class WorkspaceController  extends AbstractController
30
{
31
    const MAXIMUM_NUMBER_OF_LINKS = 5;
32
    const DEFAULT_SORT_FIELD = 'title';
33
    const DEFAULT_SORT_ORDER = 'asc';
34
35
    /**
36
     * documentRepository
37
     *
38
     * @var \EWW\Dpf\Domain\Repository\DocumentRepository
39
     * @inject
40
     */
41
    protected $documentRepository = null;
42
43
    /**
44
     * documentTypeRepository
45
     *
46
     * @var \EWW\Dpf\Domain\Repository\DocumentTypeRepository
47
     * @inject
48
     */
49
    protected $documentTypeRepository = null;
50
51
    /**
52
     * bookmarkRepository
53
     *
54
     * @var \EWW\Dpf\Domain\Repository\BookmarkRepository
55
     * @inject
56
     */
57
    protected $bookmarkRepository = null;
58
59
    /**
60
     * elasticSearch
61
     *
62
     * @var \EWW\Dpf\Services\ElasticSearch\ElasticSearch
63
     * @inject
64
     */
65
    protected $elasticSearch = null;
66
67
    /**
68
     * documentManager
69
     *
70
     * @var \EWW\Dpf\Services\Document\DocumentManager
71
     * @inject
72
     */
73
    protected $documentManager = null;
74
75
    /**
76
     * documentValidator
77
     *
78
     * @var \EWW\Dpf\Helper\DocumentValidator
79
     * @inject
80
     */
81
    protected $documentValidator;
82
83
    /**
84
     * editingLockService
85
     *
86
     * @var \EWW\Dpf\Services\Document\EditingLockService
87
     * @inject
88
     */
89
    protected $editingLockService = null;
90
91
92
    /**
93
     * list
94
     *
95
     * @param int $from
96
     * @return void
97
     */
98
    protected function list($from = 0)
99
    {
100
        $bookmarkIdentifiers = array();
101
        $bookmarks = $this->bookmarkRepository->findByFeUserUid($this->security->getUser()->getUid());
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

101
        /** @scrutinizer ignore-call */ 
102
        $bookmarks = $this->bookmarkRepository->findByFeUserUid($this->security->getUser()->getUid());
Loading history...
102
        foreach ($bookmarks as $bookmark) {
103
            $bookmarkIdentifiers[] = $bookmark->getDocumentIdentifier();
104
        }
105
106
        $filters = $this->getSessionData('workspaceFilters');
107
        if (!$filters) {
108
            $filters = [];
109
        }
110
        $excludeFilters = $this->session->getWorkspaceExcludeFilters();
111
        if (!$excludeFilters) {
112
            $excludeFilters = [];
113
        }
114
115
        list($sortField, $sortOrder) = $this->session->getWorkspaceSort();
116
117
        if ($this->security->getUser()->getUserRole() == Security::ROLE_LIBRARIAN) {
118
            $query = $this->getWorkspaceQuery($from, $bookmarkIdentifiers,
119
                $filters, $excludeFilters, $sortField, $sortOrder);
120
        } elseif ($this->security->getUser()->getUserRole() == Security::ROLE_RESEARCHER) {
121
            $query = $this->getMyPublicationsQuery($from, $bookmarkIdentifiers,
122
                $filters, $excludeFilters, $sortField, $sortOrder);
123
        }
124
125
        try {
126
            $results = $this->elasticSearch->search($query, 'object');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $query does not seem to be defined for all execution paths leading up to this point.
Loading history...
127
        } catch (\Exception $e) {
128
            $this->session->clearWorkspaceSort();
129
            $this->addFlashMessage(
130
                "Error while buildig the list!", '', AbstractMessage::ERROR
131
            );
132
        }
133
134
        if ($this->request->hasArgument('message')) {
135
            $this->view->assign('message', $this->request->getArgument('message'));
136
        }
137
138
        if ($this->request->hasArgument('errorFiles')) {
139
            $this->view->assign('errorFiles', $this->request->getArgument('errorFiles'));
140
        }
141
142
        if ($filters && $results['hits']['total']['value'] < 1) {
143
            $this->session->clearFilter();
144
            list($redirectAction, $redirectController) = $this->session->getListAction();
145
            $this->redirect(
146
                $redirectAction, $redirectController, null,
147
                array('message' => [], 'checkedDocumentIdentifiers' => [])
148
            );
149
        }
150
151
        $this->view->assign('documentCount', $results['hits']['total']['value']);
152
        $this->view->assign('documents', $results['hits']['hits']);
153
        $this->view->assign('pages', range(1, $results['hits']['total']['value']));
154
        $this->view->assign('itemsPerPage', $this->itemsPerPage());
155
        $this->view->assign('maximumNumberOfLinks', self::MAXIMUM_NUMBER_OF_LINKS);
156
        $this->view->assign('aggregations', $results['aggregations']);
157
        $this->view->assign('filters', $filters);
158
        $this->view->assign('isHideDiscarded', array_key_exists('aliasState', $excludeFilters));
159
        $this->view->assign('isBookmarksOnly', array_key_exists('bookmarks', $excludeFilters));
160
        $this->view->assign('bookmarkIdentifiers', $bookmarkIdentifiers);
161
    }
162
163
    /**
164
     * Lists documents of the workspace
165
     *
166
     * @param array $checkedDocumentIdentifiers
167
     *
168
     * @return void
169
     */
170
    protected function listWorkspaceAction($checkedDocumentIdentifiers = [])
171
    {
172
        if ($this->security->getUser()->getUserRole() === Security::ROLE_LIBRARIAN) {
173
            $this->view->assign('isWorkspace', true);
174
        } elseif ($this->security->getUser()->getUserRole() === Security::ROLE_RESEARCHER) {
175
            $this->view->assign('isWorkspace', false);
176
        } else {
177
            $message = LocalizationUtility::translate(
178
                'manager.workspace.accessDenied', 'dpf'
179
            );
180
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
181
        }
182
183
        $this->session->setListAction($this->getCurrentAction(), $this->getCurrentController(),
184
            $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

184
            $this->uriBuilder->getRequest()->/** @scrutinizer ignore-call */ getRequestUri()
Loading history...
185
        );
186
187
        $currentPage = null;
188
        $pagination = $this->getParametersSafely('@widget_0');
189
        if ($pagination) {
190
            $checkedDocumentIdentifiers = [];
191
            $currentPage = $pagination['currentPage'];
192
        } else {
193
            $currentPage = 1;
194
        }
195
196
        $this->list((empty($currentPage)? 0 : ($currentPage-1) * $this->itemsPerPage()));
197
198
        $this->view->assign('currentPage', $currentPage);
199
        $this->view->assign('workspaceListAction', $this->getCurrentAction());
200
        $this->view->assign('checkedDocumentIdentifiers', $checkedDocumentIdentifiers);
201
    }
202
203
204
    /**
205
     * Batch operations action.
206
     * @param array $listData
207
     */
208
    public function batchAction($listData)
209
    {
210
        if (array_key_exists('action', $listData)) {
211
            $this->forward($listData['action'], null, null, ['listData' => $listData]);
212
        }
213
    }
214
215
    /**
216
     * Batch operation, register documents.
217
     * @param array $listData
218
     * @throws \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException
219
     */
220
    public function batchRegisterAction($listData)
221
    {
222
        $successful = [];
223
        $checkedDocumentIdentifiers = [];
224
225
        if (array_key_exists('documentIdentifiers', $listData) && is_array($listData['documentIdentifiers']) ) {
226
            $checkedDocumentIdentifiers = $listData['documentIdentifiers'];
227
            foreach ($listData['documentIdentifiers'] as $documentIdentifier) {
228
229
                $this->editingLockService->lock(
230
                    $documentIdentifier, $this->security->getUser()->getUid()
231
                );
232
233
                if (is_numeric($documentIdentifier)) {
234
                    $document = $this->documentManager->read($documentIdentifier);
235
236
                    if ($this->authorizationChecker->isGranted(DocumentVoter::REGISTER, $document)) {
237
238
                        if ($this->documentValidator->validate($document, false)) {
0 ignored issues
show
Bug introduced by
It seems like $document can also be of type null; however, parameter $document of EWW\Dpf\Helper\DocumentValidator::validate() does only seem to accept EWW\Dpf\Domain\Model\Document, maybe add an additional type check? ( Ignorable by Annotation )

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

238
                        if ($this->documentValidator->validate(/** @scrutinizer ignore-type */ $document, false)) {
Loading history...
239
240
                            if (
241
                                $this->documentManager->update(
242
                                    $document,
0 ignored issues
show
Bug introduced by
It seems like $document can also be of type null; however, parameter $document of EWW\Dpf\Services\Documen...cumentManager::update() does only seem to accept EWW\Dpf\Domain\Model\Document, maybe add an additional type check? ( Ignorable by Annotation )

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

242
                                    /** @scrutinizer ignore-type */ $document,
Loading history...
243
                                    DocumentWorkflow::TRANSITION_REGISTER
244
                                )
245
                            ) {
246
                                $this->bookmarkRepository->addBookmark(
247
                                    $this->security->getUser()->getUid(), $document
248
                                );
249
250
                                $successful[] = $documentIdentifier;
251
252
                                $notifier = $this->objectManager->get(Notifier::class);
253
                                $notifier->sendRegisterNotification($document);
254
255
                                // index the document
256
                                $this->signalSlotDispatcher->dispatch(
257
                                    \EWW\Dpf\Controller\AbstractController::class,
258
                                    'indexDocument', [$document]
259
                                );
260
                            }
261
                        }
262
                    }
263
                }
264
            }
265
266
267
            if (sizeof($successful) == 1) {
268
                $locallangKey = 'manager.workspace.batchAction.register.success.singular';
269
            } else {
270
                $locallangKey = 'manager.workspace.batchAction.register.success.plural';
271
            }
272
273
            $message = LocalizationUtility::translate(
274
                $locallangKey,
275
                'dpf',
276
                [sizeof($successful), sizeof($listData['documentIdentifiers'])]
277
            );
278
279
280
            $this->addFlashMessage(
281
                $message, '',
282
                (sizeof($successful) > 0 ? AbstractMessage::OK : AbstractMessage::WARNING)
283
            );
284
285
        } else {
286
            $message = LocalizationUtility::translate(
287
                'manager.workspace.batchAction.failure',
288
                'dpf');
289
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
290
        }
291
292
        list($redirectAction, $redirectController) = $this->session->getListAction();
293
        $this->redirect(
294
            $redirectAction, $redirectController, null,
295
            array('message' => $message, 'checkedDocumentIdentifiers' =>  $checkedDocumentIdentifiers));
296
    }
297
298
    /**
299
     * Batch operation, remove documents.
300
     * @param array $listData
301
     */
302
    public function batchRemoveAction($listData)
303
    {
304
        $successful = [];
305
        $checkedDocumentIdentifiers = [];
306
307
        if (array_key_exists('documentIdentifiers', $listData) && is_array($listData['documentIdentifiers']) ) {
308
            $checkedDocumentIdentifiers = $listData['documentIdentifiers'];
309
            foreach ($listData['documentIdentifiers'] as $documentIdentifier) {
310
                $feUserUid = $this->security->getUser()->getUid();
311
                $bookmark = $this->bookmarkRepository->findBookmark($feUserUid, $documentIdentifier);
312
                if ($bookmark instanceof Bookmark) {
313
                    $this->bookmarkRepository->remove($bookmark);
314
                    $successful[] = $documentIdentifier;
315
                }
316
            }
317
318
319
            if (sizeof($successful) == 1) {
320
                $locallangKey = 'manager.workspace.batchAction.remove.success.singular';
321
            } else {
322
                $locallangKey = 'manager.workspace.batchAction.remove.success.plural';
323
            }
324
325
            $message = LocalizationUtility::translate(
326
                $locallangKey,
327
                'dpf',
328
                [sizeof($successful), sizeof($listData['documentIdentifiers'])]
329
            );
330
            $this->addFlashMessage(
331
                $message, '',
332
                (sizeof($successful) > 0 ? AbstractMessage::OK : AbstractMessage::WARNING)
333
            );
334
        } else {
335
            $message = LocalizationUtility::translate(
336
                'manager.workspace.batchAction.failure',
337
                'dpf');
338
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
339
        }
340
341
        list($redirectAction, $redirectController) = $this->session->getListAction();
342
        $this->redirect(
343
            $redirectAction, $redirectController, null,
344
            array('message' => $message, 'checkedDocumentIdentifiers' =>  $checkedDocumentIdentifiers));
345
    }
346
347
348
    /**
349
     * Batch operation, release documents.
350
     * @param array $listData
351
     */
352
    public function batchReleaseValidatedAction($listData)
353
    {
354
        $this->batchRelease($listData, true);
355
    }
356
357
    /**
358
     * Batch operation, release as unvalidated documents.
359
     * @param array $listData
360
     */
361
    public function batchReleaseUnvalidatedAction($listData)
362
    {
363
        $this->batchRelease($listData, false);
364
    }
365
366
367
368
369
    /**
370
     * Batch operation, release documents.
371
     * @param array $listData
372
     * @param bool $validated
373
     */
374
    protected function batchRelease($listData, $validated)
375
    {
376
        $successful = [];
377
        $checkedDocumentIdentifiers = [];
378
379
        if (array_key_exists('documentIdentifiers', $listData) && is_array($listData['documentIdentifiers']) ) {
380
            $checkedDocumentIdentifiers = $listData['documentIdentifiers'];
381
            foreach ($listData['documentIdentifiers'] as $documentIdentifier) {
382
383
                $this->editingLockService->lock(
384
                    $documentIdentifier, $this->security->getUser()->getUid()
385
                );
386
387
                $document = $this->documentManager->read($documentIdentifier);
388
389
                switch ($document->getState()) {
390
                    case DocumentWorkflow::STATE_REGISTERED_NONE:
391
                    case DocumentWorkflow::STATE_DISCARDED_NONE:
392
                    case DocumentWorkflow::STATE_POSTPONED_NONE:
393
                        $documentVoterAttribute = DocumentVoter::RELEASE_PUBLISH;
394
                        $documentWorkflowTransition = DocumentWorkflow::TRANSITION_RELEASE_PUBLISH;
395
                        break;
396
397
                    case DocumentWorkflow::STATE_NONE_DELETED:
398
                    case DocumentWorkflow::STATE_NONE_INACTIVE:
399
                    case DocumentWorkflow::STATE_IN_PROGRESS_DELETED:
400
                    case DocumentWorkflow::STATE_IN_PROGRESS_INACTIVE:
401
                    case DocumentWorkflow::STATE_IN_PROGRESS_ACTIVE:
402
                        $documentVoterAttribute = DocumentVoter::RELEASE_ACTIVATE;
403
                        $documentWorkflowTransition = DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE;
404
                        break;
405
                    default:
406
                        $documentVoterAttribute = null;
407
                        $documentWorkflowTransition = null;
408
                        break;
409
                }
410
411
                if ($this->authorizationChecker->isGranted($documentVoterAttribute, $document)) {
412
413
                    $slub = new \EWW\Dpf\Helper\Slub($document->getSlubInfoData());
414
415
                    $slub->setValidation($validated);
416
                    $document->setSlubInfoData($slub->getSlubXml());
417
418
                    if ($this->documentManager->update($document, $documentWorkflowTransition)) {
0 ignored issues
show
Bug introduced by
It seems like $document can also be of type null; however, parameter $document of EWW\Dpf\Services\Documen...cumentManager::update() does only seem to accept EWW\Dpf\Domain\Model\Document, maybe add an additional type check? ( Ignorable by Annotation )

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

418
                    if ($this->documentManager->update(/** @scrutinizer ignore-type */ $document, $documentWorkflowTransition)) {
Loading history...
419
                        $successful[] = $documentIdentifier;
420
421
                        $this->bookmarkRepository->removeBookmark(
422
                            $document, $this->security->getUser()->getUid()
423
                        );
424
425
                        //$notifier = $this->objectManager->get(Notifier::class);
426
                        //$notifier->sendRegisterNotification($document);
427
                    }
428
                }
429
            }
430
431
            if (sizeof($successful) == 1) {
432
                $locallangKey = 'manager.workspace.batchAction.release.success.singular';
433
            } else {
434
                $locallangKey = 'manager.workspace.batchAction.release.success.plural';
435
            }
436
437
            $message = LocalizationUtility::translate(
438
                $locallangKey,
439
                'dpf',
440
                [sizeof($successful), sizeof($listData['documentIdentifiers'])]
441
            );
442
            $this->addFlashMessage(
443
                $message, '',
444
                (sizeof($successful) > 0 ? AbstractMessage::OK : AbstractMessage::WARNING)
445
            );
446
447
            if (sizeof($successful) === 1 ) {
448
                $this->addFlashMessage(
449
                    "1 ".LocalizationUtility::translate("manager.workspace.bookmarkRemoved.singular", "dpf"),
450
                    '',
451
                    AbstractMessage::INFO
452
                );
453
            }
454
455
            if (sizeof($successful) > 1 ) {
456
                $this->addFlashMessage(
457
                    LocalizationUtility::translate(
458
                        "manager.workspace.bookmarkRemoved.plural", "dpf", [sizeof($successful)]
459
                    ),
460
                    '',
461
                    AbstractMessage::INFO
462
                );
463
            }
464
465
        } else {
466
            $message = LocalizationUtility::translate(
467
                'manager.workspace.batchAction.failure',
468
                'dpf');
469
            $this->addFlashMessage($message, '', AbstractMessage::ERROR);
470
        }
471
472
        list($redirectAction, $redirectController) = $this->session->getListAction();
473
        $this->redirect(
474
            $redirectAction, $redirectController, null,
475
            array('message' => $message, 'checkedDocumentIdentifiers' =>  $checkedDocumentIdentifiers));
476
477
    }
478
479
    /**
480
     * get list view data for the workspace
481
     *
482
     * @param int $from
483
     * @param array $bookmarkIdentifiers
484
     * @param array $filters
485
     * @param array $excludeFilters
486
     * @param string $sortField
487
     * @param string $sortOrder
488
     *
489
     * @return array
490
     */
491
    protected function getWorkspaceQuery(
492
        $from = 0, $bookmarkIdentifiers = [], $filters = [], $excludeFilters = [], $sortField = null, $sortOrder = null
493
    )
494
    {
495
        $workspaceFilter = [
496
            'bool' => [
497
                'must' => [
498
                    [
499
                        'bool' => [
500
                            'must' => [
501
                                [
502
                                    'term' => [
503
                                        'creator' => $this->security->getUser()->getUid()
504
                                    ]
505
                                ],
506
                                [
507
                                    'bool' => [
508
                                        'should' => [
509
                                            [
510
                                                'term' => [
511
                                                    'state' => DocumentWorkflow::STATE_NEW_NONE
512
                                                ]
513
                                            ]
514
                                        ]
515
                                    ]
516
                                ]
517
                            ]
518
                        ]
519
                    ]
520
                ]
521
            ]
522
        ];
523
524
        return $this->buildQuery(
525
            $workspaceFilter, $from, $bookmarkIdentifiers, $filters,
526
            $excludeFilters, $sortField, $sortOrder
527
        );
528
    }
529
530
531
    /**
532
     * get list view data for the my publications list.
533
     *
534
     * @param int $from
535
     * @param array $bookmarkIdentifiers
536
     * @param array $filters
537
     * @param array $excludeFilters
538
     * @param string $sortField
539
     * @param string $sortOrder
540
     *
541
     * @return array
542
     */
543
    protected function getMyPublicationsQuery(
544
        $from = 0, $bookmarkIdentifiers = [], $filters = [], $excludeFilters = [], $sortField = null, $sortOrder = null
545
    )
546
    {
547
        $workspaceFilter = [
548
            'bool' => [
549
                'must' => [
550
                    [
551
                        'term' => [
552
                            'creator' => $this->security->getUser()->getUid()
553
                        ]
554
                    ]
555
                ]
556
            ]
557
        ];
558
559
        return $this->buildQuery(
560
            $workspaceFilter, $from, $bookmarkIdentifiers, $filters,
561
            $excludeFilters, $sortField, $sortOrder
562
        );
563
    }
564
565
    /**
566
     * Builds the document list query.
567
     *
568
     * @param array $workspaceFilter
569
     * @param int $from
570
     * @param array $bookmarkIdentifiers
571
     * @param array $filters
572
     * @param array $excludeFilters
573
     * @param string $sortField
574
     * @param string $sortOrder
575
     *
576
     * @return array
577
     */
578
    protected function buildQuery(
579
        $workspaceFilter, $from = 0, $bookmarkIdentifiers = [], $filters = [], $excludeFilters = [], $sortField = null, $sortOrder = null
580
    )
581
    {
582
        // The base filter.
583
        $queryFilter = [
584
            'bool' => [
585
                'must' => [
586
                    [
587
                        'bool' => [
588
                            'should' => [
589
                                0 => $workspaceFilter
590
                            ]
591
                        ]
592
                    ]
593
                ]
594
            ]
595
        ];
596
597
        if (!($excludeFilters && array_key_exists('bookmarks', $excludeFilters))) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $excludeFilters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
598
            // Add user document bookmarks.
599
            if ($bookmarkIdentifiers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $bookmarkIdentifiers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
600
                $queryFilter['bool']['must'][0]['bool']['should'][] = [
601
                    'terms' => [
602
                        '_id' => $bookmarkIdentifiers
603
                    ]
604
                ];
605
            }
606
        } else {
607
            // Show only user document bookmarks.
608
            $queryFilter['bool']['must'][0] = [
609
                'terms' => [
610
                    '_id' => $bookmarkIdentifiers
611
                ]
612
            ];
613
        }
614
615
        $filterPart = $this->buildFilterQueryPart($filters, $excludeFilters);
616
617
        if ($filterPart) {
618
            $queryFilter['bool']['must'][] = $filterPart;
619
        }
620
621
        // Put together the complete query.
622
        $query = [
623
            'body' => [
624
                'size' => $this->itemsPerPage(),
625
                'from' => $from,
626
                'query' => [
627
                    'bool' => [
628
                        'must' => [
629
                            'match_all' => (object)[]
630
                        ],
631
                        'filter' => $queryFilter
632
                    ]
633
                ],
634
                'sort' => $this->buildSortQueryPart($sortField, $sortOrder),
635
                'aggs' => [
636
                    'aliasState' => [
637
                        'terms' => [
638
                            'field' => 'aliasState'
639
                        ]
640
                    ],
641
                    'year' => [
642
                        'terms' => [
643
                            'field' => 'year'
644
                        ]
645
                    ],
646
                    'doctype' => [
647
                        'terms' => [
648
                            'field' => 'doctype'
649
                        ]
650
                    ],
651
                    'hasFiles' => [
652
                        'terms' => [
653
                            'field' => 'hasFiles'
654
                        ]
655
                    ],
656
                    'universityCollection' => [
657
                        'terms' => [
658
                            'script' => [
659
                                'lang' => 'painless',
660
                                'source' =>
661
                                    "for (int i = 0; i < doc['collections'].length; ++i) {".
662
                                    "    if(doc['collections'][i] =='".$this->settings['universityCollection']."') {".
663
                                    "        return 'true';".
664
                                    "    }".
665
                                    "}".
666
                                    "return 'false';"
667
                                ]
668
                        ]
669
                    ],
670
                    'authorAndPublisher' => [
671
                        'terms' => [
672
                            'field' => 'authorAndPublisher'
673
                        ]
674
                    ],
675
                    'creatorRole' => [
676
                        'terms' => [
677
                            'script' => [
678
                                'lang' => 'painless',
679
                                'source' =>
680
                                    "if (".
681
                                    "    doc['creator'].size() > 0 &&".
682
                                    "    doc['creator'].value == '".$this->security->getUser()->getUid()."') {".
683
                                    "    return 'self';".
684
                                    "}".
685
                                    "if (".
686
                                    "    doc['creatorRole'].size() > 0 &&".
687
                                    "    doc['creatorRole'].value == '".Security::ROLE_LIBRARIAN."'".
688
                                    ") {".
689
                                    "    return 'librarian';".
690
                                    "}".
691
                                    "if (".
692
                                    "    doc['creatorRole'].size() > 0 &&".
693
                                    "    doc['creatorRole'].value == '".Security::ROLE_RESEARCHER."'".
694
                                    ") {".
695
                                    "    return 'user';".
696
                                    "}".
697
                                    "return 'unknown';"
698
                            ]
699
                        ]
700
                    ]
701
702
                ]
703
            ]
704
        ];
705
706
        return $query;
707
    }
708
709
    /**
710
     * Composes the filter part based on the given filters.
711
     *
712
     * @param array $filters
713
     * @param array $excludeFilters
714
     * @return array
715
     */
716
    protected function buildFilterQueryPart($filters, $excludeFilters = []) {
717
718
        $queryFilter = [];
719
720
        // Build the column filter part.
721
        if ($filters && is_array($filters)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
722
723
            $validKeys = [
724
                'aliasState', 'authorAndPublisher', 'doctype', 'hasFiles', 'year', 'universityCollection', 'creatorRole'
725
            ];
726
727
            foreach ($filters as $key => $filterValues) {
728
                $queryFilterPart = [];
729
                if (in_array($key, $validKeys, true)) {
730
                    if ($key == 'universityCollection') {
731
                        if ($filterValues && is_array($filterValues)) {
732
                            if (in_array("true", $filterValues)) {
733
                                $filterValue = $this->settings['universityCollection'];
734
                                $queryFilterPart['bool']['should'][] = [
735
                                    'term' => [
736
                                        'collections' => $filterValue
737
                                    ]
738
                                ];
739
                            } else {
740
                                $filterValue = $this->settings['universityCollection'];
741
                                $queryFilterPart['bool']['should'][] = [
742
                                    'bool' => [
743
                                        'must_not' => [
744
                                            'term' => [
745
                                                'collections' => $filterValue
746
                                            ]
747
                                        ]
748
                                    ]
749
                                ];
750
                            }
751
                            $queryFilter['bool']['must'][] = $queryFilterPart;
752
                        }
753
                    } elseif ($key == 'creatorRole') {
754
                        $queryFilterPart = [];
755
                        if ($filterValues && is_array($filterValues)) {
756
                            if (in_array("librarian", $filterValues)) {
757
                                $creatorRolePart['bool']['must'] = [
758
                                    [
759
                                        'term' => [
760
                                            'creatorRole' => Security::ROLE_LIBRARIAN
761
                                        ]
762
                                    ],
763
                                    [
764
                                        'bool' => [
765
                                            'must_not' => [
766
                                                'term' => [
767
                                                    'creator' => $this->security->getUser()->getUid()
768
                                                ]
769
                                            ]
770
                                        ]
771
                                    ]
772
                                ];
773
                                $queryFilterPart['bool']['should'][] = $creatorRolePart;
774
                            } elseif (in_array("user", $filterValues)) {
775
                                $creatorRolePart['bool']['must'] = [
776
                                    [
777
                                        'term' => [
778
                                            'creatorRole' => Security::ROLE_RESEARCHER
779
                                        ]
780
                                    ],
781
                                    [
782
                                        'bool' => [
783
                                            'must_not' => [
784
                                                'term' => [
785
                                                    'creator' => $this->security->getUser()->getUid()
786
                                                ]
787
                                            ]
788
                                        ]
789
                                    ]
790
                                ];
791
                                $queryFilterPart['bool']['should'][] = $creatorRolePart;
792
                            } elseif (in_array("self", $filterValues)) {
793
                                $creatorRolePart['bool']['must'] = [
794
                                    [
795
                                        'term' => [
796
                                            'creator' =>  $this->security->getUser()->getUid()
797
                                        ]
798
                                    ]
799
                                ];
800
                                $queryFilterPart['bool']['should'][] = $creatorRolePart;
801
                            } else {
802
                                $creatorRolePart['bool']['must'] = [
803
                                    [
804
                                        'bool' => [
805
                                            'must_not' => [
806
                                                'term' => [
807
                                                    'creator' => $this->security->getUser()->getUid()
808
                                                ]
809
                                            ]
810
                                        ]
811
                                    ],
812
                                    [
813
                                        'bool' => [
814
                                            'must_not' => [
815
                                                'term' => [
816
                                                    'creatorRole' => Security::ROLE_LIBRARIAN
817
                                                ]
818
                                            ]
819
                                        ]
820
                                    ],
821
                                    [
822
                                        'bool' => [
823
                                            'must_not' => [
824
                                                'term' => [
825
                                                    'creatorRole' => Security::ROLE_RESEARCHER
826
                                                ]
827
                                            ]
828
                                        ]
829
                                    ]
830
                                ];
831
                                $queryFilterPart['bool']['should'][] = $creatorRolePart;
832
                            }
833
834
                            if ($queryFilterPart) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $queryFilterPart of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
835
                                $queryFilter['bool']['must'][] = $queryFilterPart;
836
                            }
837
                        }
838
                    } else {
839
                        if ($filterValues && is_array($filterValues)) {
840
                            foreach ($filterValues as $filterValue) {
841
                                $queryFilterPart['bool']['should'][] = [
842
                                    'term' => [
843
                                        $key => $filterValue
844
                                    ]
845
                                ];
846
                            }
847
                            $queryFilter['bool']['must'][] = $queryFilterPart;
848
                        }
849
                    }
850
                }
851
            }
852
        }
853
854
        if ($excludeFilters && array_key_exists('aliasState', $excludeFilters)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $excludeFilters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
855
            if ($excludeFilters['aliasState']) {
856
                foreach ($excludeFilters['aliasState'] as $aliasStateExclude) {
857
                    $queryFilter['bool']['must'][] = [
858
                        'bool' => [
859
                            'must_not' => [
860
                                'bool' => [
861
                                    'must' => [
862
                                        [
863
                                            'term' => [
864
                                                'aliasState' => $aliasStateExclude
865
                                            ]
866
                                        ],
867
                                        [
868
                                            'term' => [
869
                                                'creator' => $this->security->getUser()->getUid()
870
                                            ]
871
                                        ]
872
                                    ]
873
                                ]
874
                            ]
875
                        ]
876
                    ];
877
                }
878
            }
879
        }
880
881
        return $queryFilter;
882
    }
883
884
885
    /**
886
     * Composes the sort query part based on the given sort field and order.
887
     *
888
     * @param string $sortField
889
     * @param string $sortOrder
890
     * @return array
891
     */
892
    protected function buildSortQueryPart($sortField, $sortOrder) {
893
        // Build the sorting part.
894
        $script = "";
895
        if ($sortField == "aliasState") {
896
            $script = $this->getSortScriptState();
897
        } elseif ($sortField == "universityCollection") {
898
            $script = $this->getSortScriptUniversityCollection($this->settings['universityCollection']);
899
        } elseif ($sortField == "hasFiles") {
900
            $script = $this->getSortScriptHasFiles();
901
        } elseif ($sortField == "creatorRole") {
902
            $script = $this->getSortScriptCreatorRole($this->security->getUser()->getUid());
903
        }
904
905
        if ($script) {
906
            $sort = [
907
                "_script" => [
908
                    "type" => "string",
909
                    "order" => $sortOrder,
910
                    "script" => [
911
                        "lang" => "painless",
912
                        "source" => $script
913
                    ]
914
                ],
915
                "title.keyword" => [
916
                    "order" => "asc"
917
                ]
918
            ];
919
        } else {
920
            if ($sortField == 'title') {
921
                $sortField.= ".keyword";
922
            }
923
924
            $sort = [
925
                (($sortField)? $sortField : self::DEFAULT_SORT_FIELD.".keyword") => [
926
                    'order' => (($sortOrder)? $sortOrder : self::DEFAULT_SORT_ORDER)
927
                ]
928
            ];
929
        }
930
931
        return $sort;
932
    }
933
934
935
    protected function getSortScriptUniversityCollection($collection)
936
    {
937
        $script  = "for (int i = 0; i < doc['collections'].length; ++i) {";
938
        $script .= "    if (doc['collections'][i] == '".$collection."') {";
939
        $script .= "        return '1';";
940
        $script .= "    }";
941
        $script .= "}";
942
        $script .= "return '2'";
943
944
        return $script;
945
    }
946
947
    protected function getSortScriptHasFiles()
948
    {
949
        $script = "if (doc['hasFiles'].value == 'true') {";
950
        $script .= "    return '1';";
951
        $script .= "}";
952
        $script .= "return '2'";
953
954
        return $script;
955
    }
956
957
    protected function getSortScriptCreatorRole($feUserUid)
958
    {
959
        $script = "if (doc['creator'].value == '".$feUserUid."') {";
960
        $script .= "    return '1';";
961
        $script .= "}";
962
        $script .= "if (doc['creatorRole'].value == '".Security::ROLE_LIBRARIAN."') {";
963
        $script .= "return '2';";
964
        $script .= "}";
965
        $script .= "if (doc['creatorRole'].value == '".Security::ROLE_RESEARCHER."') {";
966
        $script .= "    return '3';";
967
        $script .= "}";
968
        $script .= "return '4';";
969
970
        return $script;
971
    }
972
973
974
    protected function getSortScriptState()
975
    {
976
        $sortStates = [];
977
        foreach (DocumentWorkflow::PLACES as $state) {
978
            if (array_key_exists($state, DocumentWorkflow::STATE_TO_ALIASSTATE_MAPPING)) {
979
                $aliasState = DocumentWorkflow::STATE_TO_ALIASSTATE_MAPPING[$state];
980
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:manager.documentList.state.'.$aliasState;
981
                $stateName = LocalizationUtility::translate($key, 'dpf');
982
                $sortStates[] = "if (doc['state'].value == '".$state."') return '".$stateName."';";
983
            }
984
        }
985
986
        $sortStates = implode(" ", $sortStates);
987
988
        return $sortStates." return '';";
989
    }
990
991
992
    protected function getSortScriptDoctype()
993
    {
994
        $sortDoctypes = [];
995
        foreach ($this->documentTypeRepository->findAll() as $documentType) {
996
            if ($documentType->getName() && $documentType->getDisplayname()) {
997
                $sortDoctypes[] = "if (doc['doctype'].value == '".$documentType->getName()."')"
998
                    ." return '".$documentType->getDisplayname()."';";
999
            }
1000
        }
1001
1002
        $sortDoctypes = implode(" ", $sortDoctypes);
1003
1004
        return $sortDoctypes." return '';";
1005
    }
1006
1007
1008
    /**
1009
     * A temporary solution to initialize the index.
1010
     *
1011
     * @param int $start
1012
     * @param int $stop
1013
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
1014
     */
1015
    public function initIndexAction($start = 1, $stop = 100)
1016
    {
1017
        /** @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */
1018
        $signalSlotDispatcher = $this->objectManager->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
1019
1020
        /** @var \EWW\Dpf\Services\Transfer\DocumentTransferManager $documentTransferManager */
1021
        $documentTransferManager = $this->objectManager->get(\EWW\Dpf\Services\Transfer\DocumentTransferManager::class);
1022
1023
        $fedoraRepository = $this->objectManager->get(\EWW\Dpf\Services\Transfer\FedoraRepository::class);
1024
        $documentTransferManager->setRemoteRepository($fedoraRepository);
1025
1026
        for ($i = $start; $i < $stop; $i++) {
1027
            try {
1028
                $document = $documentTransferManager->retrieve('qucosa:' . $i);
1029
1030
                if ($document instanceof Document) {
1031
                    $state = $document->getState();
1032
                    $document->setState(
1033
                        str_replace(
1034
                            DocumentWorkflow::LOCAL_STATE_IN_PROGRESS,
1035
                            DocumentWorkflow::LOCAL_STATE_NONE,
1036
                            $state
1037
                        )
1038
                    );
1039
1040
                    // index the document
1041
                    $signalSlotDispatcher->dispatch(
1042
                        \EWW\Dpf\Controller\AbstractController::class,
1043
                        'indexDocument', [$document]
1044
                    );
1045
1046
                    $this->documentRepository->remove($document);
1047
                }
1048
            } catch (\EWW\Dpf\Exceptions\RetrieveDocumentErrorException $e) {
1049
                // Nothing to be done.
1050
            }
1051
        }
1052
1053
        foreach ($this->documentRepository->findAll() as $document) {
1054
            if (!$document->isTemporary() && !$document->isSuggestion()) {
1055
                // index the document
1056
                $signalSlotDispatcher->dispatch(
1057
                    \EWW\Dpf\Controller\AbstractController::class,
1058
                    'indexDocument', [$document]
1059
                );
1060
            }
1061
        }
1062
    }
1063
1064
1065
    /**
1066
     * action uploadFiles
1067
     *
1068
     * @param string $documentIdentifier
1069
     * @return void
1070
     */
1071
    public function uploadFilesAction($documentIdentifier)
1072
    {
1073
        $document = $this->documentManager->read(
1074
            $documentIdentifier,
1075
            $this->security->getUser()->getUID()
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Services\Document\DocumentManager::read() has too many arguments starting with $this->security->getUser()->getUID(). ( Ignorable by Annotation )

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

1075
        /** @scrutinizer ignore-call */ 
1076
        $document = $this->documentManager->read(

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...
1076
        );
1077
1078
        if ($document instanceof Document) {
1079
            if ($this->authorizationChecker->isGranted(DocumentVoter::EDIT, $document)) {
1080
                $this->redirect(
1081
                    'edit',
1082
                    'DocumentFormBackoffice',
1083
                    null,
1084
                    ['document' => $document, 'activeFileTab' => true]);
1085
            } elseif ($this->authorizationChecker->isGranted(DocumentVoter::SUGGEST_MODIFICATION, $document)) {
1086
                $this->redirect(
1087
                    'edit',
1088
                    'DocumentFormBackoffice',
1089
                    null,
1090
                    ['document' => $document, 'suggestMod' => true, 'activeFileTab' => true]);
1091
            } else {
1092
                if ($document->getCreator() !== $this->security->getUser()->getUid()) {
1093
                    $message = LocalizationUtility::translate(
1094
                        'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_edit.accessDenied',
1095
                        'dpf',
1096
                        array($document->getTitle())
1097
                    );
1098
                } else {
1099
                    $message = LocalizationUtility::translate(
1100
                        'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_edit.failureBlocked',
1101
                        'dpf',
1102
                        array($document->getTitle())
1103
                    );
1104
                }
1105
            }
1106
        } else {
1107
            $message = LocalizationUtility::translate(
1108
                'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:error.unexpected',
1109
                'dpf'
1110
            );
1111
        }
1112
1113
        $this->addFlashMessage($message, '', AbstractMessage::ERROR);
1114
1115
        list($action, $controller, $redirectUri) = $this->session->getListAction();
1116
1117
        if ($redirectUri) {
1118
            $this->redirectToUri($redirectUri);
1119
        } else {
1120
            $this->redirect($action, $controller, null, array('message' => $message));
1121
        }
1122
1123
    }
1124
1125
1126
    /**
1127
     * Returns the number of items to be shown per page.
1128
     *
1129
     * @return int
1130
     */
1131
    protected function itemsPerPage()
1132
    {
1133
        $itemsPerPage = $this->session->getWorkspaceItemsPerPage();
1134
        $default = ($this->settings['workspaceItemsPerPage'])? $this->settings['workspaceItemsPerPage'] : 10;
1135
        return ($itemsPerPage)? $itemsPerPage : $default;
1136
    }
1137
1138
}
1139