Passed
Pull Request — master (#175)
by
unknown
08:11
created

DocumentManager::hasActiveEmbargo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 10
1
<?php
2
namespace EWW\Dpf\Services\Document;
3
4
use EWW\Dpf\Domain\Model\Bookmark;
5
use EWW\Dpf\Domain\Model\Document;
6
use EWW\Dpf\Domain\Model\File;
7
use EWW\Dpf\Services\Transfer\FedoraRepository;
8
use EWW\Dpf\Services\Transfer\DocumentTransferManager;
9
use EWW\Dpf\Domain\Workflow\DocumentWorkflow;
10
use EWW\Dpf\Controller\AbstractController;
11
12
class DocumentManager
13
{
14
    /**
15
     * objectManager
16
     *
17
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
18
     * @inject
19
     */
20
    protected $objectManager = null;
21
22
    /**
23
     * documentRepository
24
     *
25
     * @var \EWW\Dpf\Domain\Repository\DocumentRepository
26
     * @inject
27
     */
28
    protected $documentRepository = null;
29
30
    /**
31
     * fileRepository
32
     *
33
     * @var \EWW\Dpf\Domain\Repository\FileRepository
34
     * @inject
35
     */
36
    protected $fileRepository = null;
37
38
    /**
39
     * bookmarkRepository
40
     *
41
     * @var \EWW\Dpf\Domain\Repository\BookmarkRepository
42
     * @inject
43
     */
44
    protected $bookmarkRepository = null;
45
46
    /**
47
     * persistence manager
48
     *
49
     * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
50
     * @inject
51
     */
52
    protected $persistenceManager;
53
54
    /**
55
     * signalSlotDispatcher
56
     *
57
     * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
58
     * @inject
59
     */
60
    protected $signalSlotDispatcher = null;
61
62
    /**
63
     * security
64
     *
65
     * @var \EWW\Dpf\Security\Security
66
     * @inject
67
     */
68
    protected $security = null;
69
70
    /**
71
     * Returns a document specified by repository object identifier or dataset uid.
72
     *
73
     * @param string $identifier
74
     * @param int $user_uid
75
     * @return Document|null
76
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
77
     */
78
    public function read($identifier)
79
    {
80
        if (!$identifier) {
81
            return null;
82
        }
83
84
        $document = $this->documentRepository->findByIdentifier($identifier);
85
86
        if ($document instanceof Document) {
0 ignored issues
show
introduced by
$document is always a sub-type of EWW\Dpf\Domain\Model\Document.
Loading history...
87
            return $document;
88
        }
89
90
        /** @var \EWW\Dpf\Domain\Model\Document $document */
91
        $document = NULL;
0 ignored issues
show
Unused Code introduced by
The assignment to $document is dead and can be removed.
Loading history...
92
93
        try {
94
            $document = $this->getDocumentTransferManager()->retrieve($identifier);
95
96
            // index the document
97
            $this->signalSlotDispatcher->dispatch(
98
                AbstractController::class, 'indexDocument', [$document]
99
            );
100
101
        } catch (\EWW\Dpf\Exceptions\RetrieveDocumentErrorException $exception) {
102
            return null;
103
        }
104
105
        if ($document instanceof Document) {
106
            return $document;
107
        }
108
109
        return null;
110
    }
111
112
    /**
113
     * Updates a document locally or remotely.
114
     *
115
     * @param Document $document
116
     * @param string $workflowTransition
117
     * @param array $deletedFiles
118
     * @param array $newFiles
119
     * @return string|false
120
     * @throws \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException
121
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
122
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
123
     */
124
    public function update(Document $document, $workflowTransition = null, $deletedFiles = [], $newFiles = [])
125
    {
126
        // xml data fields are limited to 64 KB
127
        if (strlen($document->getXmlData()) >= 64 * 1024 || strlen($document->getSlubInfoData() >= 64 * 1024)) {
128
            throw new \EWW\Dpf\Exceptions\DocumentMaxSizeErrorException("Maximum document size exceeded.");
129
        }
130
131
        /** @var \Symfony\Component\Workflow\Workflow $workflow */
132
        $workflow = $this->objectManager->get(DocumentWorkflow::class)->getWorkflow();
133
134
        if ($workflowTransition) {
135
            if (!$workflow->can($document, $workflowTransition)) {
136
                return false;
137
            }
138
            $workflow->apply($document, $workflowTransition);
139
        }
140
141
        if ($document->isSuggestion()) {
142
143
            // if local suggestion copy
144
            $updateResult = false;
145
146
        } elseif ($document->isTemporaryCopy()) {
147
148
            // if temporary working copy
149
            $updateResult = $this->updateRemotely($document, $workflowTransition, $deletedFiles, $newFiles);
150
151
        } elseif (
152
            $document->isWorkingCopy() &&
153
            (
154
                $workflowTransition === DocumentWorkflow::TRANSITION_POSTPONE ||
155
                $workflowTransition === DocumentWorkflow::TRANSITION_DISCARD ||
156
                $workflowTransition === DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE
157
            )
158
        ) {
159
160
            // if local working copy with state change
161
            $updateResult = $this->updateRemotely($document, $workflowTransition, $deletedFiles, $newFiles);
162
163
        } elseif ($document->isWorkingCopy()) {
164
165
            // if local working copy with no state change
166
            $this->updateFiles($document, $deletedFiles, $newFiles);
167
            $this->documentRepository->update($document);
168
            $updateResult = $document->getDocumentIdentifier();
169
170
        } elseif ($workflowTransition == DocumentWorkflow::TRANSITION_RELEASE_PUBLISH) {
171
            // Fedora ingest
172
            if ($ingestedDocument = $this->getDocumentTransferManager()->ingest($document)) {
173
174
                // After ingest all related bookmarks need an update of the identifier into an fedora object identifier.
175
                if ($ingestedDocument instanceof Document) {
0 ignored issues
show
introduced by
$ingestedDocument is always a sub-type of EWW\Dpf\Domain\Model\Document.
Loading history...
176
                    /** @var Bookmark $bookmark */
177
                    foreach ($this->bookmarkRepository->findByDocumentIdentifier($ingestedDocument->getUid()) as $bookmark) {
0 ignored issues
show
Bug introduced by
The method findByDocumentIdentifier() 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

177
                    foreach ($this->bookmarkRepository->/** @scrutinizer ignore-call */ findByDocumentIdentifier($ingestedDocument->getUid()) as $bookmark) {
Loading history...
178
                        $bookmark->setDocumentIdentifier($ingestedDocument->getDocumentIdentifier());
179
                        $this->bookmarkRepository->update($bookmark);
180
                    }
181
                } else {
182
                    throw \Exception("Logical exception while updating bookmarks.");
0 ignored issues
show
Bug introduced by
The function Exception was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

182
                    throw /** @scrutinizer ignore-call */ \Exception("Logical exception while updating bookmarks.");
Loading history...
183
                }
184
185
                // check embargo
186
                if(!$this->hasActiveEmbargo($document)){
187
                    $this->removeDocument($document);
188
                } else {
189
                    $document->setState(DocumentWorkflow::constructState(DocumentWorkflow::LOCAL_STATE_IN_PROGRESS, $document->getRemoteState()));
190
                }
191
                $updateResult = $document->getDocumentIdentifier();
192
            } else {
193
                $updateResult = false;
194
            }
195
        } else {
196
197
            $this->updateFiles($document, $deletedFiles, $newFiles);
198
            $this->documentRepository->update($document);
199
            $updateResult = $document->getDocumentIdentifier();
200
        }
201
202
     //   $this->persistenceManager->persistAll();
203
204
        if ($updateResult) {
205
206
            if (DocumentWorkflow::TRANSITION_RELEASE_PUBLISH) {
207
                // delete local document from index
208
                $this->signalSlotDispatcher->dispatch(
209
                    AbstractController::class, 'deleteDocumentFromIndex', [$document->getUid()]
210
                );
211
            }
212
            // index the document
213
            $this->signalSlotDispatcher->dispatch(
214
                AbstractController::class, 'indexDocument', [$document]
215
            );
216
        }
217
218
        return $updateResult;
219
    }
220
221
    /**
222
     * @return DocumentTransferManager
223
     */
224
    protected function getDocumentTransferManager()
225
    {
226
        /** @var DocumentTransferManager $documentTransferManager */
227
        $documentTransferManager = $this->objectManager->get(DocumentTransferManager::class);
228
229
        /** @var  FedoraRepository $remoteRepository */
230
        $remoteRepository = $this->objectManager->get(FedoraRepository::class);
231
232
        $documentTransferManager->setRemoteRepository($remoteRepository);
233
234
        return $documentTransferManager;
235
    }
236
237
238
    /**
239
     * Adds and delete file model objects attached to the document.
240
     *
241
     * @param Document $document
242
     * @param array $deletedFiles
243
     * @param array $newFiles
244
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
245
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
246
     */
247
    protected function updateFiles(Document $document, $deletedFiles, $newFiles)
248
    {
249
        // Delete files
250
        /** @var File $deleteFile */
251
        foreach ($deletedFiles as $deleteFile) {
252
            $deleteFile->setStatus(File::STATUS_DELETED);
253
            $this->fileRepository->update($deleteFile);
254
        }
255
256
        // Add or update files
257
        /** @var File $newFile */
258
        foreach ($newFiles as $newFile) {
259
260
            if ($newFile->getUID()) {
261
                $this->fileRepository->update($newFile);
262
            } else {
263
                $document->addFile($newFile);
264
            }
265
266
        }
267
    }
268
269
    /**
270
     * Removes the document from the local database.
271
     *
272
     * @param $document
273
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
274
     */
275
    protected function removeDocument($document)
276
    {
277
        $files = $this->fileRepository->findByDocument($document->getUid());
0 ignored issues
show
Bug introduced by
The method findByDocument() does not exist on EWW\Dpf\Domain\Repository\FileRepository. 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

277
        /** @scrutinizer ignore-call */ 
278
        $files = $this->fileRepository->findByDocument($document->getUid());
Loading history...
278
        foreach ($files as $file) {
279
            $this->fileRepository->remove($file);
280
        }
281
        $this->documentRepository->remove($document);
282
    }
283
284
285
286
    /**
287
     * @param Document $document
288
     * @param string $workflowTransition
289
     * @param array $deletedFiles
290
     * @param array $newFiles
291
     * @return string
292
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
293
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
294
     */
295
    protected function updateRemotely($document, $workflowTransition = null, $deletedFiles = [], $newFiles = [])
296
    {
297
        $lastModDate = $this->getDocumentTransferManager()->getLastModDate($document->getObjectIdentifier());
298
        $docLastModDate = $document->getRemoteLastModDate();
299
        if ($lastModDate !== $docLastModDate && !empty($docLastModDate)) {
300
            // There is a newer version in the fedora repository.
301
            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 string.
Loading history...
302
        }
303
304
        $this->updateFiles($document, $deletedFiles, $newFiles);
305
        $this->documentRepository->update($document);
306
307
        switch ($workflowTransition) {
308
            case DocumentWorkflow::TRANSITION_POSTPONE:
309
                $transferState = DocumentTransferManager::INACTIVATE;
310
                break;
311
312
            case DocumentWorkflow::TRANSITION_DISCARD:
313
                $transferState = DocumentTransferManager::DELETE;
314
                break;
315
316
            case DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE:
317
                $transferState = DocumentTransferManager::REVERT;
318
                break;
319
320
            default:
321
                $transferState = null;
322
                break;
323
        }
324
325
        if ($transferState) {
326
            if (!$this->getDocumentTransferManager()->delete($document, $transferState)) {
327
                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 string.
Loading history...
328
            }
329
        }
330
331
        if ($this->getDocumentTransferManager()->update($document)) {
332
333
            if(!$this->hasActiveEmbargo($document)){
334
                $this->removeDocument($document);
335
            } else {
336
                $document->setState(DocumentWorkflow::LOCAL_STATE_IN_PROGRESS . ':' . $document->getRemoteState());
337
            }
338
            return $document->getDocumentIdentifier();
339
        }
340
341
        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 string.
Loading history...
342
    }
343
344
    /**
345
     * @param $document
346
     * @return bool (true: if no embargo is set or embargo is expired, false: embargo is active)
347
     * @throws \Exception
348
     */
349
    protected function hasActiveEmbargo($document)
350
    {
351
        $currentDate = new \DateTime('now');
352
        if($currentDate > $document->getEmbargoDate()){
353
            // embargo is expired
354
            return false;
355
        } else {
356
            return true;
357
        }
358
359
    }
360
361
}
362
363