Passed
Push — master ( 63f369...ac5ee7 )
by Greg
05:52
created

FunctionsPrint::printAddNewFact()   C

Complexity

Conditions 11
Paths 19

Size

Total Lines 77
Code Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 61
c 0
b 0
f 0
nc 19
nop 3
dl 0
loc 77
rs 6.7042

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) 2019 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\Functions;
21
22
use Fisharebest\Webtrees\Date;
23
use Fisharebest\Webtrees\Fact;
24
use Fisharebest\Webtrees\Family;
25
use Fisharebest\Webtrees\Filter;
26
use Fisharebest\Webtrees\Gedcom;
27
use Fisharebest\Webtrees\GedcomCode\GedcomCodeStat;
28
use Fisharebest\Webtrees\GedcomCode\GedcomCodeTemp;
29
use Fisharebest\Webtrees\GedcomRecord;
30
use Fisharebest\Webtrees\GedcomTag;
31
use Fisharebest\Webtrees\Header;
32
use Fisharebest\Webtrees\I18N;
33
use Fisharebest\Webtrees\Individual;
34
use Fisharebest\Webtrees\Media;
35
use Fisharebest\Webtrees\Note;
36
use Fisharebest\Webtrees\Place;
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 Ramsey\Uuid\Uuid;
45
46
use function view;
47
48
/**
49
 * Class FunctionsPrint - common functions
50
 */
