Passed
Push — 1.7 ( d4fad9...973f3f )
by Greg
08:11
created

autocomplete.php (39 issues)

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
 */
16
namespace Fisharebest\Webtrees;
17
18
/**
19
 * Defined in session.php
20
 *
21
 * @global Tree   $WT_TREE
22
 */
23
global $WT_TREE;
24
25
define('WT_SCRIPT_NAME', 'autocomplete.php');
26
require './includes/session.php';
27
28
header('Content-Type: text/plain; charset=UTF-8');
29
30
$term = Filter::get('term'); // we can search on '"><& etc.
31
$type = Filter::get('field');
32
33
switch ($type) {
34
    case 'ASSO': // Associates of an individuals, whose name contains the search terms
35
        $data = array();
36
        // Fetch all data, regardless of privacy
37
        $rows = Database::prepare(
38
        "SELECT 'INDI' AS type, i_id AS xref, i_gedcom AS gedcom, n_full" .
39
        " FROM `##individuals`" .
40
        " JOIN `##name` ON i_id = n_id AND i_file = n_file" .
41
        " WHERE (n_full LIKE CONCAT('%', REPLACE(:term_1, ' ', '%'), '%') OR n_surn LIKE CONCAT('%', REPLACE(:term_2, ' ', '%'), '%')) AND i_file = :tree_id" .
42
        " ORDER BY n_full COLLATE :collate"
43
        )->execute(array(
44
            'term_1'  => $term,
45
            'term_2'  => $term,
46
            'tree_id' => $WT_TREE->getTreeId(),
47
            'collate' => I18N::collation(),
48
        ))->fetchAll();
49
50
        // Filter for privacy and whether they could be alive at the right time
51
        $event_date = Filter::get('extra');
52
        $date       = new Date($event_date);
53
        $event_jd   = $date->julianDay();
54
        foreach ($rows as $row) {
55
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
56
            if ($person->canShow()) {
57
                if ($event_jd) {
58
                    // Exclude individuals who were born after the event.
59
                    $person_birth_jd = $person->getEstimatedBirthDate()->minimumJulianDay();
0 ignored issues
show
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\Repository. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\Note. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\Media. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\Family. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\Source. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedBirthDate() does not exist on Fisharebest\Webtrees\GedcomRecord. It seems like you code against a sub-type of Fisharebest\Webtrees\GedcomRecord such as Fisharebest\Webtrees\Individual. ( Ignorable by Annotation )

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

59
                    $person_birth_jd = $person->/** @scrutinizer ignore-call */ getEstimatedBirthDate()->minimumJulianDay();
Loading history...
60
                    if ($person_birth_jd && $person_birth_jd > $event_jd) {
61
                        continue;
62
                    }
63
                    // Exclude individuals who died before the event.
64
                    $person_death_jd = $person->getEstimatedDeathDate()->maximumJulianDay();
0 ignored issues
show
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\Repository. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\Media. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\GedcomRecord. It seems like you code against a sub-type of Fisharebest\Webtrees\GedcomRecord such as Fisharebest\Webtrees\Individual. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();
Loading history...
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\Source. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\Note. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getEstimatedDeathDate() does not exist on Fisharebest\Webtrees\Family. ( Ignorable by Annotation )

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

64
                    $person_death_jd = $person->/** @scrutinizer ignore-call */ getEstimatedDeathDate()->maximumJulianDay();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
                    if ($person_death_jd && $person_death_jd < $event_jd) {
66
                        continue;
67
                    }
68
                }
69
                // Add the age (if we have it) or the lifespan (if we do not).
70
                $label = $person->getFullName();
71
                if ($event_jd && $person->getBirthDate()->isOK()) {
0 ignored issues
show
The method getBirthDate() does not exist on Fisharebest\Webtrees\Media. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getBirthDate() does not exist on Fisharebest\Webtrees\Source. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getBirthDate() does not exist on Fisharebest\Webtrees\Repository. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getBirthDate() does not exist on Fisharebest\Webtrees\GedcomRecord. It seems like you code against a sub-type of Fisharebest\Webtrees\GedcomRecord such as Fisharebest\Webtrees\Individual. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {
Loading history...
The method getBirthDate() does not exist on Fisharebest\Webtrees\Family. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getBirthDate() does not exist on Fisharebest\Webtrees\Note. ( Ignorable by Annotation )

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

71
                if ($event_jd && $person->/** @scrutinizer ignore-call */ getBirthDate()->isOK()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
72
                    $label .= ', <span class="age">(' . I18N::translate('Age') . ' ' . Date::getAge($person->getBirthDate(), $date, 0) . ')</span>';
73
                } else {
74
                    $label .= ', <i>' . $person->getLifeSpan() . '</i>';
0 ignored issues
show
The method getLifeSpan() does not exist on Fisharebest\Webtrees\Media. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getLifeSpan() does not exist on Fisharebest\Webtrees\Repository. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getLifeSpan() does not exist on Fisharebest\Webtrees\Source. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getLifeSpan() does not exist on Fisharebest\Webtrees\GedcomRecord. It seems like you code against a sub-type of Fisharebest\Webtrees\GedcomRecord such as Fisharebest\Webtrees\Individual. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';
Loading history...
The method getLifeSpan() does not exist on Fisharebest\Webtrees\Family. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getLifeSpan() does not exist on Fisharebest\Webtrees\Note. ( Ignorable by Annotation )

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

74
                    $label .= ', <i>' . $person->/** @scrutinizer ignore-call */ getLifeSpan() . '</i>';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
75
                }
76
                $data[$row->xref] = array('value' => $row->xref, 'label' => $label);
77
            }
78
        }
79
        echo json_encode($data);
80
81
        return;
82
83
    case 'CEME': // Cemetery fields, that contain the search term
84
        $data = array();
85
        // Fetch all data, regardless of privacy
86
        $rows = Database::prepare(
87
        "SELECT i_id AS xref, i_gedcom AS gedcom" .
88
        " FROM `##individuals`" .
89
        " WHERE i_gedcom LIKE '%\n2 CEME %' AND i_file = :tree_id" .
90
        " ORDER BY SUBSTRING_INDEX(i_gedcom, '\n2 CEME ', -1) COLLATE :collation"
91
        )->execute(array(
92
            'tree_id'   => $WT_TREE->getTreeId(),
93
            'collation' => I18N::collation(),
94
        ))->fetchAll();
95
        // Filter for privacy
96
        foreach ($rows as $row) {
97
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
98
            if (preg_match('/\n2 CEME (.*' . preg_quote($term, '/') . '.*)/i', $person->getGedcom(), $match)) {
0 ignored issues
show
It seems like $term can also be of type null; however, parameter $str of preg_quote() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

98
            if (preg_match('/\n2 CEME (.*' . preg_quote(/** @scrutinizer ignore-type */ $term, '/') . '.*)/i', $person->getGedcom(), $match)) {
Loading history...
99
                if (!in_array($match[1], $data)) {
100
                    $data[] = $match[1];
101
                }
102
            }
103
        }
104
        echo json_encode($data);
105
106
        return;
107
108
    case 'FAM': // Families, whose name contains the search terms
109
        $data = array();
110
        // Fetch all data, regardless of privacy
111
        $rows = get_FAM_rows($WT_TREE, $term);
112
        // Filter for privacy
113
        foreach ($rows as $row) {
114
            $family = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
115
            if ($family->canShowName()) {
116
                $marriage_year = $family->getMarriageYear();
0 ignored issues
show
The method getMarriageYear() does not exist on Fisharebest\Webtrees\Repository. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getMarriageYear() does not exist on Fisharebest\Webtrees\Media. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getMarriageYear() does not exist on Fisharebest\Webtrees\Note. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getMarriageYear() does not exist on Fisharebest\Webtrees\Source. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getMarriageYear() does not exist on Fisharebest\Webtrees\Individual. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getMarriageYear() does not exist on Fisharebest\Webtrees\GedcomRecord. It seems like you code against a sub-type of Fisharebest\Webtrees\GedcomRecord such as Fisharebest\Webtrees\Family. ( Ignorable by Annotation )

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

116
                /** @scrutinizer ignore-call */ 
117
                $marriage_year = $family->getMarriageYear();
Loading history...
117
                if ($marriage_year) {
118
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', <i>' . $marriage_year . '</i>');
119
                } else {
120
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName());
121
                }
122
            }
123
        }
124
        echo json_encode($data);
125
126
        return;
127
128
    case 'GIVN': // Given names, that start with the search term
129
        // Do not filter by privacy. Given names on their own do not identify individuals.
130
        echo json_encode(
131
        Database::prepare(
132
            "SELECT DISTINCT n_givn" .
133
            " FROM `##name`" .
134
            " WHERE n_givn LIKE CONCAT(:term, '%') AND n_file = :tree_id" .
135
            " ORDER BY n_givn COLLATE :collation"
136
        )->execute(array(
137
            'term'      => $term,
138
            'tree_id'   => $WT_TREE->getTreeId(),
139
            'collation' => I18N::collation(),
140
        ))->fetchOneColumn()
141
        );
142
143
        return;
144
145
    case 'INDI': // Individuals, whose name contains the search terms
146
        $data = array();
147
        // Fetch all data, regardless of privacy
148
        $rows = Database::prepare(
149
        "SELECT i_id AS xref, i_gedcom AS gedcom, n_full" .
150
        " FROM `##individuals`" .
151
        " JOIN `##name` ON i_id = n_id AND i_file = n_file" .
152
        " WHERE (n_full LIKE CONCAT('%', REPLACE(:term_1, ' ', '%'), '%') OR n_surn LIKE CONCAT('%', REPLACE(:term_2, ' ', '%'), '%')) AND i_file = :tree_id" .
153
        " ORDER BY n_full COLLATE :collation"
154
        )->execute(array(
155
            'term_1'    => $term,
156
            'term_2'    => $term,
157
            'tree_id'   => $WT_TREE->getTreeId(),
158
            'collation' => I18N::collation(),
159
        ))->fetchAll();
160
        // Filter for privacy
161
        foreach ($rows as $row) {
162
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
163
            if ($person->canShowName()) {
164
                $data[] = array('value' => $row->xref, 'label' => str_replace(array('@N.N.', '@P.N.'), array(I18N::translateContext('Unknown surname', '…'), I18N::translateContext('Unknown given name', '…')), $row->n_full) . ', <i>' . $person->getLifeSpan() . '</i>');
165
            }
166
        }
167
        echo json_encode($data);
168
169
        return;
170
171
    case 'NOTE': // Notes which contain the search terms
172
        $data = array();
173
        // Fetch all data, regardless of privacy
174
        $rows = get_NOTE_rows($WT_TREE, $term);
175
        // Filter for privacy
176
        foreach ($rows as $row) {
177
            $note = Note::getInstance($row->xref, $WT_TREE, $row->gedcom);
178
            if ($note->canShowName()) {
179
                $data[] = array('value' => $note->getXref(), 'label' => $note->getFullName());
180
            }
181
        }
182
        echo json_encode($data);
183
184
        return;
185
186
    case 'OBJE':
187
        $data = array();
188
        // Fetch all data, regardless of privacy
189
        $rows = get_OBJE_rows($WT_TREE, $term);
190
        // Filter for privacy
191
        foreach ($rows as $row) {
192
            $media = Media::getInstance($row->xref, $WT_TREE, $row->gedcom);
193
            if ($media->canShowName()) {
194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());
0 ignored issues
show
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\Source. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\Family. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\Individual. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\GedcomRecord. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\Repository. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
The method getHtmlUrlDirect() does not exist on Fisharebest\Webtrees\Note. Did you maybe mean getHtmlUrl()? ( Ignorable by Annotation )

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

194
                $data[] = array('value' => $row->xref, 'label' => '<img src="' . $media->/** @scrutinizer ignore-call */ getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
195
            }
196
        }
197
        echo json_encode($data);
198
199
        return;
200
201
    case 'PLAC': // Place names (with hierarchy), that include the search term
202
        // Do not filter by privacy. Place names on their own do not identify individuals.
203
        $data = array();
204
        foreach (Place::findPlaces($term, $WT_TREE) as $place) {
205
            $data[] = $place->getGedcomName();
206
        }
207
        if (!$data && $WT_TREE->getPreference('GEONAMES_ACCOUNT')) {
208
            // No place found? Use an external gazetteer
209
            $url =
210
            "http://api.geonames.org/searchJSON" .
211
            "?name_startsWith=" . urlencode($term) .
0 ignored issues
show
It seems like $term can also be of type null; however, parameter $string of urlencode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

211
            "?name_startsWith=" . urlencode(/** @scrutinizer ignore-type */ $term) .
Loading history...
212
            "&lang=" . WT_LOCALE .
213
            "&fcode=CMTY&fcode=ADM4&fcode=PPL&fcode=PPLA&fcode=PPLC" .
214
            "&style=full" .
215
            "&username=" . $WT_TREE->getPreference('GEONAMES_ACCOUNT');
216
            // try to use curl when file_get_contents not allowed
217
            if (ini_get('allow_url_fopen')) {
218
                $json = file_get_contents($url);
219
            } elseif (function_exists('curl_init')) {
220
                $ch = curl_init();
221
                curl_setopt($ch, CURLOPT_URL, $url);
222
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
223
                $json = curl_exec($ch);
224
                curl_close($ch);
225
            } else {
226
                return $data;
227
            }
228
            $places = json_decode($json, true);
0 ignored issues
show
It seems like $json can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

228
            $places = json_decode(/** @scrutinizer ignore-type */ $json, true);
Loading history...
229
            if (isset($places['geonames']) && is_array($places['geonames'])) {
230
                foreach ($places['geonames'] as $k => $place) {
231
                    $data[] = $place['name'] . ', ' . $place['adminName2'] . ', ' . $place['adminName1'] . ', ' . $place['countryName'];
232
                }
233
            }
234
        }
235
        echo json_encode($data);
236
237
        return;
238
239
    case 'PLAC2': // Place names (without hierarchy), that include the search term
240
        // Do not filter by privacy. Place names on their own do not identify individuals.
241
        echo json_encode(
242
        Database::prepare(
243
            "SELECT p_place" .
244
            " FROM `##places`" .
245
            " WHERE p_place LIKE CONCAT('%', :term, '%') AND p_file = :tree_id" .
246
            " ORDER BY p_place COLLATE :collation"
247
        )->execute(array(
248
            'term'      => $term,
249
            'tree_id'   => $WT_TREE->getTreeId(),
250
            'collation' => I18N::collation(),
251
        ))->fetchOneColumn()
252
        );
253
254
        return;
255
256
    case 'REPO': // Repositories, that include the search terms
257
        $data = array();
258
        // Fetch all data, regardless of privacy
259
        $rows = get_REPO_rows($WT_TREE, $term);
260
        // Filter for privacy
261
        foreach ($rows as $row) {
262
            $record = Repository::getInstance($row->xref, $WT_TREE, $row->gedcom);
263
            if ($record->canShowName()) {
264
                foreach ($record->getFacts('NAME') as $fact) {
265
                    $data[] = array('value' => $record->getXref(), 'label' => $fact->getValue());
266
                }
267
            }
268
        }
269
        echo json_encode($data);
270
271
        return;
272
273
    case 'REPO_NAME': // Repository names, that include the search terms
274
        $data = array();
275
        // Fetch all data, regardless of privacy
276
        $rows = get_REPO_rows($WT_TREE, $term);
277
        // Filter for privacy
278
        foreach ($rows as $row) {
279
            $record = Repository::getInstance($row->xref, $WT_TREE, $row->gedcom);
280
            if ($record->canShowName()) {
281
                $data[] = strip_tags($record->getFullName());
282
            }
283
        }
284
        echo json_encode($data);
285
286
        return;
287
288
    case 'SOUR': // Sources, that include the search terms
289
        $data = array();
290
        // Fetch all data, regardless of privacy
291
        $rows = get_SOUR_rows($WT_TREE, $term);
292
        // Filter for privacy
293
        foreach ($rows as $row) {
294
            $record = Source::getInstance($row->xref, $WT_TREE, $row->gedcom);
295
            if ($record->canShowName()) {
296
                foreach ($record->getFacts('TITL') as $fact) {
297
                    $data[] = array('value' => $record->getXref(), 'label' => $fact->getValue());
298
                }
299
            }
300
        }
301
        echo json_encode($data);
302
303
        return;
304
305
    case 'PAGE': // Citation details, for a given source, that contain the search term
306
        $data = array();
307
        $sid  = Filter::get('extra', WT_REGEX_XREF);
308
        // Fetch all data, regardless of privacy
309
        $rows = Database::prepare(
310
        "SELECT i_id AS xref, i_gedcom AS gedcom" .
311
        " FROM `##individuals`" .
312
        " WHERE i_gedcom LIKE CONCAT('%\n_ SOUR @', :xref, '@%', REPLACE(:term, ' ', '%'), '%') AND i_file = :tree_id"
313
        )->execute(array(
314
            'xref'    => $sid,
315
            'term'    => $term,
316
            'tree_id' => $WT_TREE->getTreeId(),
317
        ))->fetchAll();
318
        // Filter for privacy
319
        foreach ($rows as $row) {
320
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
321
            if (preg_match('/\n1 SOUR @' . $sid . '@(?:\n[2-9].*)*\n2 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $person->getGedcom(), $match)) {
322
                $data[] = $match[1];
323
            }
324
            if (preg_match('/\n2 SOUR @' . $sid . '@(?:\n[3-9].*)*\n3 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $person->getGedcom(), $match)) {
325
                $data[] = $match[1];
326
            }
327
        }
328
        // Fetch all data, regardless of privacy
329
        $rows = Database::prepare(
330
        "SELECT f_id AS xref, f_gedcom AS gedcom" .
331
        " FROM `##families`" .
332
        " WHERE f_gedcom LIKE CONCAT('%\n_ SOUR @', :xref, '@%', REPLACE(:term, ' ', '%'), '%') AND f_file = :tree_id"
333
        )->execute(array(
334
            'xref'    => $sid,
335
            'term'    => $term,
336
            'tree_id' => $WT_TREE->getTreeId(),
337
        ))->fetchAll();
338
        // Filter for privacy
339
        foreach ($rows as $row) {
340
            $family = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
341
            if (preg_match('/\n1 SOUR @' . $sid . '@(?:\n[2-9].*)*\n2 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $family->getGedcom(), $match)) {
342
                $data[] = $match[1];
343
            }
344
            if (preg_match('/\n2 SOUR @' . $sid . '@(?:\n[3-9].*)*\n3 PAGE (.*' . str_replace(' ', '.+', preg_quote($term, '/')) . '.*)/i', $family->getGedcom(), $match)) {
345
                $data[] = $match[1];
346
            }
347
        }
348
        // array_unique() converts the keys from integer to string, which breaks
349
        // the JSON encoding - so need to call array_values() to convert them
350
        // back into integers.
351
        $data = array_values(array_unique($data));
352
        echo json_encode($data);
353
354
        return;
355
356
    case 'SOUR_TITL': // Source titles, that include the search terms
357
        $data = array();
358
        // Fetch all data, regardless of privacy
359
        $rows = Database::prepare(
360
        "SELECT s_id AS xref, s_gedcom AS gedcom, s_name" .
361
        " FROM `##sources`" .
362
        " WHERE s_name LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND s_file = :tree_id" .
363
        " ORDER BY s_name COLLATE :collation"
364
        )->execute(array(
365
            'term'      => $term,
366
            'tree_id'   => $WT_TREE->getTreeId(),
367
            'collation' => I18N::collation(),
368
        ))->fetchAll();
369
        // Filter for privacy
370
        foreach ($rows as $row) {
371
            $source = Source::getInstance($row->xref, $WT_TREE, $row->gedcom);
372
            if ($source->canShowName()) {
373
                $data[] = $row->s_name;
374
            }
375
        }
376
        echo json_encode($data);
377
378
        return;
379
380
    case 'SURN': // Surnames, that start with the search term
381
        // Do not filter by privacy. Surnames on their own do not identify individuals.
382
        echo json_encode(
383
        Database::prepare(
384
            "SELECT DISTINCT n_surname" .
385
            " FROM `##name`" .
386
            " WHERE n_surname LIKE CONCAT(:term, '%') AND n_file = :tree_id" .
387
            " ORDER BY n_surname COLLATE :collation"
388
        )->execute(array(
389
            'term'      => $term,
390
            'tree_id'   => $WT_TREE->getTreeId(),
391
            'collation' => I18N::collation(),
392
        ))->fetchOneColumn()
393
        );
394
395
        return;
396
397
    case 'IFSRO':
398
        $data = array();
399
        // Fetch all data, regardless of privacy
400
        $rows = get_INDI_rows($WT_TREE, $term);
401
        // Filter for privacy
402
        foreach ($rows as $row) {
403
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
404
            if ($person->canShowName()) {
405
                $data[] = array('value' => $person->getXref(), 'label' => str_replace(array('@N.N.', '@P.N.'), array(I18N::translateContext('Unknown surname', '…'), I18N::translateContext('Unknown given name', '…')), $row->n_full) . ', <i>' . $person->getLifeSpan() . '</i>');
406
            }
407
        }
408
        // Fetch all data, regardless of privacy
409
        $rows = get_SOUR_rows($WT_TREE, $term);
410
        // Filter for privacy
411
        foreach ($rows as $row) {
412
            $source = Source::getInstance($row->xref, $WT_TREE, $row->gedcom);
413
            if ($source->canShowName()) {
414
                $data[] = array('value' => $source->getXref(), 'label' => $source->getFullName());
415
            }
416
        }
417
        // Fetch all data, regardless of privacy
418
        $rows = get_REPO_rows($WT_TREE, $term);
419
        // Filter for privacy
420
        foreach ($rows as $row) {
421
            $repository = Repository::getInstance($row->xref, $WT_TREE, $row->gedcom);
422
            if ($repository->canShowName()) {
423
                $data[] = array('value' => $repository->getXref(), 'label' => $repository->getFullName());
424
            }
425
        }
426
        // Fetch all data, regardless of privacy
427
        $rows = get_OBJE_rows($WT_TREE, $term);
428
        // Filter for privacy
429
        foreach ($rows as $row) {
430
            $media = Media::getInstance($row->xref, $WT_TREE, $row->gedcom);
431
            if ($media->canShowName()) {
432
                $data[] = array('value' => $media->getXref(), 'label' => '<img src="' . $media->getHtmlUrlDirect() . '" width="25"> ' . $media->getFullName());
433
            }
434
        }
435
        // Fetch all data, regardless of privacy
436
        $rows = get_FAM_rows($WT_TREE, $term);
437
        // Filter for privacy
438
        foreach ($rows as $row) {
439
            $family = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
440
            if ($family->canShowName()) {
441
                $marriage_year = $family->getMarriageYear();
442
                if ($marriage_year) {
443
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', <i>' . $marriage_year . '</i>');
444
                } else {
445
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName());
446
                }
447
            }
448
        }
449
        // Fetch all data, regardless of privacy
450
        $rows = get_NOTE_rows($WT_TREE, $term);
451
        // Filter for privacy
452
        foreach ($rows as $row) {
453
            $note = Note::getInstance($row->xref, $WT_TREE, $row->gedcom);
454
            if ($note->canShowName()) {
455
                $data[] = array('value' => $note->getXref(), 'label' => $note->getFullName());
456
            }
457
        }
458
        echo json_encode($data);
459
460
        return;
461
462
    case 'IFS':
463
        $data = array();
464
        // Fetch all data, regardless of privacy
465
        $rows = get_INDI_rows($WT_TREE, $term);
466
        // Filter for privacy
467
        foreach ($rows as $row) {
468
            $person = Individual::getInstance($row->xref, $WT_TREE, $row->gedcom);
469
            if ($person->canShowName()) {
470
                $data[] = array('value' => $person->getXref(), 'label' => str_replace(array('@N.N.', '@P.N.'), array(I18N::translateContext('Unknown surname', '…'), I18N::translateContext('Unknown given name', '…')), $row->n_full) . ', <i>' . $person->getLifeSpan() . '</i>');
471
            }
472
        }
473
        // Fetch all data, regardless of privacy
474
        $rows = get_SOUR_rows($WT_TREE, $term);
475
        // Filter for privacy
476
        foreach ($rows as $row) {
477
            $source = Source::getInstance($row->xref, $WT_TREE, $row->gedcom);
478
            if ($source->canShowName()) {
479
                $data[] = array('value' => $source->getXref(), 'label' => $source->getFullName());
480
            }
481
        }
482
        // Fetch all data, regardless of privacy
483
        $rows = get_FAM_rows($WT_TREE, $term);
484
        // Filter for privacy
485
        foreach ($rows as $row) {
486
            $family = Family::getInstance($row->xref, $WT_TREE, $row->gedcom);
487
            if ($family->canShowName()) {
488
                $marriage_year = $family->getMarriageYear();
489
                if ($marriage_year) {
490
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName() . ', <i>' . $marriage_year . '</i>');
491
                } else {
492
                    $data[] = array('value' => $family->getXref(), 'label' => $family->getFullName());
493
                }
494
            }
495
        }
496
        echo json_encode($data);
497
498
        return;
499
}
500
501
/**
502
 * Find family records from the database.
503
 *
504
 * @param Tree   $tree
505
 * @param string $term
506
 *
507
 * @return \stdClass[]
508
 */
509
function get_FAM_rows(Tree $tree, $term)
510
{
511
    return Database::prepare(
512
        "SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_gedcom AS gedcom, husb_name.n_sort, wife_name.n_sort" .
513
        " FROM `##families`" .
514
        " JOIN `##name` AS husb_name ON f_husb = husb_name.n_id AND f_file = husb_name.n_file" .
515
        " JOIN `##name` AS wife_name ON f_wife = wife_name.n_id AND f_file = wife_name.n_file" .
516
        " WHERE CONCAT(husb_name.n_full, ' ', wife_name.n_full) LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND f_file = :tree_id" .
517
        " AND husb_name.n_type <> '_MARNM' AND wife_name.n_type <> '_MARNM'" .
518
        " ORDER BY husb_name.n_sort, wife_name.n_sort COLLATE :collation"
519
    )->execute(array(
520
        'term'      => $term,
521
        'tree_id'   => $tree->getTreeId(),
522
        'collation' => I18N::collation(),
523
    ))->fetchAll();
524
}
525
526
/**
527
 * Find individual records from the database.
528
 *
529
 * @param Tree   $tree
530
 * @param string $term
531
 *
532
 * @return \stdClass[]
533
 */
534
function get_INDI_rows(Tree $tree, $term)
535
{
536
    return Database::prepare(
537
        "SELECT 'INDI' AS type, i_id AS xref, i_gedcom AS gedcom, n_full" .
538
        " FROM `##individuals`" .
539
        " JOIN `##name` ON i_id = n_id AND i_file = n_file" .
540
        " WHERE n_full LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND i_file = :tree_id ORDER BY n_full COLLATE :collation"
541
    )->execute(array(
542
        'term'      => $term,
543
        'tree_id'   => $tree->getTreeId(),
544
        'collation' => I18N::collation(),
545
    ))->fetchAll();
546
}
547
548
/**
549
 * Find note records from the database.
550
 *
551
 * @param Tree   $tree
552
 * @param string $term
553
 *
554
 * @return \stdClass[]
555
 */
556
function get_NOTE_rows(Tree $tree, $term)
557
{
558
    return Database::prepare(
559
        "SELECT o_id AS xref, o_gedcom AS gedcom" .
560
        " FROM `##other`" .
561
        " JOIN `##name` ON o_id = n_id AND o_file = n_file" .
562
        " WHERE o_gedcom LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND o_file = :tree_id AND o_type = 'NOTE'" .
563
        " ORDER BY n_full COLLATE :collation"
564
    )->execute(array(
565
        'term'      => $term,
566
        'tree_id'   => $tree->getTreeId(),
567
        'collation' => I18N::collation(),
568
    ))->fetchAll();
569
}
570
571
/**
572
 * Find media object records from the database.
573
 *
574
 * @param Tree   $tree
575
 * @param string $term
576
 *
577
 * @return \stdClass[]
578
 */
579
function get_OBJE_rows(Tree $tree, $term)
580
{
581
    return Database::prepare(
582
        "SELECT 'OBJE' AS type, m_id AS xref, m_gedcom AS gedcom" .
583
        " FROM `##media`" .
584
        " WHERE (m_titl LIKE CONCAT('%', REPLACE(:term_1, ' ', '%'), '%') OR m_id LIKE CONCAT('%', REPLACE(:term_2, ' ', '%'), '%')) AND m_file = :tree_id" .
585
        " ORDER BY m_titl COLLATE :collation"
586
    )->execute(array(
587
        'term_1'    => $term,
588
        'term_2'    => $term,
589
        'tree_id'   => $tree->getTreeId(),
590
        'collation' => I18N::collation(),
591
    ))->fetchAll();
592
}
593
594
/**
595
 * Find repository records from the database.
596
 *
597
 * @param Tree   $tree
598
 * @param string $term
599
 *
600
 * @return \stdClass[]
601
 */
602
function get_REPO_rows(Tree $tree, $term)
603
{
604
    return Database::prepare(
605
        "SELECT o_id AS xref, o_gedcom AS gedcom" .
606
        " FROM `##other`" .
607
        " JOIN `##name` ON o_id = n_id AND o_file = n_file" .
608
        " WHERE n_full LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND o_file = :tree_id AND o_type = 'REPO'" .
609
        " ORDER BY n_full COLLATE :collation"
610
    )->execute(array(
611
        'term'      => $term,
612
        'tree_id'   => $tree->getTreeId(),
613
        'collation' => I18N::collation(),
614
    ))->fetchAll();
615
}
616
617
/**
618
 * Find source records from the database.
619
 *
620
 * @param Tree   $tree
621
 * @param string $term
622
 *
623
 * @return \stdClass[]
624
 */
625
function get_SOUR_rows(Tree $tree, $term)
626
{
627
    return Database::prepare(
628
        "SELECT s_id AS xref, s_gedcom AS gedcom" .
629
        " FROM `##sources`" .
630
        " WHERE s_name LIKE CONCAT('%', REPLACE(:term, ' ', '%'), '%') AND s_file = :tree_id" .
631
        " ORDER BY s_name COLLATE :collation"
632
    )->execute(array(
633
        'term'      => $term,
634
        'tree_id'   => $tree->getTreeId(),
635
        'collation' => I18N::collation(),
636
    ))->fetchAll();
637
}
638