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

DocumentManager::update()   D

Complexity

Conditions 18
Paths 46

Size

Total Lines 88
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 18
eloc 44
c 1
b 0
f 0
nc 46
nop 4
dl 0
loc 88
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
                $this->removeDocument($document);
186
                $updateResult = $document->getDocumentIdentifier();
187
            } else {
188
                $updateResult = false;
189
            }
190
        } else {
191
192
            $this->updateFiles($document, $deletedFiles, $newFiles);
193
            $this->documentRepository->update($document);
194
            $updateResult = $document->getDocumentIdentifier();
195
        }
196
197
        if ($updateResult) {
198
199
            if (DocumentWorkflow::TRANSITION_RELEASE_PUBLISH) {
200
                // delete local document from index
201
                $this->signalSlotDispatcher->dispatch(
202
                    AbstractController::class, 'deleteDocumentFromIndex', [$document->getUid()]
203
                );
204
            }
205
            // index the document
206
            $this->signalSlotDispatcher->dispatch(
207
                AbstractController::class, 'indexDocument', [$document]
208
            );
209
        }
210
211
        return $updateResult;
212
    }
213
214
    /**
215
     * @return DocumentTransferManager
216
     */
217
    protected function getDocumentTransferManager()
218
    {
219
        /** @var DocumentTransferManager $documentTransferManager */
220
        $documentTransferManager = $this->objectManager->get(DocumentTransferManager::class);
221
222
        /** @var  FedoraRepository $remoteRepository */
223
        $remoteRepository = $this->objectManager->get(FedoraRepository::class);
224
225
        $documentTransferManager->setRemoteRepository($remoteRepository);
226
227
        return $documentTransferManager;
228
    }
229
230
231
    /**
232
     * Adds and delete file model objects attached to the document.
233
     *
234
     * @param Document $document
235
     * @param array $deletedFiles
236
     * @param array $newFiles
237
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
238
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
239
     */
240
    protected function updateFiles(Document $document, $deletedFiles, $newFiles)
241
    {
242
        // Delete files
243
        /** @var File $deleteFile */
244
        foreach ($deletedFiles as $deleteFile) {
245
            $deleteFile->setStatus(File::STATUS_DELETED);
246
            $this->fileRepository->update($deleteFile);
247
        }
248
249
        // Add or update files
250
        /** @var File $newFile */
251
        foreach ($newFiles as $newFile) {
252
253
            if ($newFile->getUID()) {
254
                $this->fileRepository->update($newFile);
255
            } else {
256
                $document->addFile($newFile);
257
            }
258
259
        }
260
    }
261
262
    /**
263
     * Removes the document from the local database.
264
     *
265
     * @param $document
266
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
267
     */
268
    protected function removeDocument($document)
269
    {
270
        $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

270
        /** @scrutinizer ignore-call */ 
271
        $files = $this->fileRepository->findByDocument($document->getUid());
Loading history...
271
        foreach ($files as $file) {
272
            $this->fileRepository->remove($file);
273
        }
274
        $this->documentRepository->remove($document);
275
    }
276
277
278
279
    /**
280
     * @param Document $document
281
     * @param string $workflowTransition
282
     * @param array $deletedFiles
283
     * @param array $newFiles
284
     * @return string
285
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
286
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
287
     */
288
    protected function updateRemotely($document, $workflowTransition = null, $deletedFiles = [], $newFiles = [])
289
    {
290
        $lastModDate = $this->getDocumentTransferManager()->getLastModDate($document->getObjectIdentifier());
291
        if ($lastModDate !== $document->getRemoteLastModDate()) {
292
            // There is a newer version in the fedora repository.
293
            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...
294
        }
295
296
        $this->updateFiles($document, $deletedFiles, $newFiles);
297
        $this->documentRepository->update($document);
298
299
        switch ($workflowTransition) {
300
            case DocumentWorkflow::TRANSITION_POSTPONE:
301
                $transferState = DocumentTransferManager::INACTIVATE;
302
                break;
303
304
            case DocumentWorkflow::TRANSITION_DISCARD:
305
                $transferState = DocumentTransferManager::DELETE;
306
                break;
307
308
            case DocumentWorkflow::TRANSITION_RELEASE_ACTIVATE:
309
                $transferState = DocumentTransferManager::REVERT;
310
                break;
311
312
            default:
313
                $transferState = null;
314
                break;
315
        }
316
317
        if ($transferState) {
318
            if (!$this->getDocumentTransferManager()->delete($document, $transferState)) {
319
                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...
320
            }
321
        }
322
323
        if ($this->getDocumentTransferManager()->update($document)) {
324
            $this->removeDocument($document);
325
            return $document->getDocumentIdentifier();
326
        }
327
328
        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...
329
    }
330
331
}
332
333