51
class FunctionsPrint
52
{
53
    /**
54
     * print a note record
55
     *
56
     * @param Tree   $tree
57
     * @param string $text
58
     * @param int    $nlevel the level of the note record
59
     * @param string $nrec   the note record to print
60
     *
61
     * @return string
62
     */
63
    private static function printNoteRecord(Tree $tree, $text, $nlevel, $nrec): string
64
    {
65
        $text .= Functions::getCont($nlevel, $nrec);
66
67
        // Check if shared note (we have already checked that it exists)
68
        if (preg_match('/^0 @(' . Gedcom::REGEX_XREF . ')@ NOTE/', $nrec, $match)) {
69
            $note  = Note::getInstance($match[1], $tree);
70
            $label = 'SHARED_NOTE';
71
            $html  = Filter::formatText($note->getNote(), $tree);
72
        } else {
73
            $note  = null;
74
            $label = 'NOTE';
75
            $html  = Filter::formatText($text, $tree);
76
        }
77
78
        if (strpos($text, "\n") === false) {
79
            // A one-line note? strip the block-level tags, so it displays inline
80
            return GedcomTag::getLabelValue($label, strip_tags($html, '<a><strong><em>'));
81
        }
82
83
        if ($tree->getPreference('EXPAND_NOTES')) {
84
            // A multi-line note, and we're expanding notes by default
85
            return GedcomTag::getLabelValue($label, $html);
86
        }
87
88
        // A multi-line note, with an expand/collapse option
89
        $element_id = Uuid::uuid4()->toString();
90
        // NOTE: class "note-details" is (currently) used only by some third-party themes
91
        if ($note) {
92
            $first_line = '<a href="' . e($note->url()) . '">' . $note->fullName() . '</a>';
93
        } else {
94
            [$text] = explode("\n", strip_tags($html));
95
            $first_line = Str::limit($text, 100, I18N::translate('…'));
96
        }
97
98
        return
99
            '<div class="fact_NOTE"><span class="label">' .
100
            '<a href="#" onclick="expand_layer(\'' . $element_id . '\'); return false;"><i id="' . $element_id . '_img" class="icon-plus"></i></a> ' . GedcomTag::getLabel($label) . ':</span> ' . '<span id="' . $element_id . '-alt">' . $first_line . '</span>' .
101
            '</div>' .
102
            '<div class="note-details" id="' . $element_id . '" style="display:none">' . $html . '</div>';
103
    }
104
105
    /**
106
     * Print all of the notes in this fact record
107
     *
108
     * @param Tree   $tree
109
     * @param string $factrec The factrecord to print the notes from
110
     * @param int    $level   The level of the factrecord
111
     *
112
     * @return string HTML
113
     */
114
    public static function printFactNotes(Tree $tree, $factrec, $level): string
115
    {
116
        $data          = '';
117
        $previous_spos = 0;
118
        $nlevel        = $level + 1;
119
        $ct            = preg_match_all("/$level NOTE (.*)/", $factrec, $match, PREG_SET_ORDER);
120
        for ($j = 0; $j < $ct; $j++) {
121
            $spos1 = strpos($factrec, $match[$j][0], $previous_spos);
122
            $spos2 = strpos($factrec . "\n$level", "\n$level", $spos1 + 1);
123
            if (!$spos2) {
124
                $spos2 = strlen($factrec);
125
            }
126
            $previous_spos = $spos2;
127
            $nrec          = substr($factrec, $spos1, $spos2 - $spos1);
128
            if (!isset($match[$j][1])) {
129
                $match[$j][1] = '';
130
            }
131
            if (!preg_match('/^@(' . Gedcom::REGEX_XREF . ')@$/', $match[$j][1], $nmatch)) {
132
                $data .= self::printNoteRecord($tree, $match[$j][1], $nlevel, $nrec);
133
            } else {
134
                $note = Note::getInstance($nmatch[1], $tree);
135
                if ($note) {
136
                    if ($note->canShow()) {
137
                        $noterec = $note->gedcom();
138
                        $nt      = preg_match("/0 @$nmatch[1]@ NOTE (.*)/", $noterec, $n1match);
139
                        $data    .= self::printNoteRecord($tree, ($nt > 0) ? $n1match[1] : '', 1, $noterec);
140
                    }
141
                } else {
142
                    $data = '<div class="fact_NOTE"><span class="label">' . I18N::translate('Note') . '</span>: <span class="field error">' . $nmatch[1] . '</span></div>';
143
                }
144
            }
145
        }
146
147
        return $data;
148
    }
149
150
    /**
151
     * Format age of parents in HTML
152
     *
153
     * @param Individual $person child
154
     * @param Date       $birth_date
155
     *
156
     * @return string HTML
157
     */
158
    public static function formatParentsAges(Individual $person, Date $birth_date): string
159
    {
160
        $html     = '';
161
        $families = $person->childFamilies();
162
        // Multiple sets of parents (e.g. adoption) cause complications, so ignore.
163
        if ($birth_date->isOK() && $families->count() === 1) {
164
            $family = $families->first();
165
            foreach ($family->spouses() as $parent) {
166
                if ($parent->getBirthDate()->isOK()) {
167
                    $sex      = '<small>' . view('icons/sex', ['sex' => $parent->sex()]) . '</small>';
168
                    $age      = Date::getAge($parent->getBirthDate(), $birth_date);
169
                    $deatdate = $parent->getDeathDate();
170
                    switch ($parent->sex()) {
171
                        case 'F':
172
                            // Highlight mothers who die in childbirth or shortly afterwards
173
                            if ($deatdate->isOK() && $deatdate->maximumJulianDay() < $birth_date->minimumJulianDay() + 90) {
174
                                $html .= ' <span title="' . GedcomTag::getLabel('_DEAT_PARE', $parent) . '" class="parentdeath">' . $sex . $age . '</span>';
175
                            } else {
176
                                $html .= ' <span title="' . I18N::translate('Mother’s age') . '">' . $sex . $age . '</span>';
177
                            }
178
                            break;
179
                        case 'M':
180
                            // Highlight fathers who die before the birth
181
                            if ($deatdate->isOK() && $deatdate->maximumJulianDay() < $birth_date->minimumJulianDay()) {
182
                                $html .= ' <span title="' . GedcomTag::getLabel('_DEAT_PARE', $parent) . '" class="parentdeath">' . $sex . $age . '</span>';
183
                            } else {
184
                                $html .= ' <span title="' . I18N::translate('Father’s age') . '">' . $sex . $age . '</span>';
185
                            }
186
                            break;
187
                        default:
188
                            $html .= ' <span title="' . I18N::translate('Parent’s age') . '">' . $sex . $age . '</span>';
189
                            break;
190
                    }
191
                }
192
            }
193
            if ($html) {
194
                $html = '<span class="age">' . $html . '</span>';
195
            }
196
        }
197
198
        return $html;
199
    }
200
201
    /**
202
     * Print fact DATE/TIME
203
     *
204
     * @param Fact         $event  event containing the date/age
205
     * @param GedcomRecord $record the person (or couple) whose ages should be printed
206
     * @param bool         $anchor option to print a link to calendar
207
     * @param bool         $time   option to print TIME value
208
     *
209
     * @return string
210
     */
211
    public static function formatFactDate(Fact $event, GedcomRecord $record, $anchor, $time): string
212
    {
213
        $factrec = $event->gedcom();
214
        $html    = '';
215
        // Recorded age
216
        if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) {
217
            $fact_age = $match[1];
218
        } else {
219
            $fact_age = '';
220
        }
221
        if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) {
222
            $husb_age = $match[1];
223
        } else {
224
            $husb_age = '';
225
        }
