Issues (120)

app/Functions/FunctionsPrint.php (2 issues)

1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2022 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\Functions;
21
22
use Fisharebest\Webtrees\Age;
23
use Fisharebest\Webtrees\Date;
24
use Fisharebest\Webtrees\Fact;
25
use Fisharebest\Webtrees\Family;
26
use Fisharebest\Webtrees\Filter;
27
use Fisharebest\Webtrees\Gedcom;
28
use Fisharebest\Webtrees\GedcomRecord;
29
use Fisharebest\Webtrees\GedcomTag;
30
use Fisharebest\Webtrees\Header;
31
use Fisharebest\Webtrees\I18N;
32
use Fisharebest\Webtrees\Individual;
33
use Fisharebest\Webtrees\Media;
34
use Fisharebest\Webtrees\Note;
35
use Fisharebest\Webtrees\Place;
36
use Fisharebest\Webtrees\Registry;
37
use Fisharebest\Webtrees\Repository;
38
use Fisharebest\Webtrees\Source;
39
use Fisharebest\Webtrees\Submission;
40
use Fisharebest\Webtrees\Submitter;
41
use Fisharebest\Webtrees\Tree;
42
use Illuminate\Support\Collection;
43
use Illuminate\Support\Str;
44
use LogicException;
45
use Ramsey\Uuid\Uuid;
46
47
use function array_filter;
48
use function array_intersect;
49
use function array_merge;
50
use function array_search;
51
use function e;
52
use function explode;
53
use function in_array;
54
use function preg_match;
55
use function preg_match_all;
56
use function preg_replace_callback;
57
use function preg_split;
58
use function str_contains;
59
use function strip_tags;
60
use function strlen;
61
use function strpos;
62
use function strtoupper;
63
use function substr;
64
use function trim;
65
use function uasort;
66
use function var_export;
67
use function view;
68
69
use const PREG_SET_ORDER;
70
use const PREG_SPLIT_NO_EMPTY;
71
72
/**
73
 * Class FunctionsPrint - common functions
74
 *
75
 * @deprecated since 2.0.6.  Will be removed in 2.1.0
76
 */
