Passed
Push — master ( e368ad...e7f16b )
by Greg
06:35
created

EditMediaController::editMediaFileAction()   C

Complexity

Conditions 14
Paths 98

Size

Total Lines 91
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 52
c 0
b 0
f 0
nc 98
nop 1
dl 0
loc 91
rs 6.2666

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
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2020 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Http\Controllers;
21
22
use Exception;
23
use Fig\Http\Message\StatusCodeInterface;
24
use Fisharebest\Webtrees\Auth;
25
use Fisharebest\Webtrees\FlashMessages;
26
use Fisharebest\Webtrees\GedcomRecord;
27
use Fisharebest\Webtrees\Html;
28
use Fisharebest\Webtrees\Http\RequestHandlers\TreePage;
29
use Fisharebest\Webtrees\I18N;
30
use Fisharebest\Webtrees\Media;
31
use Fisharebest\Webtrees\MediaFile;
32
use Fisharebest\Webtrees\Services\MediaFileService;
33
use Fisharebest\Webtrees\Services\PendingChangesService;
34
use Fisharebest\Webtrees\Tree;
35
use League\Flysystem\FileExistsException;
36
use League\Flysystem\FileNotFoundException;
37
use League\Flysystem\FilesystemInterface;
38
use League\Flysystem\Util;
39
use Psr\Http\Message\ResponseInterface;
40
use Psr\Http\Message\ServerRequestInterface;
41
42
use function assert;
43
use function is_string;
44
45
/**
46
 * Controller for edit forms and responses.
47
 */
