Passed
Pull Request — master (#166)
by
unknown
21:05
created

DocumentController::releaseUpdateAction()   B

Complexity

Conditions 8
Paths 25

Size

Total Lines 36
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 26
c 0
b 0
f 0
nc 25
nop 2
dl 0
loc 36
rs 8.4444

1 Method

Rating   Name   Duplication   Size   Complexity  
A DocumentController::initializeAction() 0 17 3
1
<?php
2
namespace EWW\Dpf\Controller;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use EWW\Dpf\Domain\Model\Document;
18
use EWW\Dpf\Security\DocumentVoter;
19
use EWW\Dpf\Security\Security;
20
use EWW\Dpf\Services\Transfer\ElasticsearchRepository;
21
use EWW\Dpf\Services\Transfer\DocumentTransferManager;
22
use EWW\Dpf\Services\Transfer\FedoraRepository;
23
use EWW\Dpf\Services\ProcessNumber\ProcessNumberGenerator;
24
use EWW\Dpf\Services\Email\Notifier;
25
use EWW\Dpf\Exceptions\DPFExceptionInterface;
26
use EWW\Dpf\Domain\Workflow\DocumentWorkflow;
27
use TYPO3\CMS\Core\Messaging\AbstractMessage;
28
use EWW\Dpf\Helper\DocumentMapper;
29
use EWW\Dpf\Domain\Model\File;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
32
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
33
34
35
/**
36
 * DocumentController
37
 */
38
class DocumentController extends AbstractController
39
{
40
41
    /**
42
     * documentRepository
43
     *
44
     * @var \EWW\Dpf\Domain\Repository\DocumentRepository
45
     * @inject
46
     */
47
    protected $documentRepository = null;
48
49
    /**
50
     * inputOptionListRepository
51
     *
52
     * @var \EWW\Dpf\Domain\Repository\InputOptionListRepository
53
     * @inject
54
     */
55
    protected $inputOptionListRepository = null;
56
57
    /**
58
     * persistence manager
59
     *
60
     * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
61
     * @inject
62
     */
63
    protected $persistenceManager;
64
65
    /**
66
     * editingLockService
67
     *
68
     * @var \EWW\Dpf\Services\Document\EditingLockService
69
     * @inject
70
     */
71
    protected $editingLockService = null;
72
73
    /**
74
     * documentValidator
75
     *
76
     * @var \EWW\Dpf\Helper\DocumentValidator
77
     * @inject
78
     */
79
    protected $documentValidator;
80
81
    /**
82
     * workflow
83
     *
84
     * @var \EWW\Dpf\Domain\Workflow\DocumentWorkflow
85
     */
86
    protected $workflow;
87
88
    /**
89
     * documentTransferManager
90
     *
91
     * @var \EWW\Dpf\Services\Transfer\DocumentTransferManager $documentTransferManager
92
     */
93
    protected $documentTransferManager;
94
95
    /**
96
     * fedoraRepository
97
     *
98
     * @var \EWW\Dpf\Services\Transfer\FedoraRepository $fedoraRepository
99
     */
100
    protected $fedoraRepository;
101
102
    /**
103
     * fileRepository
104
     *
105
     * @var \EWW\Dpf\Domain\Repository\FileRepository
106
     * @inject
107
     */
108
    protected $fileRepository = null;
109
110
111
    /**
112
     * frontendUserRepository
113
     *
114
     * @var \EWW\Dpf\Domain\Repository\FrontendUserRepository
115
     * @inject
116
     */
117
    protected $frontendUserRepository = null;
118
119
    /**
120
     * documentManager
121
     *
122
     * @var \EWW\Dpf\Services\Document\DocumentManager
123
     * @inject
124
     */
125
    protected $documentManager = null;
126
127
    /**
128
     * bookmarkRepository
129
     *
130
     * @var \EWW\Dpf\Domain\Repository\BookmarkRepository
131
     * @inject
132
     */
133
    protected $bookmarkRepository = null;
134
135
    /**
136
     * DocumentController constructor.
137
     */
138
    public function __construct()
139
    {
140
        parent::__construct();
141
142
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
143
        $this->documentTransferManager = $objectManager->get(DocumentTransferManager::class);
144
        $this->fedoraRepository = $objectManager->get(FedoraRepository::class);
145
        $this->documentTransferManager->setRemoteRepository($this->fedoraRepository);
146
    }
147
148
    /**
149
     * action logout of the backoffice
150
     *
151
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
152
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
153
     */
154
    public function logoutAction()
155
    {
156
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
157
        $uri = $cObj->typolink_URL([
158
            'parameter' => $this->settings['loginPage'],
159
            //'linkAccessRestrictedPages' => 1,
160
            'forceAbsoluteUrl' => 1,
161
            'additionalParams' => GeneralUtility::implodeArrayForUrl(NULL, ['logintype'=>'logout'])
162
        ]);
163
164
        $this->redirectToUri($uri);
165
    }
166
167
    public function listSuggestionsAction() {
168
        $this->session->setListAction($this->getCurrentAction(), $this->getCurrentController());
169
170
        $documents = NULL;
171
        $isWorkspace = $this->security->getUser()->getUserRole() === Security::ROLE_LIBRARIAN;
172
173
        if (
174
            $this->security->getUser()->getUserRole() == Security::ROLE_LIBRARIAN
175
        ) {
176
                $documents = $this->documentRepository->findAllDocumentSuggestions(
177
                    $this->security->getUser()->getUserRole(),
178
                    $this->security->getUser()->getUid()
179
                );
180
        }
181
182
        if ($this->request->hasArgument('message')) {
183
            $this->view->assign('message', $this->request->getArgument('message'));
184
        }
185
186
        if ($this->request->hasArgument('errorFiles')) {
187
            $this->view->assign('errorFiles', $this->request->getArgument('errorFiles'));
188
        }
189
190
        $this->view->assign('currentUser', $this->security->getUser());
191
        $this->view->assign('isWorkspace', $isWorkspace);
192
        $this->view->assign('documents', $documents);
193
    }
194
195
    /**
196
     * @param Document $document
197
     * @param bool $acceptAll
198
     */
199
    public function acceptSuggestionAction(\EWW\Dpf\Domain\Model\Document $document, bool $acceptAll = true) {
200
201
        $args = $this->request->getArguments();
0 ignored issues
show
Unused Code introduced by
The assignment to $args is dead and can be removed.
Loading history...
202
203
        /** @var DocumentMapper $documentMapper */
204
        $documentMapper = $this->objectManager->get(DocumentMapper::class);
205
206
        // Existing working copy?
207
        /** @var \EWW\Dpf\Domain\Model\Document $originDocument */
208
        $linkedUid = $document->getLinkedUid();
209
        $originDocument = $this->documentRepository->findWorkingCopy($linkedUid);
210
211
        if ($originDocument) {
0 ignored issues
show
introduced by
$originDocument is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
212
            $linkedDocumentForm = $documentMapper->getDocumentForm($originDocument);
0 ignored issues
show
Unused Code introduced by
The assignment to $linkedDocumentForm is dead and can be removed.
Loading history...
213
        } else {
214
            // get remote document
215
            $originDocument = $this->documentTransferManager->retrieve($document->getLinkedUid(), $this->security->getUser()->getUid());
216
            $linkedDocumentForm = $documentMapper->getDocumentForm($originDocument);
217
        }
218
219
        if ($acceptAll) {
220
            // all changes are confirmed
221
            // copy suggest to origin document
222
            $originDocument->copy($document, true);
0 ignored issues
show
Unused Code introduced by
The call to EWW\Dpf\Domain\Model\Document::copy() has too many arguments starting with true. ( Ignorable by Annotation )

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

222
            $originDocument->/** @scrutinizer ignore-call */ 
223
                             copy($document, true);

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...
223
224
            if ($originDocument->getTransferStatus() == 'RESTORE') {
225
                if ($originDocument->getObjectIdentifier()) {
226
                    $originDocument->setState(DocumentWorkflow::STATE_IN_PROGRESS_ACTIVE);
227
                } else {
228
                    $originDocument->setState(DocumentWorkflow::STATE_IN_PROGRESS_NONE);
229
                }
230
            }
231
232
            // copy files from suggest document
233
            foreach ($document->getFile() as $key => $file) {
234
                $newFile = $this->objectManager->get(File::class);
235
                $newFile->copy($file);
236
                $newFile->setDocument($originDocument);
237
                $this->fileRepository->add($newFile);
238
                $originDocument->addFile($newFile);
239
240
            }
241
242
            $this->documentRepository->update($originDocument);
243
            $this->documentRepository->remove($document);
244
245
            // redirect to document
246
            $this->redirect('showDetails', 'Document', null, ['document' => $originDocument]);
247
        }
248
249
        $this->redirectToDocumentList();
250
    }
251
252
253
    public function showSuggestionDetailsAction(\EWW\Dpf\Domain\Model\Document $document) {
254
        $this->authorizationChecker->denyAccessUnlessGranted(DocumentVoter::SHOW_DETAILS, $document);
255
256
        /** @var DocumentMapper $documentMapper */
257
        $documentMapper = $this->objectManager->get(DocumentMapper::class);
258
259
        $linkedUid = $document->getLinkedUid();
260
        $linkedDocument = $this->documentRepository->findWorkingCopy($linkedUid);
261
262
        if ($linkedDocument) {
263
            // Existing working copy
264
            $linkedDocumentForm = $documentMapper->getDocumentForm($linkedDocument);
265
        } else {
266
            // No existing working copy, get remote document from fedora
267
            $linkedDocument = $this->documentTransferManager->retrieve($document->getLinkedUid(), $this->security->getUser()->getUid());
268
            $linkedDocumentForm = $documentMapper->getDocumentForm($linkedDocument);
269
        }
270
271
        $newDocumentForm = $documentMapper->getDocumentForm($document);
272
        $diff = $this->documentFormDiff($linkedDocumentForm, $newDocumentForm);
273
274
        //$usernameString = $this->security->getUser()->getUsername();
275
        $user = $this->frontendUserRepository->findOneByUid($document->getCreator());
276
277
        if ($user) {
278
            $usernameString = $user->getUsername();
279
        }
280
281
        $this->view->assign('documentCreator', $usernameString);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $usernameString does not seem to be defined for all execution paths leading up to this point.
Loading history...
282
        $this->view->assign('diff', $diff);
283
        $this->view->assign('document', $document);
284
285
    }
286
287
    public function documentFormDiff($docForm1, $docForm2) {
288
        $returnArray = ['changed' => ['new' => [], 'old' => []], 'deleted' => [], 'added' => []];
289
290
        // pages
291
        foreach ($docForm1->getItems() as $keyPage => $valuePage) {
292
            foreach ($valuePage as $keyRepeatPage => $valueRepeatPage) {
293
294
                // groups
295
                foreach ($valueRepeatPage->getItems() as $keyGroup => $valueGroup) {
296
297
                    $checkFieldsForAdding = false;
298
                    $valueGroupCounter = count($valueGroup);
299
300
                    if ($valueGroupCounter < count($docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup])) {
301
                        $checkFieldsForAdding = true;
302
                    }
303
304
                    foreach ($valueGroup as $keyRepeatGroup => $valueRepeatGroup) {
305
306
                        // fields
307
                        foreach ($valueRepeatGroup->getItems() as $keyField => $valueField) {
308
                            foreach ($valueField as $keyRepeatField => $valueRepeatField) {
309
310
                                $fieldCounter = count($docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup]);
311
                                $valueFieldCounter = count($valueField);
312
313
                                // check if group or field is not existing
314
                                $notExisting = false;
315
                                try {
316
                                    $flag = 'page';
317
                                    $value2 = $docForm2->getItems()[$keyPage];
318
                                    $flag = 'group';
319
                                    $value2 = $value2[$keyRepeatPage];
320
                                    $value2 = $value2->getItems()[$keyGroup];
321
                                    $value2 = $value2[$keyRepeatGroup]->getItems()[$keyField];
322
                                    $flag = 'field';
323
                                } catch (\Throwable $t) {
324
                                    $notExisting = true;
325
                                }
326
327
                                $item = NULL;
0 ignored issues
show
Unused Code introduced by
The assignment to $item is dead and can be removed.
Loading history...
328
                                if ($flag == 'group') {
329
                                    $itemExisting = $valueRepeatGroup;
330
                                    $itemNew = $docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup];
331
                                } else if ($flag == 'field') {
332
                                    $itemExisting = $valueRepeatField;
333
                                    $itemNew = $docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup][$keyRepeatGroup]->getItems()[$keyField][$keyRepeatField];
334
                                }
335
336
                                if ($notExisting || ($valueRepeatField->getValue() != $value2[$keyRepeatField]->getValue() && empty($value2[$keyRepeatField]->getValue()))) {
337
                                    // deleted
338
                                    $returnArray['deleted'][] = $itemExisting;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemExisting does not seem to be defined for all execution paths leading up to this point.
Loading history...
339
340
                                } else if ($this->removeControlCharacterFromString($valueRepeatField->getValue()) != $this->removeControlCharacterFromString($value2[$keyRepeatField]->getValue())
341
                                    && !empty($value2[$keyRepeatField]->getValue())) {
342
343
                                    // changed
344
                                    $returnArray['changed']['old'][] = $itemExisting;
345
                                    $returnArray['changed']['new'][] = $itemNew;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemNew does not seem to be defined for all execution paths leading up to this point.
Loading history...
346
                                }
347
348
                                if ($flag == 'group') {
349
                                    break 2;
350
                                }
351
                            }
352
353
                            // check if new document form has more field items as the existing form
354
                            if ($valueFieldCounter < $fieldCounter && !$checkFieldsForAdding) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $valueFieldCounter does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $fieldCounter does not seem to be defined for all execution paths leading up to this point.
Loading history...
355
                                // field added
356
                                for ($i = count($valueField); $i < $fieldCounter;$i++) {
357
                                    $returnArray['added'][] = $docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup][$keyRepeatGroup]->getItems()[$keyField][$i];
358
359
                                }
360
                            }
361
                        }
362
                    }
