From 3432592621aa86624512da66c80331924e8e17bb Mon Sep 17 00:00:00 2001 From: Andre Wyrwa Date: Thu, 7 Nov 2019 01:46:30 +1100 Subject: [PATCH] Detect last name prefixes in combined lastname parts (fixes #30) This enables the detection of lastnames combined via a dash with the prefix to a following lastname, e.g. in "Etje Heijdanus-De Boer". At this point the entire part is treated as Lastname as there is no support for re-combining last name parts or prefixes. This means the 'De' prefix in 'De Boer' above cannot be accessed individually. --- src/Mapper/LastnameMapper.php | 54 +++++++++++++++++++++++++++++++---- src/Name.php | 10 +------ tests/ParserTest.php | 7 +++++ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/Mapper/LastnameMapper.php b/src/Mapper/LastnameMapper.php index 05d0d11..43cfdc7 100644 --- a/src/Mapper/LastnameMapper.php +++ b/src/Mapper/LastnameMapper.php @@ -57,8 +57,8 @@ protected function mapParts(array $parts): array } if ($this->isFollowedByLastnamePart($parts, $k)) { - if ($this->isApplicablePrefix($parts, $k)) { - $parts[$k] = new LastnamePrefix($part, $this->prefixes[$this->getKey($part)]); + if ($mapped = $this->mapAsPrefixIfPossible($parts, $k)) { + $parts[$k] = $mapped; continue; } @@ -78,6 +78,45 @@ protected function mapParts(array $parts): array return $parts; } + /** + * try to map this part as a lastname prefix or as a combined + * lastname part containing a prefix + * + * @param array $parts + * @param int $k + * @return Lastname|null + */ + private function mapAsPrefixIfPossible(array $parts, int $k): ?Lastname + { + if ($this->isApplicablePrefix($parts, $k)) { + return new LastnamePrefix($parts[$k], $this->prefixes[$this->getKey($parts[$k])]); + } + + if ($this->isCombinedWithPrefix($parts[$k])) { + return new Lastname($parts[$k]); + } + + return null; + } + + /** + * check if the given part is a combined lastname part + * that ends in a lastname prefix + * + * @param string $part + * @return bool + */ + private function isCombinedWithPrefix(string $part): bool + { + $pos = strpos($part, '-'); + + if (false === $pos) { + return false; + } + + return $this->isPrefix(substr($part, $pos + 1)); + } + /** * skip through the parts we want to ignore and return the start index * @@ -98,7 +137,7 @@ protected function skipIgnoredParts(array $parts): int } /** - * indicates if we should stop mapping at the give index $k + * indicates if we should stop mapping at the given index $k * * the assumption is that lastname parts have already been found * but we want to see if we should add more parts @@ -113,11 +152,15 @@ protected function shouldStopMapping(array $parts, int $k): bool return true; } - if ($parts[$k + 1] instanceof LastnamePrefix) { + $lastPart = $parts[$k + 1]; + + if ($lastPart instanceof LastnamePrefix) { return true; } - return strlen($parts[$k + 1]->getValue()) >= 3; + + + return strlen($lastPart->getValue()) >= 3; } /** @@ -135,7 +178,6 @@ protected function isIgnoredPart($part) { * * if the mapping did not derive any lastname this is called to transform * any previously ignored parts into lastname parts - * the parts array is still reversed at this point * * @param array $parts * @return array diff --git a/src/Name.php b/src/Name.php index ca5a1aa..15d2679 100644 --- a/src/Name.php +++ b/src/Name.php @@ -92,15 +92,7 @@ public function getAll(bool $format = false): array */ public function getGivenName(): string { - $fullNameParts = []; - - foreach ($this->parts as $part) { - if ($part instanceof GivenNamePart) { - $fullNameParts[] = $part->normalize(); - } - } - - return implode(' ', $fullNameParts); + return $this->export('GivenNamePart'); } /** diff --git a/tests/ParserTest.php b/tests/ParserTest.php index cebea92..1b1c488 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -527,6 +527,13 @@ public function provider() 'lastname' => 'Judy', 'salutation' => 'Her Honour Mrs.' ] + ], + [ + 'Etje Heijdanus-De Boer', + [ + 'firstname' => 'Etje', + 'lastname' => 'Heijdanus-De Boer', + ] ] ]; }