Issues (2564)

app/Media.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2025 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 <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees;
21
22
use Fisharebest\Webtrees\Elements\XrefMedia;
23
use Fisharebest\Webtrees\Http\RequestHandlers\MediaPage;
24
use Illuminate\Support\Collection;
25
26
use function array_filter;
27
use function array_unique;
28
29
/**
30
 * A GEDCOM media (OBJE) object.
31
 */
32
class Media extends GedcomRecord
33
{
34
    public const string RECORD_TYPE = 'OBJE';
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 34 at column 24
Loading history...
35
36
    protected const string ROUTE_NAME = MediaPage::class;
37
38
    /**
39
     * Each object type may have its own special rules, and re-implement this function.
40
     *
41
     * @param int $access_level
42
     *
43
     * @return bool
44
     */
45
    protected function canShowByType(int $access_level): bool
46
    {
47
        // Hide media objects if they are attached to private records
48
        $linked_ids = DB::table('link')
49
            ->where('l_file', '=', $this->tree->id())
50
            ->where('l_to', '=', $this->xref)
51
            ->pluck('l_from');
52
53
        foreach ($linked_ids as $linked_id) {
54
            $linked_record = Registry::gedcomRecordFactory()->make($linked_id, $this->tree);
55
            if ($linked_record instanceof GedcomRecord && !$linked_record->canShow($access_level)) {
56
                return false;
57
            }
58
        }
59
60
        // ... otherwise apply default behavior
61
        return parent::canShowByType($access_level);
62
    }
63
64
    /**
65
     * Get the media files for this media object
66
     *
67
     * @return Collection<int,MediaFile>
68
     */
69
    public function mediaFiles(): Collection
70
    {
71
        return $this->facts(['FILE'])
72
            ->map(fn (Fact $fact): MediaFile => new MediaFile($fact->gedcom(), $this));
73
    }
74
75
    /**
76
     * Get the first media file that contains an image.
77
     */
78
    public function firstImageFile(): MediaFile|null
79
    {
80
        return $this->mediaFiles()
81
            ->first(static fn (MediaFile $media_file): bool => $media_file->isImage() && !$media_file->isExternal());
82
    }
83
84
    /**
85
     * Get the first note attached to this media object
86
     *
87
     * @return string
88
     */
89
    public function getNote(): string
90
    {
91
        $fact = $this->facts(['NOTE'])->first();
92
93
        if ($fact instanceof Fact) {
94
            // Link to note object
95
            $note = $fact->target();
96
            if ($note instanceof Note) {
97
                return $note->getNote();
98
            }
99
100
            // Inline note
101
            return $fact->value();
102
        }
103
104
        return '';
105
    }
106
107
    /**
108
     * Extract names from the GEDCOM record.
109
     *
110
     * @return void
111
     */
112
    public function extractNames(): void
113
    {
114
        $names = [];
115
        foreach ($this->mediaFiles() as $media_file) {
116
            $names[] = $media_file->title();
117
        }
118
119
        // Titles may be empty.
120
        $names = array_filter($names);
121
122
        if ($names === []) {
123
            foreach ($this->mediaFiles() as $media_file) {
124
                $names[] = $media_file->filename();
125
            }
126
        }
127
128
        // Name and title may be the same.
129
        $names = array_unique($names);
130
131
        // No media files in this media object?
132
        if ($names === []) {
133
            $names[] = $this->getFallBackName();
134
        }
135
136
        foreach ($names as $name) {
137
            $this->addName(static::RECORD_TYPE, $name, '');
138
        }
139
    }
140
141
    /**
142
     * This function should be redefined in derived classes to show any major
143
     * identifying characteristics of this record.
144
     *
145
     * @return string
146
     */
147
    public function formatListDetails(): string
148
    {
149
        return (new XrefMedia(I18N::translate('Media')))
150
            ->labelValue('@' . $this->xref . '@', $this->tree());
151
    }
152
153
    /**
154
     * Display an image-thumbnail or a media-icon, and add markup for image viewers such as colorbox.
155
     *
156
     * @param int                  $width      Pixels
157
     * @param int                  $height     Pixels
158
     * @param string               $fit        "crop" or "contain"
159
     * @param array<string,string> $attributes Additional HTML attributes
160
     *
161
     * @return string
162
     */
163
    public function displayImage(int $width, int $height, string $fit, array $attributes): string
164
    {
165
        // Display the first image
166
        foreach ($this->mediaFiles() as $media_file) {
167
            if ($media_file->isImage()) {
168
                return $media_file->displayImage($width, $height, $fit, $attributes);
169
            }
170
        }
171
172
        // Display the first file of any type
173
        $media_file = $this->mediaFiles()->first();
174
175
        if ($media_file instanceof MediaFile) {
176
            return $media_file->displayImage($width, $height, $fit, $attributes);
177
        }
178
179
        // No image?
180
        return '';
181
    }
182
183
    /**
184
     * Lock the database row, to prevent concurrent edits.
185
     */
186
    public function lock(): void
187
    {
188
        DB::table('media')
189
            ->where('m_file', '=', $this->tree->id())
190
            ->where('m_id', '=', $this->xref())
191
            ->lockForUpdate()
192
            ->get();
193
    }
194
}
195