363
364
                    // check if new document form has more group items as the existing form
365
                    if ($valueGroupCounter < count($docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup])) {
366
                        // group added
367
                        $counter = count($docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup]);
368
                        for ($i = $valueGroupCounter; $i < $counter;$i++) {
369
                            $returnArray['added'][] = $docForm2->getItems()[$keyPage][$keyRepeatPage]->getItems()[$keyGroup][$i];
370
                        }
371
                    }
372
                }
373
            }
374
375
        }
376
377
        return $returnArray;
378
379
    }
380
381
    public function removeControlCharacterFromString($string) {
382
        return preg_replace('/\p{C}+/u', "", $string);
383
    }
384
385
    /**
386
     * action discard
387
     *
388
     * @param \EWW\Dpf\Domain\Model\Document $document
389
     * @param integer $tstamp
390
     * @param string $reason
391
     * @return void
392
     */
393
    public function discardAction(Document $document, $tstamp, $reason = NULL)
0 ignored issues
show
Unused Code introduced by
The parameter $tstamp is not used and could be removed. ( Ignorable by Annotation )

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

393
    public function discardAction(Document $document, /** @scrutinizer ignore-unused */ $tstamp, $reason = NULL)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
394
    {
395
        if (!$this->authorizationChecker->isGranted(DocumentVoter::DISCARD, $document)) {
396
            if (
397
                $this->editingLockService->isLocked(
398
                    $document->getDocumentIdentifier(),
399
                    $this->security->getUser()->getUid()
400
                )
401
            ) {
402
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_discard.failureBlocked';
403
            } else {
404
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_discard.accessDenied';
405
            }
406
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
407
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
408
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
409
        }
410
411
        $this->updateDocument($document, DocumentWorkflow::TRANSITION_DISCARD, $reason);
412
    }