226
        if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) {
227
            $wife_age = $match[1];
228
        } else {
229
            $wife_age = '';
230
        }
231
232
        // Calculated age
233
        $fact = $event->getTag();
234
        if (preg_match('/\n2 DATE (.+)/', $factrec, $match)) {
235
            $date = new Date($match[1]);
236
            $html .= ' ' . $date->display($anchor);
237
            // time
238
            if ($time && preg_match('/\n3 TIME (.+)/', $factrec, $match)) {
239
                $html .= ' – <span class="date">' . $match[1] . '</span>';
240
            }
241
            if ($record instanceof Individual) {
242
                if (in_array($fact, Gedcom::BIRTH_EVENTS, true) && $record->tree()->getPreference('SHOW_PARENTS_AGE')) {
243
                    // age of parents at child birth
244
                    $html .= self::formatParentsAges($record, $date);
245
                }
246
                if ($fact !== 'BIRT' && $fact !== 'CHAN' && $fact !== '_TODO') {
247
                    // age at event
248
                    $birth_date = $record->getBirthDate();
249
                    // Can't use getDeathDate(), as this also gives BURI/CREM events, which
250
                    // wouldn't give the correct "days after death" result for people with
251
                    // no DEAT.
252
                    $death_event = $record->facts(['DEAT'])->first();
253
                    if ($death_event instanceof Fact) {
254
                        $death_date = $death_event->date();
255
                    } else {
256
                        $death_date = new Date('');
257
                    }
258
                    $ageText = '';
259
                    if ($fact === 'DEAT' || (Date::compare($date, $death_date) <= 0 || !$record->isDead())) {
260
                        // Before death, print age
261
                        $age = Date::getAgeGedcom($birth_date, $date);
262
                        // Only show calculated age if it differs from recorded age
263
                        if ($age !== '' && $age !== '0d') {
264
                            if ($fact_age !== '' && $fact_age !== $age) {
265
                                $ageText = '(' . I18N::translate('Age') . ' ' . FunctionsDate::getAgeAtEvent($age) . ')';
266
                            } elseif ($fact_age === '' && $husb_age === '' && $wife_age === '') {
267
                                $ageText = '(' . I18N::translate('Age') . ' ' . FunctionsDate::getAgeAtEvent($age) . ')';
268
                            } elseif ($husb_age !== '' && $husb_age !== $age && $record->sex() === 'M') {
269
                                $ageText = '(' . I18N::translate('Age') . ' ' . FunctionsDate::getAgeAtEvent($age) . ')';
270
                            } elseif ($wife_age !== '' && $wife_age !== $age && $record->sex() === 'F') {
271
                                $ageText = '(' . I18N::translate('Age') . ' ' . FunctionsDate::getAgeAtEvent($age) . ')';
272
                            }
273
                        }
274
                    }
275
                    if ($fact !== 'DEAT' && Date::compare($date, $death_date) >= 0) {
276
                        // After death, print time since death
277
                        $age = FunctionsDate::getAgeAtEvent(Date::getAgeGedcom($death_date, $date));
278
                        if ($age !== '') {
279
                            if (Date::getAgeGedcom($death_date, $date) === '0d') {
280
                                $ageText = '(' . I18N::translate('on the date of death') . ')';
281
                            } else {
282
                                $ageText = '(' . $age . ' ' . I18N::translate('after death') . ')';
283
                                // Family events which occur after death are probably errors
284
                                if ($event->record() instanceof Family) {
285
                                    $ageText .= view('icons/warning');
286
                                }
287
                            }
288
                        }
289
                    }
290
                    if ($ageText) {
291
                        $html .= ' <span class="age">' . $ageText . '</span>';
292
                    }
293
                }
294
            }
295
        }
296
        // print gedcom ages
297
        $age_labels = [
298
            I18N::translate('Age')     => $fact_age,
299
            I18N::translate('Husband') => $husb_age,
300
            I18N::translate('Wife')    => $wife_age,
301
        ];