77
class FunctionsPrint
78
{
79
    /**
80
     * print a note record
81
     *
82
     * @param Tree   $tree
83
     * @param string $text
84
     * @param int    $nlevel the level of the note record
85
     * @param string $nrec   the note record to print
86
     *
87
     * @return string
88
     */
89
    private static function printNoteRecord(Tree $tree, string $text, int $nlevel, string $nrec): string
90
    {
91
        $element = Registry::elementFactory()->make('NOTE:CONC');
92
93
        $text .= Functions::getCont($nlevel, $nrec);
94
95
        if (preg_match('/^0 @(' . Gedcom::REGEX_XREF . ')@ NOTE/', $nrec, $match)) {
96
            // Shared note.
97
            $note = Registry::noteFactory()->make($match[1], $tree);
98
            // It must exist.
99
            assert($note instanceof Note);
100
101
            $label      = I18N::translate('Shared note');
102
            $html       = $element->value($note->getNote(), $tree);
103
            $first_line = '<a href="' . e($note->url()) . '">' . $note->fullName() . '</a>';
104
105
            $one_line_only = strip_tags($note->fullName()) === strip_tags($note->getNote());
106
        } else {
107
            // Inline note.
108
            $label = I18N::translate('Note');
109
            $html  = $element->value($text, $tree);
110
111
            [$first_line] = explode("\n", strip_tags($html));
112
            // Use same logic as note objects
113
            $first_line = Str::limit($first_line, 100, I18N::translate('…'));
114
115
            $one_line_only = !str_contains($text, "\n") && mb_strlen($text) <= 100;
116
        }
117
118
        if ($one_line_only) {
119
            return
120
                '<div class="fact_NOTE">' .
121
                I18N::translate(
122
                    '<span class="label">%1$s:</span> <span class="field" dir="auto">%2$s</span>',
123
                    $label,
124
                    $first_line
125
                ) .
126
                '</div>';
127
        }
128
129
        $id       = 'collapse-' . Uuid::uuid4()->toString();
130
        $expanded = (bool) $tree->getPreference('EXPAND_NOTES');
131
132
        return
133
            '<div class="fact_NOTE">' .
134
            '<a href="#' . e($id) . '" role="button" data-toggle="collapse" aria-controls="' . e($id) . '" aria-expanded="' . ($expanded ? 'true' : 'false') . '">' .
135
            view('icons/expand') .
136
            view('icons/collapse') .
137
            '</a>' .
138
            '<span class="label">' . $label . ':</span> ' .
139
            $first_line .
140
            '</div>' .
141
            '<div id="' . e($id) . '" class="markdown collapse ' . ($expanded ? 'show' : '') . '">' .
142
            $html .
143
            '</div>';
144
    }
145
146
    /**
147
     * Print all of the notes in this fact record
148
     *
149
     * @param Tree   $tree
150
     * @param string $factrec The fact to print the notes from
151
     * @param int    $level   The level of the notes
152
     *
153
     * @return string HTML
154
     */
155
    public static function printFactNotes(Tree $tree, string $factrec, int $level): string
156
    {
157
        $data          = '';
158
        $previous_spos = 0;
159
        $nlevel        = $level + 1;
160
        $ct            = preg_match_all("/$level NOTE (.*)/", $factrec, $match, PREG_SET_ORDER);
161
        for ($j = 0; $j < $ct; $j++) {
162
            $spos1 = strpos($factrec, $match[$j][0], $previous_spos);
163
            $spos2 = strpos($factrec . "\n$level", "\n$level", $spos1 + 1);
164
            if (!$spos2) {
165
                $spos2 = strlen($factrec);
166
            }
167
            $previous_spos = $spos2;
168
            $nrec          = substr($factrec, $spos1, $spos2 - $spos1);
169
            if (!isset($match[$j][1])) {
170
                $match[$j][1] = '';
171
            }
172
            if (!preg_match('/^@(' . Gedcom::REGEX_XREF . ')@$/', $match[$j][1], $nmatch)) {
173
                $data .= self::printNoteRecord($tree, $match[$j][1], $nlevel, $nrec);
174
            } else {
175
                $note = Registry::noteFactory()->make($nmatch[1], $tree);
176
                if ($note) {
177
                    if ($note->canShow()) {
178
                        $noterec = $note->gedcom();
179
                        $nt      = preg_match("/0 @$nmatch[1]@ NOTE (.*)/", $noterec, $n1match);
180
                        $data    .= self::printNoteRecord($tree, $nt > 0 ? $n1match[1] : '', 1, $noterec);
181
                    }
182
                } else {
183
                    $data = '<div class="fact_NOTE"><span class="label">' . I18N::translate('Note') . '</span>: <span class="field error">' . $nmatch[1] . '</span></div>';
184
                }
185
            }
186
        }
187
188
        return $data;
189
    }
190
191
    /**
192
     * Format age of parents in HTML
193
     *
194
     * @param Individual $person child
195
     * @param Date       $birth_date
196
     *
197
     * @return string HTML
198
     */
199
    public static function formatParentsAges(Individual $person, Date $birth_date): string
200
    {
201
        $html     = '';
202
        $families = $person->childFamilies();
203
        // Multiple sets of parents (e.g. adoption) cause complications, so ignore.
204
        if ($birth_date->isOK() && $families->count() === 1) {
205
            $family = $families->first();
206
            foreach ($family->spouses() as $parent) {
207
                if ($parent->getBirthDate()->isOK()) {
208
                    $sex      = '<small>' . view('icons/sex', ['sex' => $parent->sex()]) . '</small>';
209
                    $age      = new Age($parent->getBirthDate(), $birth_date);
210
                    $deatdate = $parent->getDeathDate();
211
                    switch ($parent->sex()) {
212
                        case 'F':
213
                            // Highlight mothers who die in childbirth or shortly afterwards
214
                            if ($deatdate->isOK() && $deatdate->maximumJulianDay() < $birth_date->minimumJulianDay() + 90) {
215
                                $html .= ' <span title="' . I18N::translate('Death of a mother') . '" class="parentdeath">' . $sex . I18N::number($age->ageYears()) . '</span>';
216
                            } else {
217
                                $html .= ' <span title="' . I18N::translate('Mother’s age') . '">' . $sex . I18N::number($age->ageYears()) . '</span>';
218
                            }
219
                            break;
220
                        case 'M':
221
                            // Highlight fathers who die before the birth
222
                            if ($deatdate->isOK() && $deatdate->maximumJulianDay() < $birth_date->minimumJulianDay()) {
223
                                $html .= ' <span title="' . I18N::translate('Death of a father') . '" class="parentdeath">' . $sex . I18N::number($age->ageYears()) . '</span>';
224
                            } else {
225
                                $html .= ' <span title="' . I18N::translate('Father’s age') . '">' . $sex . I18N::number($age->ageYears()) . '</span>';
226
                            }
227
                            break;
228
                        default:
229
                            $html .= ' <span title="' . I18N::translate('Parent’s age') . '">' . $sex . I18N::number($age->ageYears()) . '</span>';
230
                            break;
231
                    }
232
                }
233
            }
234
            if ($html) {
235
                $html = '<span class="age">' . $html . '</span>';
236
            }
237
        }
238
239
        return $html;
240
    }
241
242
    /**
243
     * Convert a GEDCOM age string to localized text.
244
     *
245
     * @param string $age_string
246
     *
247
     * @return string
248
     */
249
    public static function formatGedcomAge(string $age_string): string
250
    {
251
        switch (strtoupper($age_string)) {
252
            case 'CHILD':
253
                return I18N::translate('Child');
254
            case 'INFANT':
255
                return I18N::translate('Infant');
256
            case 'STILLBORN':
257
                return I18N::translate('Stillborn');
258
            default:
259
                return (string) preg_replace_callback(
260
                    [
261
                        '/(\d+)([ymwd])/',
262
                    ],
263
                    static function (array $match): string {
264
                        $num = (int) $match[1];
265
266
                        switch ($match[2]) {
267
                            case 'y':
268
                                return I18N::plural('%s year', '%s years', $num, I18N::number($num));
269
                            case 'm':
270
                                return I18N::plural('%s month', '%s months', $num, I18N::number($num));
271
                            case 'w':
272
                                return I18N::plural('%s week', '%s weeks', $num, I18N::number($num));
273
                            case 'd':
274
                                return I18N::plural('%s day', '%s days', $num, I18N::number($num));
275
                            default:
276
                                throw new LogicException('Should never get here');
277
                        }
278
                    },
279
                    $age_string
280
                ) ;
281
        }
282
    }
283
284
    /**
285
     * Print fact DATE/TIME
286
     *
287
     * @param Fact         $event  event containing the date/age
288
     * @param GedcomRecord $record the person (or couple) whose ages should be printed
289
     * @param bool         $anchor option to print a link to calendar
290
     * @param bool         $time   option to print TIME value
291
     *
292
     * @return string
293
     */
294
    public static function formatFactDate(Fact $event, GedcomRecord $record, bool $anchor, bool $time): string
295
    {
296
        $factrec = $event->gedcom();
297
        $html    = '';
298
        // Recorded age
299
        if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) {
300
            $fact_age = self::formatGedcomAge($match[1]);
301
        } else {
302
            $fact_age = '';
303
        }
304
        if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) {
305
            $husb_age = self::formatGedcomAge($match[1]);
306
        } else {
307
            $husb_age = '';
308
        }