413
414
    /**
415
     * action postpone
416
     *
417
     * @param \EWW\Dpf\Domain\Model\Document $document
418
     * @param integer $tstamp
419
     * @param string $reason
420
     * @return void
421
     */
422
    public function postponeAction(\EWW\Dpf\Domain\Model\Document $document, $tstamp, $reason = NULL)
0 ignored issues
show
Unused Code introduced by
The parameter $tstamp is not used and could be removed. ( Ignorable by Annotation )

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

422
    public function postponeAction(\EWW\Dpf\Domain\Model\Document $document, /** @scrutinizer ignore-unused */ $tstamp, $reason = NULL)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
423
    {
424
        if (!$this->authorizationChecker->isGranted(DocumentVoter::POSTPONE, $document)) {
425
            if (
426
                $this->editingLockService->isLocked(
427
                    $document->getDocumentIdentifier(),
428
                    $this->security->getUser()->getUid()
429
                )
430
            ) {
431
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_postpone.failureBlocked';
432
            } else {
433
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_postpone.accessDenied';
434
            }
435
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
436
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
437
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
438
        }
439
440
        $this->updateDocument($document, DocumentWorkflow::TRANSITION_POSTPONE, $reason);
441
442
    }
443
444
445
    /**
446
     * action deleteLocallyAction
447
     *
448
     * @param Document $document
449
     * @param integer $tstamp
450
     * @return void
451
     */
