Passed
Push — feature/code-analysis ( e964aa...4fe35d )
by Jonathan
14:33
created

SourceStatusService   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 123
rs 10
c 0
b 0
f 0
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A sourceStatusForRecord() 0 15 3
A sourceStatusForFactsWithTags() 0 12 3
B sourceStatusForFact() 0 29 7
A sourceStatusForBirth() 0 3 1
A sourceStatusForMarriage() 0 4 1
A sourceStatusForDeath() 0 3 1
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage IsSourced
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2009-2022, Jonathan Jaubart
10
 * @license https://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\IsSourced\Services;
16
17
use Fisharebest\Webtrees\Date;
18
use Fisharebest\Webtrees\Fact;
19
use Fisharebest\Webtrees\Family;
20
use Fisharebest\Webtrees\Gedcom;
21
use Fisharebest\Webtrees\GedcomRecord;
22
use Fisharebest\Webtrees\Individual;
23
use MyArtJaub\Webtrees\Module\IsSourced\Data\FactSourceStatus;
24
use MyArtJaub\Webtrees\Module\IsSourced\Data\NullFactSourceStatus;
25
use MyArtJaub\Webtrees\Module\IsSourced\Data\SourceStatus;
26
27
/**
28
 * Service for computing the status of sources for records and facts.
29
 */
30
class SourceStatusService
31
{
32
    /**
33
     * Maximum timespan between the date of a source and the date of the event to consider the source precise.
34
     * Arbitrally set to approximately a year around the event date.
35
     *
36
     * @var int DATE_PRECISION_MARGIN
37
     */
38
    private const DATE_PRECISION_MARGIN = 180;
39
40
    /**
41
     * Return the status of source citations for a fact.
42
     *
43
     * @param Fact $fact
44
     * @return FactSourceStatus
45
     */
46
    public function sourceStatusForFact(Fact $fact): FactSourceStatus
47
    {
48
        $source_status = new FactSourceStatus();
49
50
        $date = $fact->date();
51
        $source_status
52
            ->setFactHasDate($date->isOK())
53
            ->setFactHasPreciseDate($date->qual1 === '' && $date->minimumJulianDay() === $date->maximumJulianDay());
54
55
        foreach ($fact->getCitations() as $citation) {
56
            $source_status
57
                ->setHasSource(true)
58
                ->addHasSupportingDocument(preg_match('/\n3 _ACT (?:.*)/', $citation) === 1);
59
60
            preg_match_all("/\n3 DATA(?:\n[4-9] .*)*\n4 DATE (.*)/", $citation, $date_matches, PREG_SET_ORDER);
61
            foreach ($date_matches as $date_match) {
62
                $source_date = new Date($date_match[1]);
63
                $source_status
64
                    ->addSourceHasDate($source_date->isOK())
65
                    ->addSourceMatchesFactDate($date->isOK() && $source_date->isOK()
66
                        && abs($source_date->julianDay() - $date->julianDay()) < self::DATE_PRECISION_MARGIN);
67
            }
68
69
            if ($source_status->isFullySourced()) {
70
                return $source_status;
71
            }
72
        }
73
74
        return $source_status;
75
    }
76
77
    /**
78
     * Return the status of sources for a Gedcom record.
79
     *
80
     * @param GedcomRecord $record
81
     * @return SourceStatus
82
     */
83
    public function sourceStatusForRecord(GedcomRecord $record): SourceStatus
84
    {
85
        $source_status = new SourceStatus();
86
87
        foreach ($record->facts(['SOUR']) as $source) {
88
            $source_status
89
                ->setHasSource(true)
90
                ->addHasSupportingDocument($source->attribute('_ACT') !== '');
91
92
            if ($source_status->isFullySourced()) {
93
                return $source_status;
94
            }
95
        }
96
97
        return $source_status;
98
    }
99
100
    /**
101
     * Return the status of source citations for a list of fact types associated with a record.
102
     *
103
     * @param GedcomRecord $record
104
     * @param string[] $tags
105
     * @return FactSourceStatus
106
     */
107
    public function sourceStatusForFactsWithTags(GedcomRecord $record, array $tags): FactSourceStatus
108
    {
109
        $source_status = new NullFactSourceStatus();
110
111
        foreach ($record->facts($tags) as $fact) {
112
            $source_status = $source_status->combineWith($this->sourceStatusForFact($fact));
113
            if ($source_status->isFullySourced()) {
114
                return $source_status;
115
            }
116
        }
117
118
        return $source_status;
119
    }
120
121
    /**
122
     * Return the status of source citations for an individual's birth events.
123
     *
124
     * @param Individual $individual
125
     * @return FactSourceStatus
126
     */
127
    public function sourceStatusForBirth(Individual $individual): FactSourceStatus
128
    {
129
        return $this->sourceStatusForFactsWithTags($individual, Gedcom::BIRTH_EVENTS);
130
    }
131
132
    /**
133
     * Return the status of source citations for an individual's death events.
134
     *
135
     * @param Individual $individual
136
     * @return FactSourceStatus
137
     */
138
    public function sourceStatusForDeath(Individual $individual): FactSourceStatus
139
    {
140
        return $this->sourceStatusForFactsWithTags($individual, Gedcom::DEATH_EVENTS);
141
    }
142
143
    /**
144
     * Return the status of source citations for a family's marriage events.
145
     *
146
     * @param Family $family
147
     * @return FactSourceStatus
148
     */
149
    public function sourceStatusForMarriage(Family $family): FactSourceStatus
150
    {
151
        $marr_events = [...Gedcom::MARRIAGE_EVENTS, 'MARC', 'MARL', 'MARS'];
152
        return $this->sourceStatusForFactsWithTags($family, $marr_events);
153
    }
154
}
155