CertificateDataService::linkedNotes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 1
dl 0
loc 11
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Certificates
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2021-2022, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Certificates\Services;
16
17
use Fisharebest\Webtrees\Gedcom;
18
use Fisharebest\Webtrees\GedcomRecord;
19
use Fisharebest\Webtrees\Registry;
20
use Fisharebest\Webtrees\Source;
21
use Illuminate\Database\Capsule\Manager as DB;
22
use Illuminate\Support\Collection;
23
use MyArtJaub\Webtrees\Module\Certificates\Model\Certificate;
24
use Generator;
25
26
/**
27
 * Service for accessing genealogical data linked to a certificate file.
28
 */
29
class CertificateDataService
30
{
31
    /**
32
     * Find individuals linked to a certificate.
33
     *
34
     * {@internal Ideally, the underscore should be escaped in the WHERE clause,
35
     * but does not work with Sqlite if no default escape has been defined}
36
     *
37
     * @param Certificate $certificate
38
     * @return Collection<\Fisharebest\Webtrees\Individual>
39
     */
40
    public function linkedIndividuals(Certificate $certificate): Collection
41
    {
42
        $tree = $certificate->tree();
43
        return DB::table('individuals')
44
            ->where('i_file', '=', $tree->id())
45
            ->where('i_gedcom', 'like', '% _ACT ' . $this->escapedSqlPath($certificate) . '%')
46
            ->select(['individuals.*'])
47
            ->get()
48
            ->map(Registry::individualFactory()->mapper($tree))
49
            ->filter(GedcomRecord::accessFilter());
50
    }
51
52
    /**
53
     * Find families linked to a certificate.
54
     *
55
     * {@internal Ideally, the underscore should be escaped in the WHERE clause,
56
     * but does not work with Sqlite if no default escape has been defined}
57
     *
58
     * @param Certificate $certificate
59
     * @return Collection<\Fisharebest\Webtrees\Family>
60
     */
61
    public function linkedFamilies(Certificate $certificate): Collection
62
    {
63
        $tree = $certificate->tree();
64
        return DB::table('families')
65
            ->where('f_file', '=', $tree->id())
66
            ->where('f_gedcom', 'like', '% _ACT ' . $this->escapedSqlPath($certificate) . '%')
67
            ->select(['families.*'])
68
            ->get()
69
            ->map(Registry::familyFactory()->mapper($tree))
70
            ->filter(GedcomRecord::accessFilter());
71
    }
72
73
    /**
74
     * Find media objects linked to a certificate.
75
     *
76
     * {@internal Ideally, the underscore should be escaped in the WHERE clause,
77
     * but does not work with Sqlite if no default escape has been defined}
78
     *
79
     * @param Certificate $certificate
80
     * @return Collection<\Fisharebest\Webtrees\Media>
81
     */
82
    public function linkedMedias(Certificate $certificate): Collection
83
    {
84
        $tree = $certificate->tree();
85
        return DB::table('media')
86
            ->where('m_file', '=', $tree->id())
87
            ->where('m_gedcom', 'like', '% _ACT ' . $this->escapedSqlPath($certificate) . '%')
88
            ->select(['media.*'])
89
            ->get()
90
            ->map(Registry::mediaFactory()->mapper($tree))
91
            ->filter(GedcomRecord::accessFilter());
92
    }
93
94
    /**
95
     * Find notes linked to a certificate.
96
     *
97
     * {@internal Ideally, the underscore should be escaped in the WHERE clause,
98
     * but does not work with Sqlite if no default escape has been defined}
99
     *
100
     * @param Certificate $certificate
101
     * @return Collection<\Fisharebest\Webtrees\Note>
102
     */
103
    public function linkedNotes(Certificate $certificate): Collection
104
    {
105
        $tree = $certificate->tree();
106
        return DB::table('other')
107
            ->where('o_file', '=', $tree->id())
108
            ->where('o_type', '=', 'NOTE')
109
            ->where('o_gedcom', 'like', '% _ACT ' . $this->escapedSqlPath($certificate) . '%')
110
            ->select(['other.*'])
111
            ->get()
112
            ->map(Registry::noteFactory()->mapper($tree))
113
            ->filter(GedcomRecord::accessFilter());
114
    }
115
116
    /**
117
     * Return an escaped string to be used in SQL LIKE comparisons.
118
     * This would not work well for Sqlite, if the escape character is not defined.
119
     *
120
     * @param Certificate $certificate
121
     * @return string
122
     */
123
    protected function escapedSqlPath(Certificate $certificate): string
124
    {
125
        return str_replace(array('\\', '%', '_'), array('\\\\', '\\%', '\\_'), $certificate->gedcomPath());
126
    }
127
128
    /**
129
     * Find a source linked to a citation where a certificate file is referenced.
130
     *
131
     * @param Certificate $certificate
132
     * @return Source|NULL
133
     */
134
    public function oneLinkedSource(Certificate $certificate): ?Source
135
    {
136
        $regex_query = preg_quote($certificate->gedcomPath(), '/');
137
        $regex_pattern = '/[1-9] SOUR @(' . Gedcom::REGEX_XREF . ')@(?:\n[2-9]\s(?:(?!SOUR)\w+)\s.*)*\n[2-9] _ACT ' . $regex_query . '/i'; //phpcs:ignore Generic.Files.LineLength.TooLong
138
139
        foreach ($this->linkedRecordsLists($certificate) as $linked_records) {
140
            foreach ($linked_records as $gedcom_record) {
141
                foreach ($gedcom_record->facts() as $fact) {
142
                    if (preg_match_all($regex_pattern, $fact->gedcom(), $matches, PREG_SET_ORDER) >= 1) {
143
                        foreach ($matches as $match) {
144
                            $source = Registry::sourceFactory()->make($match[1], $certificate->tree());
145
                            if ($source !== null && $source->canShowName()) {
146
                                return $source;
147
                            }
148
                        }
149
                    }
150
                }
151
            }
152
        }
153
154
        return null;
155
    }
156
157
    /**
158
     * Yield lists of gedcom records linked to a certificate.
159
     *
160
     * @param Certificate $certificate
161
     * @return Generator<int, Collection<GedcomRecord>, mixed, void>
162
     * @psalm-suppress InvalidReturnType
163
     */
164
    protected function linkedRecordsLists(Certificate $certificate): Generator
165
    {
166
        yield $this->linkedIndividuals($certificate);
167
        yield $this->linkedFamilies($certificate);
168
        yield $this->linkedMedias($certificate);
169
        yield $this->linkedNotes($certificate);
170
    }
171
}
172