452
    public function deleteLocallyAction(\EWW\Dpf\Domain\Model\Document $document, $tstamp)
453
    {
454
        if ($document->getObjectIdentifier()) {
455
            $voterAttribute = DocumentVoter::DELETE_WORKING_COPY;
456
        } else {
457
            $voterAttribute = DocumentVoter::DELETE_LOCALLY;
458
        }
459
460
        if (!$this->authorizationChecker->isGranted($voterAttribute, $document)) {
461
            if (
462
                $this->editingLockService->isLocked(
463
                    $document->getDocumentIdentifier(),
464
                    $this->security->getUser()->getUid()
465
                )
466
            ) {
467
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_deleteLocally.failureBlocked';
468
            } else {
469
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_deleteLocally.accessDenied';
470
            }
471
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
472
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
473
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
474
        }
475
476
        if ($tstamp === $document->getTstamp()) {
477
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_deleteLocally.success';
478
            $this->flashMessage($document, $key, AbstractMessage::OK);
479
            $this->documentRepository->remove($document);
480
481
            if ($document->isWorkingCopy() || $document->isTemporaryCopy()) {
482
483
                if ($document->isWorkingCopy()) {
484
                    if ($this->bookmarkRepository->removeBookmark($document, $this->security->getUser()->getUid())) {
485
                        $this->addFlashMessage(
486
                            LocalizationUtility::translate("manager.workspace.bookmarkRemoved.singular", "dpf"), '',
487
                            AbstractMessage::INFO
488
                        );
489
                    }
490
                }
491
492
                $this->persistenceManager->persistAll();
493
                $document = $this->documentManager->read($document->getDocumentIdentifier());
494
495
                // index the document
496
                $this->signalSlotDispatcher->dispatch(
497
                    \EWW\Dpf\Controller\AbstractController::class,
498
                    'indexDocument', [$document]
499
                );
500
501
                $this->documentRepository->remove($document);
502
            } else {
503
                $this->bookmarkRepository->removeBookmark($document, $this->security->getUser()->getUid());
504
                // delete document from index
505
                $this->signalSlotDispatcher->dispatch(
506
                    \EWW\Dpf\Controller\AbstractController::class,
507
                    'deleteDocumentFromIndex', [$document->getDocumentIdentifier()]
508
                );
509
            }
510
511
            $suggestions = $this->documentRepository->findByLinkedUid($document->getDocumentIdentifier());
0 ignored issues
show
Bug introduced by
The method findByLinkedUid() does not exist on EWW\Dpf\Domain\Repository\DocumentRepository. 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

511
            /** @scrutinizer ignore-call */ 
512
            $suggestions = $this->documentRepository->findByLinkedUid($document->getDocumentIdentifier());
Loading history...
512
            foreach ($suggestions as $suggestion) {
513
                $this->documentRepository->remove($suggestion);
514
            }
515
516
            $this->redirectToDocumentList();
517
        } else {
518
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_deleteLocally.failureNewVersion';
519
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
520
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
521
        }
522
    }