48
class EditMediaController extends AbstractEditController
49
{
50
    /** @var MediaFileService */
51
    private $media_file_service;
52
53
    /** @var PendingChangesService */
54
    private $pending_changes_service;
55
56
    /**
57
     * EditMediaController constructor.
58
     *
59
     * @param MediaFileService      $media_file_service
60
     * @param PendingChangesService $pending_changes_service
61
     */
62
    public function __construct(MediaFileService $media_file_service, PendingChangesService $pending_changes_service)
63
    {
64
        $this->media_file_service      = $media_file_service;
65
        $this->pending_changes_service = $pending_changes_service;
66
    }
67
68
    /**
69
     * Add a media file to an existing media object.
70
     *
71
     * @param ServerRequestInterface $request
72
     *
73
     * @return ResponseInterface
74
     */
75
    public function addMediaFile(ServerRequestInterface $request): ResponseInterface
76
    {
77
        $tree = $request->getAttribute('tree');
78
        assert($tree instanceof Tree);
79
80
        $data_filesystem = $request->getAttribute('filesystem.data');
81
        assert($data_filesystem instanceof FilesystemInterface);
82
83
        $xref  = $request->getQueryParams()['xref'];
84
        $media = Media::getInstance($xref, $tree);
85
86
        try {
87
            $media = Auth::checkMediaAccess($media);
88
        } catch (Exception $ex) {
89
            return response(view('modals/error', [
90
                'title' => I18N::translate('Add a media file'),
91
                'error' => $ex->getMessage(),
92
            ]));
93
        }
94
95
        return response(view('modals/add-media-file', [
96
            'max_upload_size' => $this->media_file_service->maxUploadFilesize(),
97
            'media'           => $media,
98
            'media_types'     => $this->media_file_service->mediaTypes(),
99
            'tree'            => $tree,
100
            'unused_files'    => $this->media_file_service->unusedFiles($tree, $data_filesystem),
101
        ]));
102
    }
103
104
    /**
105
     * Add a media file to an existing media object.
106
     *
107
     * @param ServerRequestInterface $request
108
     *
109
     * @return ResponseInterface
110
     */
111
    public function addMediaFileAction(ServerRequestInterface $request): ResponseInterface
112
    {
113
        $tree = $request->getAttribute('tree');
114
        assert($tree instanceof Tree);
115
116
        $xref  = $request->getQueryParams()['xref'];
117
        $media = Media::getInstance($xref, $tree);
118
119
        $params = (array) $request->getParsedBody();
120
121
        $title = $params['title'];
122
        $type  = $params['type'];
123
124
        if ($media === null || $media->isPendingDeletion() || !$media->canEdit()) {
125
            return redirect(route(TreePage::class, ['tree' => $tree->name()]));
126
        }
127
128
        $file = $this->media_file_service->uploadFile($request);
129
130
        if ($file === '') {
131
            FlashMessages::addMessage(I18N::translate('There was an error uploading your file.'));
132
133
            return redirect($media->url());
134
        }
135
136
        $gedcom = $this->media_file_service->createMediaFileGedcom($file, $type, $title, '');
137
138
        $media->createFact($gedcom, true);
139
140
        // Accept the changes, to keep the filesystem in sync with the GEDCOM data.
141
        $this->pending_changes_service->acceptRecord($media);
142
143
        return redirect($media->url());
144
    }
145
146
    /**
147
     * Edit an existing media file.
148
     *
149
     * @param ServerRequestInterface $request
150
     *
151
     * @return ResponseInterface
152
     */
153
    public function editMediaFile(ServerRequestInterface $request): ResponseInterface
154
    {
155
        $tree = $request->getAttribute('tree');
156
        assert($tree instanceof Tree);
157
158
        $data_filesystem = $request->getAttribute('filesystem.data');
159
        assert($data_filesystem instanceof FilesystemInterface);
160
161
        $params  = $request->getQueryParams();
162
        $xref    = $params['xref'];
163
        $fact_id = $params['fact_id'];
164
        $media   = Media::getInstance($xref, $tree);
165
166
        try {
167
            $media = Auth::checkMediaAccess($media);
168
        } catch (Exception $ex) {
169
            return response(view('modals/error', [
170
                'title' => I18N::translate('Edit a media file'),
171
                'error' => $ex->getMessage(),
172
            ]), StatusCodeInterface::STATUS_FORBIDDEN);
173
        }
174
175
        foreach ($media->mediaFiles() as $media_file) {
176
            if ($media_file->factId() === $fact_id) {
177
                return response(view('modals/edit-media-file', [
178
                    'media_file'      => $media_file,
179
                    'max_upload_size' => $this->media_file_service->maxUploadFilesize(),
180
                    'media'           => $media,
181
                    'media_types'     => $this->media_file_service->mediaTypes(),
182
                    'unused_files'    => $this->media_file_service->unusedFiles($tree, $data_filesystem),
183
                    'tree'            => $tree,
184
                ]));
185
            }
186
        }
187
188
        return response('', StatusCodeInterface::STATUS_NOT_FOUND);
189
    }
190
191
    /**
192
     * Save an edited media file.
193
     *
194
     * @param ServerRequestInterface $request
195
     *
196
     * @return ResponseInterface
197
     */
198
    public function editMediaFileAction(ServerRequestInterface $request): ResponseInterface
199
    {
200
        $tree = $request->getAttribute('tree');
201
        assert($tree instanceof Tree);
202
203
        $data_filesystem = $request->getAttribute('filesystem.data');
204
        assert($data_filesystem instanceof FilesystemInterface);
205
206
        $xref    = $request->getQueryParams()['xref'];
207
        $fact_id = $request->getQueryParams()['fact_id'];
208
209
        $params = (array) $request->getParsedBody();
210
211
        $folder   = $params['folder'];
212
        $new_file = $params['new_file'];
213
        $remote   = $params['remote'];
214
        $title    = $params['title'];
215
        $type     = $params['type'];
216
        $media    = Media::getInstance($xref, $tree);
217
218
        // Tidy whitespace
219
        $type  = trim(preg_replace('/\s+/', ' ', $type));
220
        $title = trim(preg_replace('/\s+/', ' ', $title));
221
222
        // Media object oes not exist?  Media object is read-only?
223
        if ($media === null || $media->isPendingDeletion() || !$media->canEdit()) {
224
            return redirect(route(TreePage::class, ['tree' => $tree->name()]));
225
        }
226
227
        // Find the fact we are editing.
228
        $media_file = $media->mediaFiles()
229
            ->filter(static function (MediaFile $media_file) use ($fact_id): bool {
230
                return $media_file->factId() === $fact_id;
231
            })
232
            ->first();
233
234
        // Media file does not exist?
235
        if ($media_file === null) {
236
            return redirect(route(TreePage::class, ['tree' => $tree->name()]));
237
        }
238
239
        // We can edit the file as either a URL or a folder/file
240
        if ($remote !== '') {
241
            $file = $remote;
242
        } else {
243
            $new_file = str_replace('\\', '/', $new_file);
244
            $folder   = str_replace('\\', '/', $folder);
245
            $folder   = trim($folder, '/');
246
247
            if ($folder === '') {
248
                $file = $new_file;
249
            } else {
250
                $file = $folder . '/' . $new_file;
251
            }
252
        }
253
254
        // Invalid filename?  Do not change it.
255
        if ($new_file === '') {
256
            $file = $media_file->filename();
257
        }
258
259
        $filesystem = $media->tree()->mediaFilesystem($data_filesystem);
260
        $old        = $media_file->filename();
261
        $new        = $file;
262
263
        // Update the filesystem, if we can.
264
        if ($old !== $new && !$media_file->isExternal()) {
265
            try {
266
                $new = Util::normalizePath($new);
267
                $filesystem->rename($old, $new);
268
                FlashMessages::addMessage(I18N::translate('The media file %1$s has been renamed to %2$s.', Html::filename($media_file->filename()), Html::filename($file)), 'info');
269
            } catch (FileNotFoundException $ex) {
270
                // The "old" file may not exist.  For example, if the file was renamed on disk,
271
                // and we are now renaming the GEDCOM data to match.
272
            } catch (FileExistsException $ex) {
273
                // Don't overwrite existing file
274
                FlashMessages::addMessage(I18N::translate('The media file %1$s could not be renamed to %2$s.', Html::filename($media_file->filename()), Html::filename($file)), 'info');
275
                $file = $old;
276
            }
277
        }
278
279
        $gedcom = $this->media_file_service->createMediaFileGedcom($file, $type, $title, '');
280
281
        $media->updateFact($fact_id, $gedcom, true);
282
283
        // Accept the changes, to keep the filesystem in sync with the GEDCOM data.
284
        if ($old !== $new && !$media_file->isExternal()) {
285
            $this->pending_changes_service->acceptRecord($media);
286
        }
287
288
        return redirect($media->url());
289
    }
290
291
    /**
292
     * Show a form to create a new media object.
293
     *
294
     * @param ServerRequestInterface $request
295
     *
296
     * @return ResponseInterface
297
     */
298
    public function createMediaObject(ServerRequestInterface $request): ResponseInterface
299
    {
300
        $tree = $request->getAttribute('tree');
301
        assert($tree instanceof Tree);
302
303
        $data_filesystem = $request->getAttribute('filesystem.data');
304
        assert($data_filesystem instanceof FilesystemInterface);
305
306
        return response(view('modals/create-media-object', [
307
            'max_upload_size' => $this->media_file_service->maxUploadFilesize(),
308
            'media_types'     => $this->media_file_service->mediaTypes(),
309
            'unused_files'    => $this->media_file_service->unusedFiles($tree, $data_filesystem),
310
        ]));
311
    }
312
313
    /**
314
     * @param ServerRequestInterface $request
315
     *
316
     * @return ResponseInterface
317
     */
318
    public function createMediaObjectFromFileAction(ServerRequestInterface $request): ResponseInterface
319
    {
320
        $tree = $request->getAttribute('tree');
321
        assert($tree instanceof Tree);
322
323
        $params = (array) $request->getParsedBody();
324
        $file   = $params['file'];
325
        $type   = $params['type'];
326
        $title  = $params['title'];
327
        $note   = $params['note'];
328
329
        $gedcom = "0 @@ OBJE\n" . $this->media_file_service->createMediaFileGedcom($file, $type, $title, $note);
330
331
        $media_object = $tree->createRecord($gedcom);
332
333
        // Accept the new record.  Rejecting it would leave the filesystem out-of-sync with the genealogy
334
        $this->pending_changes_service->acceptRecord($media_object);
335
336
        return redirect($media_object->url());
337
    }
338
339
    /**
340
     * @param ServerRequestInterface $request
341
     *
342
     * @return ResponseInterface
343
     */
344
    public function linkMediaToIndividual(ServerRequestInterface $request): ResponseInterface
345
    {
346
        $tree = $request->getAttribute('tree');
347
        assert($tree instanceof Tree);
348
349
        $xref = $request->getQueryParams()['xref'];
350
        $media = Media::getInstance($xref, $tree);
351
352
        return response(view('modals/link-media-to-individual', [
353
            'media' => $media,
354
            'tree'  => $tree,
355
        ]));
356
    }
357
358
    /**
359
     * @param ServerRequestInterface $request
360
     *
361
     * @return ResponseInterface
362
     */
363
    public function linkMediaToFamily(ServerRequestInterface $request): ResponseInterface
364
    {
365
        $tree = $request->getAttribute('tree');
366
        assert($tree instanceof Tree);
367
368
        $xref = $request->getQueryParams()['xref'];
369
370
        $media = Media::getInstance($xref, $tree);
371
372
        return response(view('modals/link-media-to-family', [
373
            'media' => $media,
374
            'tree'  => $tree,
375
        ]));
376
    }
377
378
    /**
379
     * @param ServerRequestInterface $request
380
     *
381
     * @return ResponseInterface
382
     */
383
    public function linkMediaToSource(ServerRequestInterface $request): ResponseInterface
384
    {
385
        $tree = $request->getAttribute('tree');
386
        assert($tree instanceof Tree);
387
388
        $xref = $request->getQueryParams()['xref'];
389
390
        $media = Media::getInstance($xref, $tree);
391
392
        return response(view('modals/link-media-to-source', [
393
            'media' => $media,
394
            'tree'  => $tree,
395
        ]));
396
    }
397
398
    /**
399
     * @param ServerRequestInterface $request
400
     *
401
     * @return ResponseInterface
402
     */
403
    public function linkMediaToRecordAction(ServerRequestInterface $request): ResponseInterface
404
    {
405
        $tree = $request->getAttribute('tree');
406
        assert($tree instanceof Tree);
407
408
        $xref = $request->getAttribute('xref');
409
        assert(is_string($xref));
410
411
        $params = (array) $request->getParsedBody();
412
413
        $link = $params['link'];
414
415
        $media  = Media::getInstance($xref, $tree);
416
        $record = GedcomRecord::getInstance($link, $tree);
417
418
        $record->createFact('1 OBJE @' . $xref . '@', true);
419
420
        return redirect($media->url());
421
    }
422
}
423