309
        if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) {
310
            $wife_age = self::formatGedcomAge($match[1]);
311
        } else {
312
            $wife_age = '';
313
        }
314
315
        // Calculated age
316
        $fact = $event->getTag();
0 ignored issues
show
Deprecated Code introduced by
The function Fisharebest\Webtrees\Fact::getTag() has been deprecated: since 2.0.5. Will be removed in 2.1.0 ( Ignorable by Annotation )

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

316
        $fact = /** @scrutinizer ignore-deprecated */ $event->getTag();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
317
        if (preg_match('/\n2 DATE (.+)/', $factrec, $match)) {
318
            $date = new Date($match[1]);
319
            $html .= ' ' . $date->display($anchor);
320
            // time
321
            if ($time && preg_match('/\n3 TIME (.+)/', $factrec, $match)) {
322
                $html .= ' – <span class="date">' . $match[1] . '</span>';
323
            }
324
            if ($record instanceof Individual) {
325
                if (
326
                    in_array($fact, Gedcom::BIRTH_EVENTS, true) &&
327
                    $record === $event->record() &&
0 ignored issues
show
The condition $record === $event->record() is always false.
Loading history...
328
                    $record->tree()->getPreference('SHOW_PARENTS_AGE') === '1'
329
                ) {
330
                    // age of parents at child birth
331
                    $html .= self::formatParentsAges($record, $date);
332
                }
333
                if ($fact !== 'BIRT' && $fact !== 'CHAN' && $fact !== '_TODO') {
334
                    // age at event
335
                    $birth_date = $record->getBirthDate();
336
                    // Can't use getDeathDate(), as this also gives BURI/CREM events, which
337
                    // wouldn't give the correct "days after death" result for people with
338
                    // no DEAT.
339
                    $death_event = $record->facts(['DEAT'])->first();
340
                    if ($death_event instanceof Fact) {
341
                        $death_date = $death_event->date();
342
                    } else {
343
                        $death_date = new Date('');
344
                    }
345
                    $ageText = '';
346
                    if ($fact === 'DEAT' || Date::compare($date, $death_date) <= 0 || !$record->isDead()) {
347
                        // Before death, print age
348
                        $age = (string) new Age($birth_date, $date);
349
350
                        // Only show calculated age if it differs from recorded age
351
                        if ($age !== '') {
352
                            if (
353
                                $fact_age !== '' && $fact_age !== $age ||
354
                                $fact_age === '' && $husb_age === '' && $wife_age === '' ||
355
                                $husb_age !== '' && $husb_age !== $age && $record->sex() === 'M' ||
356
                                $wife_age !== '' && $wife_age !== $age && $record->sex() === 'F'
357
                            ) {
358
                                switch ($record->sex()) {
359
                                    case 'M':
360
                                        /* I18N: The age of an individual at a given date */
361
                                        $ageText = I18N::translateContext('Male', '(aged %s)', $age);
362
                                        break;
363
                                    case 'F':
364
                                        /* I18N: The age of an individual at a given date */
365
                                        $ageText = I18N::translateContext('Female', '(aged %s)', $age);
366
                                        break;
367
                                    default:
368
                                        /* I18N: The age of an individual at a given date */
369
                                        $ageText = I18N::translate('(aged %s)', $age);
370
                                        break;
371
                                }
372
                            }
373
                        }
374
                    }
375
                    if ($fact !== 'DEAT' && $death_date->isOK() && Date::compare($death_date, $date) <= 0) {
376
                        $death_day = $death_date->minimumDate()->day();
377
                        $event_day = $date->minimumDate()->day();
378
                        if ($death_day !== 0 && $event_day !== 0 && Date::compare($death_date, $date) === 0) {
379
                            // On the exact date of death?
380
                            // NOTE: this path is never reached.  Keep the code (translation) in case
381
                            // we decide to re-introduce it.
382
                            $ageText = I18N::translate('(on the date of death)');
383
                        } else {
384
                            // After death
385
                            $age = (string) new Age($death_date, $date);
386
                            $ageText = I18N::translate('(%s after death)', $age);
387
                        }
388
                        // Family events which occur after death are probably errors
389
                        if ($event->record() instanceof Family) {
390
                            $ageText .= view('icons/warning');
391
                        }
392
                    }
393
                    if ($ageText !== '') {
394
                        $html .= ' <span class="age">' . $ageText . '</span>';
395
                    }
396
                }
397
            }
398
        }