302
303
        foreach ($age_labels as $label => $age) {
304
            if ($age !== '') {
305
                $html .= ' <span class="label">' . $label . ':</span> <span class="age">' . FunctionsDate::getAgeAtEvent($age) . '</span>';
306
            }
307
        }
308
309
        return $html;
310
    }
311
312
    /**
313
     * print fact PLACe TEMPle STATus
314
     *
315
     * @param Fact $event       gedcom fact record
316
     * @param bool $anchor      to print a link to placelist
317
     * @param bool $sub_records to print place subrecords
318
     * @param bool $lds         to print LDS TEMPle and STATus
319
     *
320
     * @return string HTML
321
     */
322
    public static function formatFactPlace(Fact $event, $anchor = false, $sub_records = false, $lds = false): string
323
    {
324
        $tree = $event->record()->tree();
325
326
        if ($anchor) {
327
            // Show the full place name, for facts/events tab
328
            $html = $event->place()->fullName(true);
329
        } else {
330
            // Abbreviate the place name, for chart boxes
331
            return $event->place()->shortName();
332
        }
333
334
        if ($sub_records) {
335
            $placerec = Functions::getSubRecord(2, '2 PLAC', $event->gedcom());
336
            if ($placerec !== '') {
337
                if (preg_match_all('/\n3 (?:_HEB|ROMN) (.+)/', $placerec, $matches)) {
338
                    foreach ($matches[1] as $match) {
339
                        $wt_place = new Place($match, $tree);
340
                        $html     .= ' - ' . $wt_place->fullName();
341
                    }
342
                }
343
                $map_lati = '';
344
                $cts      = preg_match('/\d LATI (.*)/', $placerec, $match);
345
                if ($cts > 0) {
346
                    $map_lati = $match[1];
347
                    $html     .= '<br><span class="label">' . I18N::translate('Latitude') . ': </span>' . $map_lati;
348
                }
349
                $map_long = '';
350
                $cts      = preg_match('/\d LONG (.*)/', $placerec, $match);
351
                if ($cts > 0) {
352
                    $map_long = $match[1];
353
                    $html     .= ' <span class="label">' . I18N::translate('Longitude') . ': </span>' . $map_long;
354
                }
355
                if ($map_lati && $map_long) {
356
                    $map_lati = trim(strtr($map_lati, 'NSEW,�', ' - -. ')); // S5,6789 ==> -5.6789
357
                    $map_long = trim(strtr($map_long, 'NSEW,�', ' - -. ')); // E3.456� ==> 3.456
358
359
                    $html .= '<a href="https://maps.google.com/maps?q=' . e($map_lati) . ',' . e($map_long) . '" rel="nofollow" title="' . I18N::translate('Google Maps™') . '">' .
360
                        view('icons/google-maps') .
361
                        '<span class="sr-only">' . I18N::translate('Google Maps™') . '</span>' .
362
                        '</a>';
363
364
                    $html .= '<a href="https://www.bing.com/maps/?lvl=15&cp=' . e($map_lati) . '~' . e($map_long) . '" rel="nofollow" title="' . I18N::translate('Bing Maps™') . '">' .
365
                        view('icons/bing-maps') .
366
                        '<span class="sr-only">' . I18N::translate('Bing Maps™') . '</span>' .
367
                        '</a>';
368
369
                    $html .= '<a href="https://www.openstreetmap.org/#map=15/' . e($map_lati) . '/' . e($map_long) . '" rel="nofollow" title="' . I18N::translate('OpenStreetMap™') . '">' .
370
                        view('icons/openstreetmap') .
371
                        '<span class="sr-only">' . I18N::translate('OpenStreetMap™') . '</span>' .
372
                        '</a>';
373
                }
374
                if (preg_match('/\d NOTE (.*)/', $placerec, $match)) {
375
                    $html .= '<br>' . self::printFactNotes($tree, $placerec, 3);
376
                }
377
            }
378
        }
379
        if ($lds) {
380
            if (preg_match('/2 TEMP (.*)/', $event->gedcom(), $match)) {
381
                $html .= '<br>' . I18N::translate('LDS temple') . ': ' . GedcomCodeTemp::templeName($match[1]);
382
            }
383
            if (preg_match('/2 STAT (.*)/', $event->gedcom(), $match)) {
384
                $html .= '<br>' . I18N::translate('Status') . ': ' . GedcomCodeStat::statusName($match[1]);
385
                if (preg_match('/3 DATE (.*)/', $event->gedcom(), $match)) {
386
                    $date = new Date($match[1]);
387
                    $html .= ', ' . GedcomTag::getLabel('STAT:DATE') . ': ' . $date->display();
388
                }
389
            }
390
        }
391
392
        return $html;
393
    }
