Completed
Push — test ( fcdd70...8957cd )
by Greg
24:03 queued 04:42
created

Media::getInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2021 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 Closure;
23
use Fisharebest\Webtrees\Functions\FunctionsPrintFacts;
24
use Fisharebest\Webtrees\Http\RequestHandlers\MediaPage;
25
use Illuminate\Database\Capsule\Manager as DB;
26
use Illuminate\Support\Collection;
27
28
/**
29
 * A GEDCOM media (OBJE) object.
30
 */
31
class Media extends GedcomRecord
32
{
33
    public const RECORD_TYPE = 'OBJE';
34
35
    protected const ROUTE_NAME = MediaPage::class;
36
37
    /**
38
     * A closure which will create a record from a database row.
39
     *
40
     * @deprecated since 2.0.4.  Will be removed in 2.1.0 - Use Registry::mediaFactory()
41
     *
42
     * @param Tree $tree
43
     *
44
     * @return Closure
45
     */
46
    public static function rowMapper(Tree $tree): Closure
47
    {
48
        return Registry::mediaFactory()->mapper($tree);
49
    }
50
51
    /**
52
     * Get an instance of a media object. For single records,
53
     * we just receive the XREF. For bulk records (such as lists
54
     * and search results) we can receive the GEDCOM data as well.
55
     *
56
     * @deprecated since 2.0.4.  Will be removed in 2.1.0 - Use Registry::mediaFactory()
57
     *
58
     * @param string      $xref
59
     * @param Tree        $tree
60
     * @param string|null $gedcom
61
     *
62
     * @return Media|null
63
     */
64
    public static function getInstance(string $xref, Tree $tree, string $gedcom = null): ?Media
65
    {
66
        return Registry::mediaFactory()->make($xref, $tree, $gedcom);
67
    }
68
69
    /**
70
     * Each object type may have its own special rules, and re-implement this function.
71
     *
72
     * @param int $access_level
73
     *
74
     * @return bool
75
     */
76
    protected function canShowByType(int $access_level): bool
77
    {
78
        // Hide media objects if they are attached to private records
79
        $linked_ids = DB::table('link')
80
            ->where('l_file', '=', $this->tree->id())
81
            ->where('l_to', '=', $this->xref)
82
            ->pluck('l_from');
83
84
        foreach ($linked_ids as $linked_id) {
85
            $linked_record = Registry::gedcomRecordFactory()->make($linked_id, $this->tree);
86
            if ($linked_record instanceof GedcomRecord && !$linked_record->canShow($access_level)) {
87
                return false;
88
            }
89
        }
90
91
        // ... otherwise apply default behavior
92
        return parent::canShowByType($access_level);
93
    }
94
95
    /**
96
     * Get the media files for this media object
97
     *
98
     * @return Collection<MediaFile>
99
     */
100
    public function mediaFiles(): Collection
101
    {
102
        return $this->facts(['FILE'])
103
            ->map(function (Fact $fact): MediaFile {
104
                return new MediaFile($fact->gedcom(), $this);
105
            });
106
    }
107
108
    /**
109
     * Get the first media file that contains an image.
110
     *
111
     * @return MediaFile|null
112
     */
113
    public function firstImageFile(): ?MediaFile
114
    {
115
        return $this->mediaFiles()
116
            ->first(static function (MediaFile $media_file): bool {
117
                return $media_file->isImage() && !$media_file->isExternal();
118
            });
119
    }
120
121
    /**
122
     * Get the first note attached to this media object
123
     *
124
     * @return string
125
     */
126
    public function getNote(): string
127
    {
128
        $fact = $this->facts(['NOTE'])->first();
129
130
        if ($fact instanceof Fact) {
131
            // Link to note object
132
            $note = $fact->target();
133
            if ($note instanceof Note) {
134
                return $note->getNote();
135
            }
136
137
            // Inline note
138
            return $fact->value();
139
        }
140
141
        return '';
142
    }
143
144
    /**
145
     * Extract names from the GEDCOM record.
146
     *
147
     * @return void
148
     */
149
    public function extractNames(): void
150
    {
151
        $names = [];
152
        foreach ($this->mediaFiles() as $media_file) {
153
            $names[] = $media_file->title();
154
        }
155
        foreach ($this->mediaFiles() as $media_file) {
156
            $names[] = $media_file->filename();
157
        }
158
        $names = array_filter(array_unique($names));
159
160
        if ($names === []) {
161
            $names[] = $this->getFallBackName();
162
        }
163
164
        foreach ($names as $name) {
165
            $this->addName(static::RECORD_TYPE, $name, '');
166
        }
167
    }
168
169
    /**
170
     * This function should be redefined in derived classes to show any major
171
     * identifying characteristics of this record.
172
     *
173
     * @return string
174
     */
175
    public function formatListDetails(): string
176
    {
177
        ob_start();
178
        FunctionsPrintFacts::printMediaLinks($this->tree(), '1 OBJE @' . $this->xref() . '@', 1);
179
180
        return ob_get_clean();
181
    }
182
183
    /**
184
     * Display an image-thumbnail or a media-icon, and add markup for image viewers such as colorbox.
185
     *
186
     * @param int                  $width      Pixels
187
     * @param int                  $height     Pixels
188
     * @param string               $fit        "crop" or "contain"
189
     * @param array<string,string> $attributes Additional HTML attributes
190
     *
191
     * @return string
192
     */
193
    public function displayImage(int $width, int $height, string $fit, array $attributes = []): string
194
    {
195
        // Display the first image
196
        foreach ($this->mediaFiles() as $media_file) {
197
            if ($media_file->isImage()) {
198
                return $media_file->displayImage($width, $height, $fit, $attributes);
199
            }
200
        }
201
202
        // Display the first file of any type
203
        $media_file = $this->mediaFiles()->first();
204
205
        if ($media_file instanceof MediaFile) {
206
            return $media_file->displayImage($width, $height, $fit, $attributes);
207
        }
208
209
        // No image?
210
        return '';
211
    }
212
213
    /**
214
     * Lock the database row, to prevent concurrent edits.
215
     */
216
    public function lock(): void
217
    {
218
        DB::table('media')
219
            ->where('m_file', '=', $this->tree->id())
220
            ->where('m_id', '=', $this->xref())
221
            ->lockForUpdate()
222
            ->get();
223
    }
224
}
225