399
        // print gedcom ages
400
        $age_labels = [
401
            I18N::translate('Age')     => $fact_age,
402
            I18N::translate('Husband') => $husb_age,
403
            I18N::translate('Wife')    => $wife_age,
404
        ];
405
406
        foreach (array_filter($age_labels) as $label => $age) {
407
            $html .= ' <span class="label">' . $label . ':</span> <span class="age">' . $age . '</span>';
408
        }
409
410
        return $html;
411
    }
412
413
    /**
414
     * print fact PLACe TEMPle STATus
415
     *
416
     * @param Fact $event       gedcom fact record
417
     * @param bool $anchor      to print a link to placelist
418
     * @param bool $sub_records to print place subrecords
419
     * @param bool $lds         to print LDS TEMPle and STATus
420
     *
421
     * @return string HTML
422
     */
423
    public static function formatFactPlace(Fact $event, $anchor = false, $sub_records = false, $lds = false): string
424
    {
425
        $tree = $event->record()->tree();
426
427
        if ($anchor) {
428
            // Show the full place name, for facts/events tab
429
            $html = $event->place()->fullName(true);
430
        } else {
431
            // Abbreviate the place name, for chart boxes
432
            return $event->place()->shortName();
433
        }
434
435
        if ($sub_records) {
436
            $placerec = Functions::getSubRecord(2, '2 PLAC', $event->gedcom());
437
            if ($placerec !== '') {
438
                if (preg_match_all('/\n3 (?:_HEB|ROMN) (.+)/', $placerec, $matches)) {
439
                    foreach ($matches[1] as $match) {
440
                        $wt_place = new Place($match, $tree);
441
                        $html     .= ' - ' . $wt_place->fullName();
442
                    }
443
                }
444
                $map_lati = '';
445
                $cts      = preg_match('/\d LATI (.*)/', $placerec, $match);
446
                if ($cts > 0) {
447
                    $map_lati = $match[1];
448
                    $html     .= '<br><span class="label">' . I18N::translate('Latitude') . ': </span>' . $map_lati;
449
                }
450
                $map_long = '';
451
                $cts      = preg_match('/\d LONG (.*)/', $placerec, $match);
452
                if ($cts > 0) {
453
                    $map_long = $match[1];
454
                    $html     .= ' <span class="label">' . I18N::translate('Longitude') . ': </span>' . $map_long;
455
                }
456
                if ($map_lati && $map_long) {
457
                    $map_lati = trim(strtr($map_lati, 'NSEW,�', ' - -. ')); // S5,6789 ==> -5.6789
458
                    $map_long = trim(strtr($map_long, 'NSEW,�', ' - -. ')); // E3.456� ==> 3.456
459
460
                    $html .= '<a href="https://maps.google.com/maps?q=' . e($map_lati) . ',' . e($map_long) . '" rel="nofollow" target="_top" title="' . I18N::translate('Google Mapsâ„¢') . '">' .
461
                        view('icons/google-maps') .
462
                        '<span class="sr-only">' . I18N::translate('Google Mapsâ„¢') . '</span>' .
463
                        '</a>';
464
465
                    $html .= '<a href="https://www.bing.com/maps/?lvl=15&cp=' . e($map_lati) . '~' . e($map_long) . '" rel="nofollow" target="_top" title="' . I18N::translate('Bing Mapsâ„¢') . '">' .
466
                        view('icons/bing-maps') .
467
                        '<span class="sr-only">' . I18N::translate('Bing Mapsâ„¢') . '</span>' .
468
                        '</a>';
469
470
                    $html .= '<a href="https://www.openstreetmap.org/#map=15/' . e($map_lati) . '/' . e($map_long) . '" rel="nofollow" target="_top" title="' . I18N::translate('OpenStreetMapâ„¢') . '">' .
471
                        view('icons/openstreetmap') .
472
                        '<span class="sr-only">' . I18N::translate('OpenStreetMapâ„¢') . '</span>' .
473
                        '</a>';
474
                }
475
                if (preg_match('/\d NOTE (.*)/', $placerec, $match)) {
476
                    $html .= '<br>' . self::printFactNotes($tree, $placerec, 3);
477
                }
478
            }
479
        }
480
        if ($lds) {
481
            if (preg_match('/2 TEMP (.*)/', $event->gedcom(), $match)) {
482
                $element = Registry::elementFactory()->make($event->tag() . ':TEMP');
483
                $html .= $element->labelValue($match[1], $tree);
484
            }
485
            if (preg_match('/2 STAT (.*)/', $event->gedcom(), $match)) {
486
                $element = Registry::elementFactory()->make($event->tag() . ':STAT');
487
                $html .= $element->labelValue($match[1], $tree);
488
                if (preg_match('/3 DATE (.*)/', $event->gedcom(), $match)) {
489
                    $date = new Date($match[1]);
490
                    $element = Registry::elementFactory()->make($event->tag() . ':STAT:DATE');
491
                    $html .= $element->labelValue($date->display(), $tree);
492
                }
493
            }
494
        }
495
496
        return $html;
497
    }