394
395
    /**
396
     * Check for facts that may exist only once for a certain record type.
397
     * If the fact already exists in the second array, delete it from the first one.
398
     *
399
     * @param string[]   $uniquefacts
400
     * @param Collection $recfacts
401
     *
402
     * @return string[]
403
     */
404
    public static function checkFactUnique(array $uniquefacts, Collection $recfacts): array
405
    {
406
        foreach ($recfacts as $factarray) {
407
            $fact = $factarray->getTag();
408
409
            $key = array_search($fact, $uniquefacts, true);
410
            if ($key !== false) {
411
                unset($uniquefacts[$key]);
412
            }
413
        }
414
415
        return $uniquefacts;
416
    }
417
418
    /**
419
     * Print a new fact box on details pages
420
     *
421
     * @param GedcomRecord $record    the person, family, source etc the fact will be added to
422
     * @param Collection   $usedfacts an array of facts already used in this record
423
     * @param string       $type      the type of record INDI, FAM, SOUR etc
424
     *
425
     * @return void
426
     */
427
    public static function printAddNewFact(GedcomRecord $record, Collection $usedfacts, $type): void
428
    {
429
        $tree = $record->tree();
430
431
        // -- Add from pick list
432
        switch ($type) {
433
            case Individual::RECORD_TYPE:
434
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
435
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
436
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('INDI_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
437
                break;
438
439
            case Family::RECORD_TYPE:
440
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
441
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
442
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('FAM_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
443
                break;
444
445
            case Source::RECORD_TYPE:
446
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
447
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
448
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('SOUR_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
449
                break;
450
451
            case Note::RECORD_TYPE:
452
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
453
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
454
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('NOTE_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
455
                break;
456
457
            case Repository::RECORD_TYPE:
458
                $addfacts    = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
459
                $uniquefacts = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
460
                $quickfacts  = preg_split('/[, ;:]+/', $tree->getPreference('REPO_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
461
                break;
462
463
            case Media::RECORD_TYPE:
464
                $addfacts    = ['NOTE'];
465
                $uniquefacts = [];
466
                $quickfacts  = [];
467
                break;
468
469
            case Submitter::RECORD_TYPE:
470
                $addfacts    = ['LANG', 'OBJE', 'NOTE', 'SHARED_NOTE'];
471
                $uniquefacts = ['ADDR', 'EMAIL', 'NAME', 'PHON', 'WWW'];
472
                $quickfacts  = [];
473
                break;
474
475
            case Submission::RECORD_TYPE:
476
                $addfacts    = ['NOTE', 'SHARED_NOTE'];
477
                $uniquefacts = ['FAMF', 'TEMP', 'ANCE', 'DESC', 'ORDI', 'SUBM'];
478
                $quickfacts  = [];
479
                break;
480
481
            case Header::RECORD_TYPE:
482
                $addfacts    = [];
483
                $uniquefacts = ['COPR', 'LANG', 'SUBM'];
484
                $quickfacts  = [];
485
                break;
486
            default:
487
                return;
488
        }
489
        $addfacts            = array_merge(self::checkFactUnique($uniquefacts, $usedfacts), $addfacts);
490
        $quickfacts          = array_intersect($quickfacts, $addfacts);
491
        $translated_addfacts = [];
492
        foreach ($addfacts as $addfact) {
493
            $translated_addfacts[$addfact] = GedcomTag::getLabel($addfact);
494
        }
495
        uasort($translated_addfacts, static function (string $x, string $y): int {
496
            return I18N::strcasecmp(I18N::translate($x), I18N::translate($y));
497
        });
498
499
        echo view('edit/add-fact-row', [
500
            'add_facts'   => $translated_addfacts,
501
            'quick_facts' => $quickfacts,
502
            'record'      => $record,
503
            'tree'        => $tree,
504
        ]);
505
    }
506
}
507