1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace kalanis\kw_pedigree\Storage\MultiTable; |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
use kalanis\kw_mapper\MapperException; |
7
|
|
|
use kalanis\kw_mapper\Mappers\Shared\ForeignKey; |
8
|
|
|
use kalanis\kw_mapper\Search\Search; |
9
|
|
|
use kalanis\kw_pedigree\Interfaces\ISex; |
10
|
|
|
use kalanis\kw_pedigree\PedigreeException; |
11
|
|
|
use kalanis\kw_pedigree\Storage\AEntryAdapter; |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class EntryAdapter |
16
|
|
|
* @package kalanis\kw_pedigree\Storage\MultiTable |
17
|
|
|
*/ |
18
|
|
|
class EntryAdapter extends AEntryAdapter |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @param int|null $fatherId |
22
|
|
|
* @throws MapperException |
23
|
|
|
* @throws PedigreeException |
24
|
|
|
* @return bool|null |
25
|
|
|
*/ |
26
|
2 |
|
public function setFatherId(?int $fatherId): ?bool |
27
|
|
|
{ |
28
|
2 |
|
return $this->setParentId($fatherId, ISex::MALE); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @param int|null $motherId |
33
|
|
|
* @throws MapperException |
34
|
|
|
* @throws PedigreeException |
35
|
|
|
* @return bool|null |
36
|
|
|
*/ |
37
|
2 |
|
public function setMotherId(?int $motherId): ?bool |
38
|
|
|
{ |
39
|
2 |
|
return $this->setParentId($motherId, ISex::FEMALE); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @param int|null $parentId |
44
|
|
|
* @param string $sex |
45
|
|
|
* @throws MapperException |
46
|
|
|
* @throws PedigreeException |
47
|
|
|
* @return bool|null |
48
|
|
|
*/ |
49
|
2 |
|
protected function setParentId(?int $parentId, string $sex): ?bool |
50
|
|
|
{ |
51
|
2 |
|
$result = $this->parentLookup($sex); |
52
|
2 |
|
if (!empty($result) && !empty($parentId)) { |
53
|
|
|
// rewrite record |
54
|
1 |
|
if ($result->parentId != $parentId) { |
55
|
1 |
|
$result->parentId = intval($parentId); |
56
|
1 |
|
return $result->save(); |
57
|
|
|
} |
58
|
1 |
|
return null; |
59
|
2 |
|
} elseif (!empty($parentId)) { |
60
|
|
|
// new one |
61
|
2 |
|
$record = $this->getRelateRecord(); |
62
|
2 |
|
$record->childId = intval($this->getId()); |
63
|
2 |
|
$record->parentId = intval($parentId); |
64
|
2 |
|
return $record->save(); |
65
|
2 |
|
} elseif (!empty($result) && empty($parentId)) { |
66
|
|
|
// remove current one |
67
|
1 |
|
return $result->delete(); |
68
|
|
|
} else { |
69
|
2 |
|
return null; |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @throws MapperException |
75
|
|
|
* @throws PedigreeException |
76
|
|
|
* @return int|null |
77
|
|
|
*/ |
78
|
1 |
|
public function getFatherId(): ?int |
79
|
|
|
{ |
80
|
1 |
|
return $this->getParentId(ISex::MALE); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @throws MapperException |
85
|
|
|
* @throws PedigreeException |
86
|
|
|
* @return int|null |
87
|
|
|
*/ |
88
|
1 |
|
public function getMotherId(): ?int |
89
|
|
|
{ |
90
|
1 |
|
return $this->getParentId(ISex::FEMALE); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* @param string $sex |
95
|
|
|
* @throws MapperException |
96
|
|
|
* @throws PedigreeException |
97
|
|
|
* @return int|null |
98
|
|
|
*/ |
99
|
1 |
|
protected function getParentId(string $sex): ?int |
100
|
|
|
{ |
101
|
1 |
|
$results = $this->parentLookup($sex); |
102
|
1 |
|
return empty($results) ? null : intval($results->parentId); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* @param string $sex |
107
|
|
|
* @throws MapperException |
108
|
|
|
* @throws PedigreeException |
109
|
|
|
* @return PedigreeRelateRecord|null |
110
|
|
|
*/ |
111
|
2 |
|
protected function parentLookup(string $sex): ?PedigreeRelateRecord |
112
|
|
|
{ |
113
|
2 |
|
$search = new Search($this->getRelateRecord()); |
114
|
2 |
|
$search->exact('childId', strval($this->getId())); |
115
|
2 |
|
$search->child('parents', '', '', 'par'); |
116
|
2 |
|
$search->like('par.sex', $sex); |
117
|
2 |
|
$results = $search->getResults(); |
118
|
|
|
/** @var PedigreeRelateRecord[] $results */ |
119
|
2 |
|
return empty($results) ? null : reset($results); |
120
|
|
|
} |
121
|
|
|
|
122
|
1 |
|
public function getChildren(): array |
123
|
|
|
{ |
124
|
1 |
|
$searchRelation = new Search($this->getRelateRecord()); |
125
|
1 |
|
$searchRelation->exact('parentId', strval($this->getId())); |
126
|
1 |
|
$search = new Search($this->getLoadedRecord()); |
127
|
1 |
|
$search->in('id', array_map([$this, 'mapChildren'], $searchRelation->getResults() )); |
128
|
1 |
|
return $search->getResults(); |
129
|
|
|
} |
130
|
|
|
|
131
|
1 |
|
public function mapChildren(PedigreeRelateRecord $record): string |
132
|
|
|
{ |
133
|
1 |
|
return strval($record->childId); |
134
|
|
|
} |
135
|
|
|
|
136
|
2 |
|
public function saveFamily(?int $fatherId, ?int $motherId): ?bool |
137
|
|
|
{ |
138
|
2 |
|
$willSave = null; |
139
|
2 |
|
$action = $this->setFatherId($fatherId); |
140
|
2 |
|
if (is_bool($action)) { |
141
|
2 |
|
$willSave = $action; |
142
|
|
|
} |
143
|
2 |
|
$action = $this->setMotherId($motherId); |
144
|
2 |
|
if (is_bool($action)) { |
145
|
2 |
|
$willSave = (is_bool($willSave) ? $willSave : true) && $action; |
146
|
|
|
} |
147
|
2 |
|
return $willSave; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Unhook the original class, use only its definition and create new clear copy |
152
|
|
|
* @throws MapperException |
153
|
|
|
* @throws PedigreeException |
154
|
|
|
* @return PedigreeRelateRecord |
155
|
|
|
*/ |
156
|
3 |
|
protected function getRelateRecord(): PedigreeRelateRecord |
157
|
|
|
{ |
158
|
3 |
|
$fks = $this->getLoadedRecord()->getMapper()->getForeignKeys(); |
159
|
|
|
/** @var array<string, ForeignKey> $fks */ |
160
|
3 |
|
if (!isset($fks['children'])) { |
161
|
|
|
// @codeCoverageIgnoreStart |
162
|
|
|
throw new PedigreeException('Your mapper does not have children'); |
163
|
|
|
} |
164
|
|
|
// @codeCoverageIgnoreEnd |
165
|
3 |
|
$record = $fks['children']->getRemoteRecord(); |
166
|
3 |
|
return new $record(); |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|