523
524
    /**
525
     * action duplicate
526
     *
527
     * @param \EWW\Dpf\Domain\Model\Document $document
528
     * @return void
529
     */
530
    public function duplicateAction(\EWW\Dpf\Domain\Model\Document $document)
531
    {
532
        if (!$this->authorizationChecker->isGranted(DocumentVoter::DUPLICATE, $document)) {
533
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_duplicate.accessDenied';
534
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
535
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
536
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
537
        }
538
539
        try {
540
            /* @var $newDocument \EWW\Dpf\Domain\Model\Document */
541
            $newDocument = $this->objectManager->get(Document::class);
542
543
            $newDocument->setState(DocumentWorkflow::STATE_NEW_NONE);
544
545
            $newDocument->setTitle($document->getTitle());
546
            $newDocument->setAuthors($document->getAuthors());
547
548
            $newDocument->setCreator($this->security->getUser()->getUid());
549
550
            $mods = new \EWW\Dpf\Helper\Mods($document->getXmlData());
551
            $mods->clearAllUrn();
552
            $newDocument->setXmlData($mods->getModsXml());
553
554
            $newDocument->setDocumentType($document->getDocumentType());
555
556
            $processNumberGenerator = $this->objectManager->get(ProcessNumberGenerator::class);
557
            $processNumber = $processNumberGenerator->getProcessNumber();
558
            $newDocument->setProcessNumber($processNumber);
559
560
            $slub = new \EWW\Dpf\Helper\Slub($document->getSlubInfoData());
561
            $slub->setProcessNumber($processNumber);
562
            $newDocument->setSlubInfoData($slub->getSlubXml());
563
564
            $this->documentRepository->add($newDocument);
565
            $this->persistenceManager->persistAll();
566
567
            // index the document
568
            $this->signalSlotDispatcher->dispatch(
569
                \EWW\Dpf\Controller\AbstractController::class,
570
                'indexDocument', [$newDocument]
571
            );
572
573
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_duplicate.success';
574
            $this->flashMessage($document, $key, AbstractMessage::OK);
575
            $this->redirect('listWorkspace', 'Workspace');
576
        } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
577
            // A redirect always throws this exception, but in this case, however,
578
            // redirection is desired and should not lead to an exception handling
579
        } catch (\Exception $exception) {
580
            if ($exception instanceof DPFExceptionInterface) {
581
                $key = $exception->messageLanguageKey();
582
            } else {
583
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_duplicate.failure';
584
            }
585
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
586
            $this->redirect('list');
587
        }
588
    }
589
590
591
    /**
592
     * releasePublishAction
593
     *
594
     * @param \EWW\Dpf\Domain\Model\Document $document
595
     * @param integer $tstamp
596
     * @return void
597
     */
598
    public function releasePublishAction(\EWW\Dpf\Domain\Model\Document $document, $tstamp)
