From fafda7920308cbd058fd206e8963a6694712f034 Mon Sep 17 00:00:00 2001 From: Andre Wyrwa Date: Sun, 10 May 2015 05:30:17 +1000 Subject: [PATCH] refactor and improvements; fix tests; add docblocks; --- README.md | 7 +- src/Mapper/AbstractMapper.php | 20 ++ src/Mapper/FirstnameMapper.php | 27 ++- src/Mapper/InitialMapper.php | 8 +- src/Mapper/LastnameMapper.php | 47 ++--- src/Mapper/MiddlenameMapper.php | 50 +++++ src/Mapper/NicknameMapper.php | 32 +++ src/Mapper/SalutationMapper.php | 27 +-- src/Mapper/SuffixMapper.php | 46 ++--- src/Name.php | 89 ++++++++- src/Parser.php | 107 ++++++---- src/Part/AbstractPart.php | 57 ++++++ src/Part/Firstname.php | 10 + src/Part/Lastname.php | 60 ++++++ src/Part/Middlename.php | 18 ++ src/Part/Nickname.php | 18 ++ src/Part/Salutation.php | 46 +++++ src/Part/Suffix.php | 60 ++++++ tests/TheIconic/NameParser/ParserTest.php | 230 ++++++---------------- 19 files changed, 666 insertions(+), 293 deletions(-) create mode 100644 src/Mapper/MiddlenameMapper.php create mode 100644 src/Mapper/NicknameMapper.php create mode 100644 src/Part/Middlename.php create mode 100644 src/Part/Nickname.php diff --git a/README.md b/README.md index 9cf728b..ed0280d 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,14 @@ init(); + $name = $parser->parse($name); + echo $name->getSalutation(); echo $name->getFirstname(); echo $name->getLastname(); +echo $name->getMiddlename(); +echo $name->getNickname(); +echo $name->getInitials(); +echo $name->getSuffix(); ``` diff --git a/src/Mapper/AbstractMapper.php b/src/Mapper/AbstractMapper.php index be603c9..7f64c3a 100644 --- a/src/Mapper/AbstractMapper.php +++ b/src/Mapper/AbstractMapper.php @@ -5,6 +5,26 @@ abstract class AbstractMapper { + protected $options = []; + + /** + * constructor allows passing of options + * + * @param array $options + */ + public function __construct(array $options = null) + { + if (null !== $options) { + $this->options = array_merge($this->options, $options); + } + } + + /** + * implements the mapping of parts + * + * @param array $parts - the name parts + * @return array $parts - the mapped parts + */ abstract public function map(array $parts); } diff --git a/src/Mapper/FirstnameMapper.php b/src/Mapper/FirstnameMapper.php index 1667b7c..d7d3be0 100644 --- a/src/Mapper/FirstnameMapper.php +++ b/src/Mapper/FirstnameMapper.php @@ -8,10 +8,16 @@ use TheIconic\NameParser\Part\Initial; use TheIconic\NameParser\Part\Salutation; -class FirstnameMapper +class FirstnameMapper extends AbstractMapper { - public function map($parts) { + /** + * map firstnames in parts array + * + * @param array $parts the parts + * @return array the mapped parts + */ + public function map(array $parts) { if (count($parts) < 2) { if ($parts[0] instanceof AbstractPart) { return $parts; @@ -31,6 +37,8 @@ public function map($parts) { } } + $pos = null; + for ($k = $start; $k < $length; $k++) { $part = $parts[$k]; @@ -39,18 +47,21 @@ public function map($parts) { } if ($part instanceof Initial) { - if (!isset($parts[$k-1]) || $parts[$k-1] instanceof Firstname || $parts[$k-1] instanceof Initial) { - continue; + if (null === $pos) { + $pos = $k; } - - $parts[$k] = new Firstname($part); } if ($part instanceof AbstractPart) { - break; + continue; } - $parts[$k] = new Firstname($part); + $pos = $k; + break; + } + + if (null !== $pos) { + $parts[$pos] = new Firstname($parts[$pos]); } return $parts; diff --git a/src/Mapper/InitialMapper.php b/src/Mapper/InitialMapper.php index 40bcc2f..ff6230a 100644 --- a/src/Mapper/InitialMapper.php +++ b/src/Mapper/InitialMapper.php @@ -6,9 +6,15 @@ use TheIconic\NameParser\Part\Initial; // single letter, possibly followed by a period -class InitialMapper +class InitialMapper extends AbstractMapper { + /** + * map intials in parts array + * + * @param array $parts the name parts + * @return array the mapped parts + */ function map(array $parts) { foreach ($parts as $k => $part) { if ($part instanceof AbstractPart) { diff --git a/src/Mapper/LastnameMapper.php b/src/Mapper/LastnameMapper.php index 3d24ca6..816b702 100644 --- a/src/Mapper/LastnameMapper.php +++ b/src/Mapper/LastnameMapper.php @@ -6,29 +6,24 @@ use TheIconic\NameParser\Part\Lastname; use TheIconic\NameParser\Part\Suffix; -class LastnameMapper +class LastnameMapper extends AbstractMapper { - protected $prefixes = [ - 'vere' => 'vere', - 'von' => 'von', - 'van' => 'van', - 'de' => 'de', - 'der' => 'der', - 'del' => 'del', - 'della' => 'della', - 'di' => 'di', - 'da' => 'da', - 'pietro' => 'pietro', - 'vanden' => 'vanden', - 'du' => 'du', - 'st' => 'st.', - 'la' => 'la', - 'ter' => 'ter' + /** + * @var array options + */ + protected $options = [ + 'match_single' => false, ]; + /** + * map lastnames in the parts array + * + * @param array $parts the name parts + * @return array the mapped parts + */ public function map(array $parts) { - if (count($parts) < 2) { + if (!$this->options['match_single'] && count($parts) < 2) { return $parts; } @@ -47,9 +42,9 @@ public function map(array $parts) { break; } - if (false !== $prefix = $this->isPrefix($part)) { + if (Lastname::isPrefix($part)) { if (isset($parts[$k-1]) && $parts[$k-1] instanceof Lastname) { - $parts[$k] = new Lastname($prefix); + $parts[$k] = new Lastname($part); } } else if (!isset($parts[$k-1]) || !($parts[$k-1] instanceof Lastname)) { $parts[$k] = new Lastname($part); @@ -61,16 +56,4 @@ public function map(array $parts) { return array_reverse($parts); } - protected function isPrefix($part) - { - $part = str_replace('.', '', $part); - $part = strtolower($part); - - if (array_key_exists($part, $this->prefixes)) { - return $this->prefixes[$part]; - } - - return false; - } - } diff --git a/src/Mapper/MiddlenameMapper.php b/src/Mapper/MiddlenameMapper.php new file mode 100644 index 0000000..ef7d6e0 --- /dev/null +++ b/src/Mapper/MiddlenameMapper.php @@ -0,0 +1,50 @@ + $part) { + if ($part instanceof AbstractPart) { + continue; + } + + if (preg_match('/^[\(\[\<\{].*[\)\]\>\}]$/', $part)) { + $parts[$k] = new Nickname(substr($part, 1, -1)); + } + } + + return $parts; + } + +} diff --git a/src/Mapper/SalutationMapper.php b/src/Mapper/SalutationMapper.php index 1d9ffb4..a188adf 100644 --- a/src/Mapper/SalutationMapper.php +++ b/src/Mapper/SalutationMapper.php @@ -5,32 +5,23 @@ use TheIconic\NameParser\Part\AbstractPart; use TheIconic\NameParser\Part\Salutation; -class SalutationMapper +class SalutationMapper extends AbstractMapper { - protected $salutations = [ - 'mr' => 'Mr.', - 'master' => 'Mr.', - 'mister' => 'Mr.', - 'mrs' => 'Mrs.', - 'miss' => 'Ms.', - 'ms' => 'Ms.', - 'dr' => 'Dr.', - 'rev' => 'Rev.', - 'fr' => 'Fr.', - ]; - + /** + * map salutations in the parts array + * + * @param array $parts the name parts + * @return array the mapped parts + */ function map(array $parts) { foreach ($parts as $k => $part) { if ($part instanceof AbstractPart) { break; } - $part = str_replace('.', '', $part); - $part = strtolower($part); - - if (array_key_exists($part, $this->salutations)) { - $parts[$k] = new Salutation($this->salutations[$part]); + if (Salutation::isSalutation($part)) { + $parts[$k] = new Salutation($part); } } diff --git a/src/Mapper/SuffixMapper.php b/src/Mapper/SuffixMapper.php index fd07cff..bf8f734 100644 --- a/src/Mapper/SuffixMapper.php +++ b/src/Mapper/SuffixMapper.php @@ -5,45 +5,33 @@ use TheIconic\NameParser\Part\AbstractPart; use TheIconic\NameParser\Part\Suffix; -class SuffixMapper +class SuffixMapper extends AbstractMapper { - protected $suffixes = [ - 'i' => 'I', - 'ii' => 'II', - 'iii' => 'III', - 'iv' => 'IV', - 'v' => 'V', - 'seniour' => 'Senior', - 'junior' => 'Junior', - 'jr' => 'Jr', - 'sr' => 'Sr', - 'phd' => 'PhD', - 'apr' => 'APR', - 'rph' => 'RPh', - 'pe' => 'PE', - 'md' => 'MD', - 'ma' => 'MA', - 'dmd' => 'DMD', - 'cme' => 'CME', - ]; - + /** + * map suffixes in the parts array + * + * @param array $parts the name parts + * @return array the mapped parts + */ function map(array $parts) { - $parts = array_reverse($parts); - foreach ($parts as $k => $part) { + $start = count($parts) - 1; + + for ($k = $start; $k > 1; $k--) { + $part = $parts[$k]; + if ($part instanceof AbstractPart) { break; } - $part = str_replace('.', '', $part); - $part = strtolower($part); - - if (array_key_exists($part, $this->suffixes)) { - $parts[$k] = new Suffix($this->suffixes[$part]); + if (Suffix::isSuffix($part)) { + $parts[$k] = new Suffix($part); + } else { + break; } } - return array_reverse($parts); + return $parts; } } diff --git a/src/Name.php b/src/Name.php index 48145df..d058b30 100644 --- a/src/Name.php +++ b/src/Name.php @@ -7,47 +7,128 @@ class Name { - protected $parts; + /** + * @var array the parts that make up this name + */ + protected $parts = []; - public function __construct($parts = null) + /** + * constructor takes the array of parts this name consists of + * @param array|null $parts + */ + public function __construct(array $parts = null) { if (null !== $parts) { - $this->parts = $parts; + $this->setParts($parts); } } + /** + * set the parts this name consists of + * + * @param array $parts + * @return $this + */ + public function setParts(array $parts) + { + $this->parts = $parts; + + return $this; + } + + /** + * get the parts this name consists of + * + * @return array + */ + public function getParts() + { + return $this->parts; + } + + /** + * get the first name + * + * @return string + */ public function getFirstname() { return $this->export('Firstname'); } + /** + * get the last name + * + * @return string + */ public function getLastname() { return $this->export('Lastname'); } + /** + * get the initials + * + * @return string + */ public function getInitials() { return $this->export('Initial'); } + /** + * get the suffix(es) + * + * @return string + */ public function getSuffix() { return $this->export('Suffix'); } + /** + * get the salutation(s) + * + * @return string + */ public function getSalutation() { return $this->export('Salutation'); } + /** + * get the nick name(s) + * + * @return string + */ + public function getNickname() + { + return $this->export('Nickname'); + } + + /** + * get the middle name(s) + * + * @return string + */ + public function getMiddlename() + { + return $this->export('Middlename'); + } + + /** + * helper method used by getters to extract and format relevant name parts + * + * @param string $type the part type to export + * @return string the exported parts + */ protected function export($type) { $matched = []; foreach ($this->parts as $part) { if ($part instanceof AbstractPart && is_a($part, 'TheIconic\\NameParser\\Part\\' . $type)) { - $matched[] = $part->getValue(); + $matched[] = $part->normalize(); } } diff --git a/src/Parser.php b/src/Parser.php index 026b43b..2dee6e6 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -2,12 +2,13 @@ namespace TheIconic\NameParser; -use TheIconic\NameParser\Part\AbstractPart; +use TheIconic\NameParser\Mapper\NicknameMapper; use TheIconic\NameParser\Mapper\SalutationMapper; use TheIconic\NameParser\Mapper\SuffixMapper; use TheIconic\NameParser\Mapper\InitialMapper; use TheIconic\NameParser\Mapper\LastnameMapper; use TheIconic\NameParser\Mapper\FirstnameMapper; +use TheIconic\NameParser\Mapper\MiddlenameMapper; class Parser { @@ -16,17 +17,6 @@ class Parser protected $mappers = []; - public function init() - { - $this->setMappers([ - new SalutationMapper(), - new SuffixMapper(), - new InitialMapper(), - new LastnameMapper(), - new FirstnameMapper() - ]); - } - /** * split full names into the following parts: * - prefix / salutation (Mr., Mrs., etc) @@ -36,15 +26,17 @@ public function init() * - suffix (II, Phd, Jr, etc) * * @param $full_name - * @return mixed + * @return Name */ public function parse($name) { $name = $this->normalize($name); - $parts = explode(' ', $name); + if (false !== $pos = strpos($name, ',')) { + return $this->parseSplitName(substr($name, 0, $pos), substr($name, $pos + 1)); + } - $parts = $this->filter($parts); + $parts = explode(' ', $name); foreach ($this->getMappers() as $mapper) { $parts = $mapper->map($parts); @@ -53,51 +45,100 @@ public function parse($name) { return new Name($parts); } + /** + * handles split-parsing of comma-separated name parts + * + * @param $left - the name part left of the comma + * @param $right - the name part right of the comma + * + * @return Name + */ + protected function parseSplitName($left, $right) { + $first = new Parser(); + $first->setMappers([ + new SalutationMapper(), + new SuffixMapper(), + new LastnameMapper(['match_single' => true]), + ]); + $second = new Parser(); + $second->setMappers([ + new NicknameMapper(), + new InitialMapper(), + new FirstnameMapper(), + new MiddlenameMapper(), + ]); + $parts = array_merge( + $first->parse($left)->getParts(), + $second->parse($right)->getParts() + ); + return new Name($parts); + } + + /** + * get the mappers for this parser + * + * @return array + */ public function getMappers() { + if (empty($this->mappers)) { + $this->setMappers([ + new NicknameMapper(), + new SalutationMapper(), + new SuffixMapper(), + new InitialMapper(), + new LastnameMapper(), + new FirstnameMapper(), + new MiddlenameMapper(), + ]); + } + return $this->mappers; } + /** + * set the mappers for this parser + * + * @param array $mappers + */ public function setMappers(array $mappers) { $this->mappers = $mappers; } + /** + * normalize the name + * + * @param $name + * @return mixed + */ protected function normalize($name) { $whitespace = $this->getWhitespace(); - if (false !== $pos = strpos($name, ',')) { - $name = sprintf('%s %s', substr($name, $pos + 1), substr($name, 0, $pos)); - } - $name = trim($name); return preg_replace('/[' . preg_quote($whitespace) . ']+/', ' ', $name); } + /** + * get a string of characters that are supposed to be treated as whitespace + * + * @return string + */ protected function getWhitespace() { return $this->whitespace; } + /** + * set the string of characters that are supposed to be treated as whitespace + * + * @param $whitespace + */ protected function setWhitespace($whitespace) { $this->whitespace = $whitespace; } - protected function filter($parts) - { - $filtered = []; - - foreach ($parts as $part) { - if (preg_match('/[\(\[\<\{].*[\)\]\>\}]/', $part)) { - continue; - } - - $filtered[] = $part; - } - - return $filtered; - } } diff --git a/src/Part/AbstractPart.php b/src/Part/AbstractPart.php index e6d7f3e..1cfebc5 100644 --- a/src/Part/AbstractPart.php +++ b/src/Part/AbstractPart.php @@ -5,13 +5,28 @@ abstract class AbstractPart { + /** + * @var string the wrapped value + */ protected $value; + /** + * constructor allows passing the value to wrap + * + * @param $value + */ public function __construct($value) { $this->setValue($value); } + /** + * set the value to wrap + * (can take string or part instance) + * + * @param string|AbstractPart $value + * @return $this + */ public function setValue($value) { if ($value instanceof AbstractPart) { @@ -23,9 +38,51 @@ public function setValue($value) return $this; } + /** + * get the wrapped value + * + * @return string + */ public function getValue() { return $this->value; } + /** + * get the normalized value + * + * @return string + */ + public function normalize() + { + return $this->getValue(); + } + + /** + * helper for camelization of values + * to be used during normalize + * + * @param $word + * @return mixed + */ + protected function camelcase($word) + { + if (preg_match("/[A-Za-z]([A-Z]*[a-z][a-z]*[A-Z]|[a-z]*[A-Z][A-Z]*[a-z])[A-Za-z]*/", $word)) { + return $word; + } + + return preg_replace_callback('/[a-z0-9]+/i', array($this, 'camelcaseReplace'), $word); + } + + /** + * camelcasing callback + * + * @param $matches + * @return string + */ + protected function camelcaseReplace($matches) + { + return ucfirst(strtolower($matches[0])); + } + } diff --git a/src/Part/Firstname.php b/src/Part/Firstname.php index 1106bb2..ba8fd18 100644 --- a/src/Part/Firstname.php +++ b/src/Part/Firstname.php @@ -5,4 +5,14 @@ class Firstname extends AbstractPart { + /** + * camelcase the firstname + * + * @return mixed + */ + public function normalize() + { + return $this->camelcase($this->getValue()); + } + } diff --git a/src/Part/Lastname.php b/src/Part/Lastname.php index a13dd55..d9163a7 100644 --- a/src/Part/Lastname.php +++ b/src/Part/Lastname.php @@ -5,4 +5,64 @@ class Lastname extends AbstractPart { + /** + * @var array possible lastname prefixes + */ + static protected $prefixes = [ + 'vere' => 'vere', + 'von' => 'von', + 'van' => 'van', + 'de' => 'de', + 'der' => 'der', + 'del' => 'del', + 'della' => 'della', + 'di' => 'di', + 'da' => 'da', + 'pietro' => 'pietro', + 'vanden' => 'vanden', + 'du' => 'du', + 'st' => 'st.', + 'la' => 'la', + 'ter' => 'ter' + ]; + + /** + * check if the given word is a lastname prefix + * + * @param string $word the word to check + * @return bool + */ + static public function isPrefix($word) + { + return (array_key_exists(self::getKey($word), static::$prefixes)); + } + + /** + * get the prefix registry key for the given word + * + * @param string $word the word + * @return string the key + */ + static protected function getKey($word) + { + return strtolower(str_replace('.', '', $word)); + } + + /** + * if this is a lastname prefix, look up normalized version from registry + * otherwise camelcase the lastname + * + * @return mixed + */ + public function normalize() + { + $value = $this->getValue(); + + if (self::isPrefix($value)) { + return static::$prefixes[self::getKey($value)]; + } + + return $this->camelcase($this->getValue()); + } + } diff --git a/src/Part/Middlename.php b/src/Part/Middlename.php new file mode 100644 index 0000000..5346940 --- /dev/null +++ b/src/Part/Middlename.php @@ -0,0 +1,18 @@ +camelcase($this->getValue()); + } + +} diff --git a/src/Part/Nickname.php b/src/Part/Nickname.php new file mode 100644 index 0000000..68175dd --- /dev/null +++ b/src/Part/Nickname.php @@ -0,0 +1,18 @@ +camelcase($this->getValue()); + } + +} diff --git a/src/Part/Salutation.php b/src/Part/Salutation.php index 8d2e305..d1b693e 100644 --- a/src/Part/Salutation.php +++ b/src/Part/Salutation.php @@ -5,4 +5,50 @@ class Salutation extends AbstractPart { + /** + * @var array possible salutations + */ + static protected $salutations = [ + 'mr' => 'Mr.', + 'master' => 'Mr.', + 'mister' => 'Mr.', + 'mrs' => 'Mrs.', + 'miss' => 'Ms.', + 'ms' => 'Ms.', + 'dr' => 'Dr.', + 'rev' => 'Rev.', + 'fr' => 'Fr.', + ]; + + /** + * check if the given word is a viable salutation + * + * @param string $word the word to check + * @return bool + */ + static public function isSalutation($word) + { + return (array_key_exists(self::getKey($word), static::$salutations)); + } + + /** + * get the registry lookup key for the given word + * + * @param string $word the word + * @return string the key + */ + static protected function getKey($word) + { + return strtolower(str_replace('.', '', $word)); + } + + /** + * normalize by looking up the wrapped value against the registry + * + * @return mixed + */ + public function normalize() + { + return static::$salutations[self::getKey($this->getValue())]; + } } diff --git a/src/Part/Suffix.php b/src/Part/Suffix.php index 40c7d22..b64d4e9 100644 --- a/src/Part/Suffix.php +++ b/src/Part/Suffix.php @@ -5,4 +5,64 @@ class Suffix extends AbstractPart { + /** + * @var array possible suffixes + */ + static protected $suffixes = [ + 'i' => 'I', + 'ii' => 'II', + 'iii' => 'III', + 'iv' => 'IV', + 'v' => 'V', + '1st' => '1st', + '2nd' => '2nd', + '3rd' => '3rd', + '4th' => '4th', + '5th' => '5th', + 'senior' => 'Senior', + 'junior' => 'Junior', + 'jr' => 'Jr', + 'sr' => 'Sr', + 'phd' => 'PhD', + 'apr' => 'APR', + 'rph' => 'RPh', + 'pe' => 'PE', + 'md' => 'MD', + 'ma' => 'MA', + 'dmd' => 'DMD', + 'cme' => 'CME', + ]; + + /** + * check if the given word is a viable suffix + * + * @param string $word the word to check + * @return bool + */ + static public function isSuffix($word) + { + return (array_key_exists(self::getKey($word), static::$suffixes)); + } + + /** + * get the registry lookup key for the given word + * + * @param string $word the word + * @return string the key + */ + static protected function getKey($word) + { + return strtolower(str_replace('.', '', $word)); + } + + /** + * lookup the normalized suffix from the registry + * + * @return mixed + */ + public function normalize() + { + return static::$suffixes[self::getKey($this->getValue())]; + } + } diff --git a/tests/TheIconic/NameParser/ParserTest.php b/tests/TheIconic/NameParser/ParserTest.php index ec8aab1..1665968 100644 --- a/tests/TheIconic/NameParser/ParserTest.php +++ b/tests/TheIconic/NameParser/ParserTest.php @@ -10,14 +10,20 @@ class ParserTest extends PHPUnit_Framework_TestCase public function provider() { return array( + array( + 'James Norrington', + array( + 'firstname' => 'James', + 'lastname' => 'Norrington', + ) + + ), array( 'Hans Christian Anderssen', array( - 'firstname' => 'Hans Christian', + 'firstname' => 'Hans', 'lastname' => 'Anderssen', - 'salutation' => '', - 'initials' => '', - 'suffix' => '', + 'middlename' => 'Christian', ) ), array( @@ -43,29 +49,22 @@ public function provider() array( "J. B. Hunt", array( - "salutation" => "", "firstname" => "J.", "initials" => "B.", "lastname" => "Hunt", - "suffix" => "" ) ), array( "J.B. Hunt", array( - "salutation" => "", "firstname" => "J.B.", - "initials" => "", "lastname" => "Hunt", - "suffix" => "" ) ), array( "Edward Senior III", array( - "salutation" => "", "firstname" => "Edward", - "initials" => "", "lastname" => "Senior", "suffix" => "III" ) @@ -73,49 +72,24 @@ public function provider() array( "Edward Dale Senior II", array( - "salutation" => "", - "firstname" => "Edward Dale", - "initials" => "", - "lastname" => "Senior", - "suffix" => "II" - ) - ), - array( - "Dale Edward Jones Senior", - array( - "salutation" => "", - "firstname" => "Dale Edward", - "initials" => "", - "lastname" => "Jones", - "suffix" => "Senior" - ) - ), - array( - "Edward Senior II", - array( - "salutation" => "", "firstname" => "Edward", - "initials" => "", - "lastname" => "Senior", - "suffix" => "II" + "lastname" => "Dale", + "suffix" => "Senior II" ) ), array( - "Dale Edward Senior II, PhD", + "Dale Edward Jones Senior", array( - "salutation" => "", - "firstname" => "Dale Edward", - "initials" => "", - "lastname" => "Senior", - "suffix" => "II, PhD" + "firstname" => "Dale", + 'middlename' => 'Edward', + "lastname" => "Jones", + "suffix" => "Senior" ) ), array( "Jason Rodriguez Sr.", array( - "salutation" => "", "firstname" => "Jason", - "initials" => "", "lastname" => "Rodriguez", "suffix" => "Sr" ) @@ -123,132 +97,90 @@ public function provider() array( "Jason Senior", array( - "salutation" => "", "firstname" => "Jason", - "initials" => "", "lastname" => "Senior", - "suffix" => "" ) ), array( "Bill Junior", array( - "salutation" => "", - "firstname" => "Bill", - "initials" => "", - "lastname" => "Junior", - "suffix" => "" + "firstname" => "Bill", + "lastname" => "Junior", ) ), array( "Sara Ann Fraser", array( - "salutation" => "", - "firstname" => "Sara Ann", - "initials" => "", - "lastname" => "Fraser", - "suffix" => "" + "firstname" => "Sara", + 'middlename' => 'Ann', + "lastname" => "Fraser", ) ), array( "Adam", array( - "salutation" => "", - "firstname" => "Adam", - "initials" => "", - "lastname" => "", - "suffix" => "" + "firstname" => "Adam", ) ), array( "OLD MACDONALD", array( - "salutation" => "", "firstname" => "Old", - "initials" => "", "lastname" => "Macdonald", - "suffix" => "" ) ), array( "Old MacDonald", array( - "salutation" => "", "firstname" => "Old", - "initials" => "", "lastname" => "MacDonald", - "suffix" => "" ) ), array( "Old McDonald", array( - "salutation" => "", "firstname" => "Old", - "initials" => "", "lastname" => "McDonald", - "suffix" => "" ) ), array( "Old Mc Donald", array( - "salutation" => "", - "firstname" => "Old Mc", - "initials" => "", + "firstname" => "Old", + 'middlename' => 'Mc', "lastname" => "Donald", - "suffix" => "" ) ), array( "Old Mac Donald", array( - "salutation" => "", - "firstname" => "Old Mac", - "initials" => "", + "firstname" => "Old", + 'middlename' => 'Mac', "lastname" => "Donald", - "suffix" => "" ) ), array( "James van Allen", array( - "salutation" => "", "firstname" => "James", - "initials" => "", "lastname" => "van Allen", - "suffix" => "" ) ), array( "Jimmy (Bubba) Smith", array( - "nickname" => "Bubba", - "salutation" => "", - "firstname" => "Jimmy", - "initials" => "", - "lastname" => "Smith", - "suffix" => "" + "firstname" => "Jimmy", + "lastname" => "Smith", + "nickname" => "Bubba", ) ), array( "Miss Jennifer Shrader Lawrence", array( "salutation" => "Ms.", - "firstname" => "Jennifer Shrader", - "initials" => "", - "lastname" => "Lawrence", - "suffix" => "" - ) - ), - array( - "Jonathan Smith, MD", - array( - "salutation" => "", - "firstname" => "Jonathan", - "initials" => "", - "lastname" => "Smith", - "suffix" => "MD" + "firstname" => "Jennifer", + 'middlename' => 'Shrader', + "lastname" => "Lawrence", ) ), array( @@ -256,19 +188,7 @@ public function provider() array( "salutation" => "Dr.", "firstname" => "Jonathan", - "initials" => "", - "lastname" => "Smith", - "suffix" => "" - ) - ), - array( - "Jonathan Smith IV, PhD", - array( - "salutation" => "", - "firstname" => "Jonathan", - "initials" => "", "lastname" => "Smith", - "suffix" => "IV, PhD" ) ), array( @@ -278,7 +198,6 @@ public function provider() "firstname" => "Jamie", "initials" => "P.", "lastname" => "Harrowitz", - "suffix" => "" ) ), array( @@ -286,9 +205,7 @@ public function provider() array( "salutation" => "Mr.", "firstname" => "John", - "initials" => "", "lastname" => "Doe", - "suffix" => "" ) ), array( @@ -296,37 +213,21 @@ public function provider() array( "salutation" => "Rev. Dr.", "firstname" => "John", - "initials" => "", "lastname" => "Doe", - "suffix" => "" ) ), array( "Anthony Von Fange III", array( - "salutation" => "", "firstname" => "Anthony", - "initials" => "", "lastname" => "von Fange", "suffix" => "III" ) ), - array( - "Anthony Von Fange III, PhD", - array( - "salutation" => "", - "firstname" => "Anthony", - "initials" => "", - "lastname" => "von Fange", - "suffix" => "III, PhD" - ) - ), array( "Smarty Pants Phd", array( - "salutation" => "", "firstname" => "Smarty", - "initials" => "", "lastname" => "Pants", "suffix" => "PhD" ) @@ -334,61 +235,49 @@ public function provider() array( "Mark Peter Williams", array( - "salutation" => "", - "firstname" => "Mark Peter", - "initials" => "", - "lastname" => "Williams", - "suffix" => "" + "firstname" => "Mark", + 'middlename' => 'Peter', + "lastname" => "Williams", ) ), array( "Mark P Williams", array( - "salutation" => "", "firstname" => "Mark", - "initials" => "P", "lastname" => "Williams", - "suffix" => "" + 'initials' => 'P', ) ), array( "Mark P. Williams", array( - "salutation" => "", "firstname" => "Mark", "initials" => "P.", "lastname" => "Williams", - "suffix" => "" ) ), array( "M Peter Williams", array( - "salutation" => "", "firstname" => "Peter", "initials" => "M", "lastname" => "Williams", - "suffix" => "" ) ), array( "M. Peter Williams", array( - "salutation" => "", "firstname" => "Peter", "initials" => "M.", "lastname" => "Williams", - "suffix" => "" ) ), array( "M. P. Williams", array( - "salutation" => "", "firstname" => "M.", "initials" => "P.", "lastname" => "Williams", - "suffix" => "" ) ), array( @@ -396,9 +285,7 @@ public function provider() array( "salutation" => "Rev.", "firstname" => "Mark", - "initials" => "", "lastname" => "Williams", - "suffix" => "" ) ), array( @@ -406,9 +293,22 @@ public function provider() array( "salutation" => "Mr.", "firstname" => "Mark", - "initials" => "", "lastname" => "Williams", - "suffix" => "" + ) + ), + array( + "Fraser, Joshua", + array( + "firstname" => "Joshua", + "lastname" => "Fraser", + ) + ), + array( + 'Mrs. Brown, Amanda', + array( + 'salutation' => 'Mrs.', + 'firstname' => 'Amanda', + 'lastname' => 'Brown', ) ) ); @@ -417,15 +317,12 @@ public function provider() public function disfunctionalastnameProvider() { return array( - // fails. format not yet supported array( - "Fraser, Joshua", + "Jonathan Smith, MD", array( - "salutation" => "", - "firstname" => "Joshua", - "initials" => "", - "lastname" => "Fraser", - "suffix" => "" + "firstname" => "Jonathan", + "lastname" => "Smith", + "suffix" => "MD" ) ), // fails. both initials should be capitalized @@ -487,17 +384,16 @@ public function testParse($input, $expectation) { $parser = new Parser(); - $parser->init(); $name = $parser->parse($input); $this->assertInstanceOf('\\TheIconic\\NameParser\\Name', $name); - $results = [ - 'salutation' => $name->getSalutation(), - 'firstname' => $name->getFirstname(), - 'lastname' => $name->getLastname(), - 'initials' => $name->getInitials(), - 'suffix' => $name->getSuffix(), - ]; + $results = []; + foreach (['salutation', 'firstname', 'middlename', 'lastname', 'nickname', 'initials', 'suffix'] as $key) { + $method = sprintf('get%s', ucfirst($key)); + if ($value = call_user_func(array($name, $method))) { + $results[$key] = $value; + }; + } $this->assertEquals($expectation, $results); }