498
499
    /**
500
     * Check for facts that may exist only once for a certain record type.
501
     * If the fact already exists in the second array, delete it from the first one.
502
     *
503
     * @param array<string>    $uniquefacts
504
     * @param Collection<Fact> $recfacts
505
     *
506
     * @return array<string>
507
     */
508
    public static function checkFactUnique(array $uniquefacts, Collection $recfacts): array
509
    {
510
        foreach ($recfacts as $factarray) {
511
            $fact = $factarray->getTag();
512
513
            $key = array_search($fact, $uniquefacts, true);
514
            if ($key !== false) {
515
                unset($uniquefacts[$key]);
516
            }
517
        }
518
519
        return $uniquefacts;
520
    }
521
522
    /**
523
     * Print a new fact box on details pages
524
     *
525
     * @param GedcomRecord     $record    the person, family, source etc the fact will be added to
526
     * @param Collection<Fact> $usedfacts an array of facts already used in this record
527
     * @param string           $type      the type of record INDI, FAM, SOUR etc
528
     *
529
     * @return void
530
     */
531
    public static function printAddNewFact(GedcomRecord $record, Collection $usedfacts, string $type): void
532
    {
533
        $tree = $record->tree();
534
535
        // -- Add from pick list
536
        switch ($type) {
537
            case Individual::RECORD_TYPE:
538
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
539
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
540
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
541
                break;
542
543
            case Family::RECORD_TYPE:
544
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
545
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
546
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
547
                break;
548
549
            case Source::RECORD_TYPE:
550
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
551
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
552
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
553
                break;
554
555
            case Note::RECORD_TYPE:
556
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
557
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
558
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
559
                break;
560
561
            case Repository::RECORD_TYPE:
562
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
563
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
564
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
565
                break;
566
567
            case Media::RECORD_TYPE:
568
                $addfacts    = ['NOTE'];
569
                $uniquefacts = [];
570
                $quickfacts  = [];
571
                break;
572
            default:
573
                return;
574
        }
575
        $addfacts            = array_merge(self::checkFactUnique($uniquefacts, $usedfacts), $addfacts);
576
        $quickfacts          = array_intersect($quickfacts, $addfacts);
577
        $translated_addfacts = [];
578
        foreach ($addfacts as $addfact) {
579
            $translated_addfacts[$addfact] = GedcomTag::getLabel($record->tag() . ':' . $addfact);
580
        }
581
        uasort($translated_addfacts, static function (string $x, string $y): int {
582
            return I18N::strcasecmp(I18N::translate($x), I18N::translate($y));
583
        });
584
585
        echo view('edit/add-fact-row', [
586
            'add_facts'   => $translated_addfacts,
587
            'quick_facts' => $quickfacts,
588
            'record'      => $record,
589
            'tree'        => $tree,
590
        ]);
591
    }
592
}
593