0 ignored issues
show
Unused Code introduced by
The parameter $tstamp is not used and could be removed. ( Ignorable by Annotation )

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

598
    public function releasePublishAction(\EWW\Dpf\Domain\Model\Document $document, /** @scrutinizer ignore-unused */ $tstamp)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
599
    {
600
        if (!$this->authorizationChecker->isGranted(DocumentVoter::RELEASE_PUBLISH, $document)) {
601
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_ingest.accessDenied';
602
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
603
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
604
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
605
        }
606
607
        $this->updateDocument($document, DocumentWorkflow::TRANSITION_RELEASE_PUBLISH, null);
608
609
    }
610
611
612
    /**
613
     * releaseActivateAction
614
     *
615
     * @param \EWW\Dpf\Domain\Model\Document $document
616
     * @param integer $tstamp
617
     * @return void
618
     */
619
    public function releaseActivateAction(\EWW\Dpf\Domain\Model\Document $document, $tstamp)
0 ignored issues
show
Unused Code introduced by
The parameter $tstamp is not used and could be removed. ( Ignorable by Annotation )

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

619
    public function releaseActivateAction(\EWW\Dpf\Domain\Model\Document $document, /** @scrutinizer ignore-unused */ $tstamp)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
620
    {
621
        if (!$this->authorizationChecker->isGranted(DocumentVoter::RELEASE_ACTIVATE, $document)) {
622
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_activate.accessDenied';
623
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
624
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
625
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
626
        }
627
628
        $this->updateDocument($document, DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE, null);
629
630
    }
631
632
    /**
633
     * action register
634
     *
635
     * @param \EWW\Dpf\Domain\Model\Document $document
636
     * @return void
637
     */
638
    public function registerAction(\EWW\Dpf\Domain\Model\Document $document)
639
    {
640
        if (!$this->authorizationChecker->isGranted(DocumentVoter::REGISTER, $document)) {
641
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_register.accessDenied';
642
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
643
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
644
        }
645
646
        if (!$this->documentValidator->validate($document, false)) {
647
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_register.missingValues';
648
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
649
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
650
        }
651
652
        $this->workflow->apply($document, \EWW\Dpf\Domain\Workflow\DocumentWorkflow::TRANSITION_REGISTER);
0 ignored issues
show
Bug introduced by
The method apply() does not exist on EWW\Dpf\Domain\Workflow\DocumentWorkflow. ( Ignorable by Annotation )

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

652
        $this->workflow->/** @scrutinizer ignore-call */ 
653
                         apply($document, \EWW\Dpf\Domain\Workflow\DocumentWorkflow::TRANSITION_REGISTER);

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

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

Loading history...
653
        $this->documentRepository->update($document);
654
655
656
        if ($this->security->getUser()->getUserRole() === Security::ROLE_LIBRARIAN) {
657
            $this->bookmarkRepository->addBookmark($this->security->getUser()->getUid(), $document);
658
        }
659
660
        $notifier = $this->objectManager->get(Notifier::class);
661
        $notifier->sendRegisterNotification($document);
662
663
        // index the document
664
        $this->signalSlotDispatcher->dispatch(\EWW\Dpf\Controller\AbstractController::class, 'indexDocument', [$document]);
665
666
        $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_register.success';
667
        $this->flashMessage($document, $key, AbstractMessage::OK);
668
        $this->redirect('showDetails', 'Document', null, ['document' => $document]);
669
    }
670
671
    /**
672
     * action showDetails
673
     *
674
     * @param \EWW\Dpf\Domain\Model\Document $document
675
     * @return void
676
     */
677
    public function showDetailsAction(Document $document)
678
    {
679
        if (!$this->authorizationChecker->isGranted(DocumentVoter::SHOW_DETAILS, $document)) {
680
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_showDetails.accessDenied';
681
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
682
            $this->redirectToDocumentList();
683
        }
684
685
        $this->editingLockService->lock(
686
            ($document->getObjectIdentifier()? $document->getObjectIdentifier() : $document->getUid()),
687
            $this->security->getUser()->getUid()
688
        );
689
690
        $postponeOptions = $this->inputOptionListRepository->findOneByName($this->settings['postponeOptionListName']);
0 ignored issues
show
Bug introduced by
The method findOneByName() does not exist on EWW\Dpf\Domain\Repositor...putOptionListRepository. 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

690
        /** @scrutinizer ignore-call */ 
691
        $postponeOptions = $this->inputOptionListRepository->findOneByName($this->settings['postponeOptionListName']);
Loading history...
691
        if ($postponeOptions) {
692
            $this->view->assign('postponeOptions', $postponeOptions->getInputOptions());
0 ignored issues
show
Bug introduced by
The method getInputOptions() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

692
            $this->view->assign('postponeOptions', $postponeOptions->/** @scrutinizer ignore-call */ getInputOptions());

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

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

Loading history...
693
        }
694
695
        $discardOptions = $this->inputOptionListRepository->findOneByName($this->settings['discardOptionListName']);
696
        if ($discardOptions) {
697
            $this->view->assign('discardOptions', $discardOptions->getInputOptions());
698
        }
699
700
        $this->view->assign('document', $document);
701
    }
