xref: /webtrees/app/Note.php (revision 86c75e30decf65b2ee2190ca2847e42271e795ee)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2019 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees;
19
20use Illuminate\Database\Capsule\Manager as DB;
21use Illuminate\Support\Str;
22
23/**
24 * A GEDCOM note (NOTE) object.
25 */
26class Note extends GedcomRecord
27{
28    public const RECORD_TYPE = 'NOTE';
29
30    protected const ROUTE_NAME = 'note';
31
32    /**
33     * Get an instance of a note object. For single records,
34     * we just receive the XREF. For bulk records (such as lists
35     * and search results) we can receive the GEDCOM data as well.
36     *
37     * @param string      $xref
38     * @param Tree        $tree
39     * @param string|null $gedcom
40     *
41     * @throws \Exception
42     *
43     * @return Note|null
44     */
45    public static function getInstance(string $xref, Tree $tree, string $gedcom = null)
46    {
47        $record = parent::getInstance($xref, $tree, $gedcom);
48
49        if ($record instanceof Note) {
50            return $record;
51        }
52
53        return null;
54    }
55
56    /**
57     * Get the text contents of the note
58     *
59     * @return string
60     */
61    public function getNote()
62    {
63        if (preg_match('/^0 @' . Gedcom::REGEX_XREF . '@ NOTE ?(.*(?:\n1 CONT ?.*)*)/', $this->gedcom . $this->pending, $match)) {
64            return preg_replace("/\n1 CONT ?/", "\n", $match[1]);
65        }
66
67        return '';
68    }
69
70    /**
71     * Each object type may have its own special rules, and re-implement this function.
72     *
73     * @param int $access_level
74     *
75     * @return bool
76     */
77    protected function canShowByType(int $access_level): bool
78    {
79        // Hide notes if they are attached to private records
80        $linked_ids = Database::prepare(
81            "SELECT l_from FROM `##link` WHERE l_to=? AND l_file=?"
82        )->execute([
83            $this->xref,
84            $this->tree->id(),
85        ])->fetchOneColumn();
86        foreach ($linked_ids as $linked_id) {
87            $linked_record = GedcomRecord::getInstance($linked_id, $this->tree);
88            if ($linked_record && !$linked_record->canShow($access_level)) {
89                return false;
90            }
91        }
92
93        // Apply default behaviour
94        return parent::canShowByType($access_level);
95    }
96
97    /**
98     * Generate a private version of this record
99     *
100     * @param int $access_level
101     *
102     * @return string
103     */
104    protected function createPrivateGedcomRecord(int $access_level): string
105    {
106        return '0 @' . $this->xref . '@ NOTE ' . I18N::translate('Private');
107    }
108
109    /**
110     * Fetch data from the database
111     *
112     * @param string $xref
113     * @param int    $tree_id
114     *
115     * @return null|string
116     */
117    protected static function fetchGedcomRecord(string $xref, int $tree_id)
118    {
119        return DB::table('other')
120            ->where('o_id', '=', $xref)
121            ->where('o_file', '=', $tree_id)
122            ->where('o_type', '=', self::RECORD_TYPE)
123            ->value('o_gedcom');
124    }
125
126    /**
127     * Create a name for this note - apply (and remove) markup, then take
128     * a maximum of 100 characters from the first line.
129     *
130     * @return void
131     */
132    public function extractNames()
133    {
134        $text = $this->getNote();
135
136        if ($text) {
137            switch ($this->tree()->getPreference('FORMAT_TEXT')) {
138                case 'markdown':
139                    $text = Filter::markdown($text, $this->tree());
140                    $text = strip_tags($text);
141                    $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
142                    break;
143            }
144
145            [$text] = explode("\n", $text);
146            $this->addName('NOTE', Str::limit($text, 100, I18N::translate('…')), $this->gedcom());
147        }
148    }
149}
150