702
703
704
    public function cancelListTaskAction()
705
    {
706
        $this->redirectToDocumentList();
707
    }
708
    
709
    /**
710
     * action suggest restore
711
     *
712
     * @param Document $document
713
     * @return void
714
     */
715
    public function suggestRestoreAction(\EWW\Dpf\Domain\Model\Document $document) {
716
717
        if (!$this->authorizationChecker->isGranted(DocumentVoter::SUGGEST_RESTORE, $document)) {
718
            $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:document_suggestRestore.accessDenied';
719
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
720
            $this->redirect('showDetails', 'Document', null, ['document' => $document]);
721
            return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The expression return FALSE returns the type false which is incompatible with the documented return type void.
Loading history...
722
        }
723
724
        $this->view->assign('document', $document);
725
    }
726
727
    /**
728
     * @param Document $document
729
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
730
     */
731
    public function suggestModificationAction(\EWW\Dpf\Domain\Model\Document $document) {
732
733
        $this->authorizationChecker->denyAccessUnlessGranted(DocumentVoter::SUGGEST_MODIFICATION, $document);
734
735
        $documentMapper = $this->objectManager->get(DocumentMapper::class);
736
737
        /* @var $newDocument \EWW\Dpf\Domain\Model\Document */
738
        $documentForm = $documentMapper->getDocumentForm($document);
739
740
        $this->view->assign('suggestMod', true);
741
        $this->forward('edit','DocumentFormBackoffice',NULL, ['documentForm' => $documentForm, 'suggestMod' => true]);
742
    }
743
744
745
    /**
746
     * initializeAction
747
     */
748
    public function initializeAction()
749
    {
750
        $this->authorizationChecker->denyAccessUnlessLoggedIn();
751
752
        parent::initializeAction();
753
754
        $this->workflow = $this->objectManager->get(DocumentWorkflow::class)->getWorkflow();
755
756
        if ($this->request->hasArgument('document')) {
757
            $document = $this->request->getArgument('document');
758
            $document = $this->documentManager->read($document, $this->security->getUser()->getUID());
759
760
            if (!$document) {
761
                $this->redirectToDocumentList();
762
            }
763
764
            $this->request->setArgument('document', $document);
765
        }
766
    }
767
768
    /**
769
     * Redirect to the current document list.
770
     *
771
     * @param null $message
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $message is correct as it would always require null to be passed?
Loading history...
772
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
773
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
774
     */
775
    protected function redirectToDocumentList($message = null)
0 ignored issues
show
Unused Code introduced by
The parameter $message is not used and could be removed. ( Ignorable by Annotation )

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

775
    protected function redirectToDocumentList(/** @scrutinizer ignore-unused */ $message = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
776
    {
777
        list($action, $controller, $redirectUri) = $this->session->getListAction();
778
779
        if ($redirectUri) {
780
            $this->redirectToUri($redirectUri);
781
        } else {
782
            $this->redirect($action, $controller);
783
        }
784
    }
785
786
    /**
787
     * Gets the storage PID of the current client
788
     *
789
     * @return mixed
790
     */
791
    protected function getStoragePID()
792
    {
793
        return $this->settings['persistence']['classes']['EWW\Dpf\Domain\Model\Document']['newRecordStoragePid'];
794
    }
795
796
    /**
797
     *
798
     * @param \EWW\Dpf\Domain\Model\Document $document
799
     * @param string $key
800
     * @param string $severity
801
     * @param string $defaultMessage
802
     */
803
    protected function flashMessage(\EWW\Dpf\Domain\Model\Document $document, $key, $severity, $defaultMessage = "")
804
    {
805
        // Show success or failure of the action in a flash message
806
        if ($document) {
0 ignored issues
show
introduced by
$document is of type EWW\Dpf\Domain\Model\Document, thus it always evaluated to true.
Loading history...
807
            $args[] = $document->getTitle();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$args was never initialized. Although not strictly required by PHP, it is generally a good practice to add $args = array(); before regardless.
Loading history...
808
            $args[] = $document->getObjectIdentifier();
809
        }
810
811
        $message = LocalizationUtility::translate($key, 'dpf', $args);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $args does not seem to be defined for all execution paths leading up to this point.
Loading history...
812
        $message = empty($message) ? $defaultMessage : $message;
813
814
        $this->addFlashMessage(
815
            $message,
816
            '',
817
            $severity,
0 ignored issues
show
Bug introduced by
$severity of type string is incompatible with the type integer expected by parameter $severity of TYPO3\CMS\Extbase\Mvc\Co...ller::addFlashMessage(). ( Ignorable by Annotation )

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

817
            /** @scrutinizer ignore-type */ $severity,
Loading history...
818
            true
819
        );
820
    }
821
822
    /**
823
     * Updates the document in combination with a state transition.
824
     *
825
     * @param Document $document
826
     * @param $workflowTransition
827
     * @param string $reason
828
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
829
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
830
     */
831
    protected function updateDocument(\EWW\Dpf\Domain\Model\Document $document, $workflowTransition, $reason)
832
    {
833
        switch ($workflowTransition) {
834
            case DocumentWorkflow::TRANSITION_DISCARD:
835
                $messageKeyPart = 'document_discard';
836
                break;
837
            case DocumentWorkflow::TRANSITION_POSTPONE:
838
                $messageKeyPart = 'document_postpone';
839
                break;
840
            case DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE:
841
                $messageKeyPart = 'document_activate';
842
                break;
843
            case DocumentWorkflow::TRANSITION_RELEASE_PUBLISH:
844
                $messageKeyPart = 'document_ingest';
845
                break;
846
            default:
847
                $messageKeyPart = "document_update";
848
                break;
849
        }
850
851
        try {
852
            if ($reason) {
853
                $timezone = new \DateTimeZone($this->settings['timezone']);
854
                $timeStamp = (new \DateTime('now', $timezone))->format("d.m.Y H:i:s");
855
856
                if ($workflowTransition == DocumentWorkflow::TRANSITION_DISCARD) {
857
                    $note = LocalizationUtility::translate(
858
                        "manager.document.discard.note", "dpf", [$timeStamp, $reason]
859
                    );
860
                } elseif ($workflowTransition == DocumentWorkflow::TRANSITION_POSTPONE) {
861
                    $note = LocalizationUtility::translate(
862
                        "manager.document.postpone.note", "dpf", [$timeStamp, $reason]
863
                    );
864
                }
865
866
                $slub = new \EWW\Dpf\Helper\Slub($document->getSlubInfoData());
867
                $slub->addNote($note);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $note does not seem to be defined for all execution paths leading up to this point.
Loading history...
868
                $document->setSlubInfoData($slub->getSlubXml());
869
            }
870
871
            if ($this->documentManager->update($document, $workflowTransition)) {
872
873
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:'.$messageKeyPart.'.success';
874
                $this->flashMessage($document, $key, AbstractMessage::OK);
875
876
                if ($this->security->getUser()->getUserRole() === Security::ROLE_LIBRARIAN) {
877
                    switch ($document->getState()) {
878
                        case DocumentWorkflow::STATE_POSTPONED_NONE:
879
                        case DocumentWorkflow::STATE_DISCARDED_NONE:
880
                        case DocumentWorkflow::STATE_NONE_INACTIVE:
881
                        case DocumentWorkflow::STATE_NONE_ACTIVE:
882
                        case DocumentWorkflow::STATE_NONE_DELETED:
883
884
                            if (
885
                                $this->bookmarkRepository->removeBookmark(
886
                                    $document,
887
                                    $this->security->getUser()->getUid()
888
                                )
889
                            ) {
890
                                $this->addFlashMessage(
891
                                    LocalizationUtility::translate("manager.workspace.bookmarkRemoved.singular", "dpf"), '',
892
                                    AbstractMessage::INFO
893
                                );
894
                            }
895
896
                            break;
897
                    }
898
                }
899
900
                $this->redirectToDocumentList();
901
            } else {
902
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:'.$messageKeyPart.'.failure';
903
                $this->flashMessage($document, $key, AbstractMessage::ERROR);
904
                $this->redirect('showDetails', 'Document', NULL, ['document' => $document]);
905
            }
906
        } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
907
            // A redirect always throws this exception, but in this case, however,
908
            // redirection is desired and should not lead to an exception handling
909
        } catch (\Exception $exception) {
910
            if ($exception instanceof DPFExceptionInterface) {
911
                $key = $exception->messageLanguageKey();
912
            } else {
913
                $key = 'LLL:EXT:dpf/Resources/Private/Language/locallang.xlf:'.$messageKeyPart.'.failure';
914
            }
915
            $this->flashMessage($document, $key, AbstractMessage::ERROR);
916
            $this->redirectToDocumentList();
917
        }
918
919
    }
920
}
921