public function rule_to_name($name, $is_capitalise_prefix = false)
{
/*
A name can have up to 5 components, space delimited:
Worst case:
salutation | forenames | prefix(es) | main name | suffix
Ms | Jo-Sue Ellen | de la | Mer-Savarin | III
Rules for forenames
1) Capitalise 1st char and after a hyphen.
Rules for special case prefixes: von, de etc
1) Set capitalisation at runtime.
There seem to be no fixed rules, but
lower case is commonly used as part of a
whole name:
John von Trapp
While it is normally capitalised as part of
a salutation:
Dear Mr Von Trapp
By default we store in the lower case form.
Set the param $is_capitalise_prefix to true
to capitalise.
2) In default mode, St is capitalised,
other prefixes lower cased. We retain user's
choice of punctuation with St./St
Rules for main name:
1) Capitalise after a hyphen in the main name:
Smythington-Fenwick
2) Capitalise after Mc at start of name -
this is pretty much a universal rule
MCDONALD => McDonald
3) Unless user has capitalised after the M,
do NOT capitalise after Mac at start of name:
- Many Scottish Mac names
are not capitalised: Macaulay, Macdonald
- Many non-Scottish names start with Mac:
eg Macon - we want to avoid "MacOn";
- The Cpan name modules and some style manuals
force MacDonald, but this seems to
create more problems than it solves.
macrae => Macrae
4) Capitalise after O'
o'grady => O'Grady
*/
// If name string is empty, bail out
if (empty($name)) {
return '';
}
// Setup special case prefix lookup list.
// These are prefixes that are not capitalised.
// Prefixes which are capitalised such as "St"
// can be omitted.
// We omit prefixes that are also common names,
// such as "Della", "Di" and "Ben"
$prefixes = array('ap' => array('upper' => 'Ap', 'lower' => 'ap'), 'da' => array('upper' => 'Da', 'lower' => 'da'), 'de' => array('upper' => 'De', 'lower' => 'de'), 'del' => array('upper' => 'Del', 'lower' => 'del'), 'der' => array('upper' => 'Der', 'lower' => 'der'), 'du' => array('upper' => 'Du', 'lower' => 'du'), 'la' => array('upper' => 'La', 'lower' => 'la'), 'le' => array('upper' => 'Le', 'lower' => 'le'), 'lo' => array('upper' => 'Lo', 'lower' => 'lo'), 'van' => array('upper' => 'Van', 'lower' => 'van'), 'von' => array('upper' => 'Von', 'lower' => 'von'));
// Set up suffix lookup list
// We preserve user's preferred punctuation: Sr./Sr
$suffixes = array('i' => 'I', 'ii' => 'II', 'iii' => 'III', 'iv' => 'IV', 'v' => 'V', 'vi' => 'VI', 'vii' => 'VII', 'viii' => 'VIII', 'ix' => 'IX', 'x' => 'X', 'jr.' => 'Jr.', 'jr' => 'Jr', 'jnr.' => 'Jnr.', 'jnr' => 'Jnr', 'sr.' => 'Sr.', 'sr' => 'Sr', 'snr.' => 'Snr.', 'snr' => 'Snr', '1st' => '1st', '2nd' => '2nd', '3rd' => '3rd', '4th' => '4th', '5th' => '5th', '6th' => '6th', '7th' => '7th', '8th' => '8th', '9th' => '9th', '10th' => '10th', '1st.' => '1st.', '2nd.' => '2nd.', '3rd.' => '3rd.', '4th.' => '4th.', '5th.' => '5th.', '6th.' => '6th.', '7th.' => '7th.', '8th.' => '8th.', '9th.' => '9th.', '10th.' => '10th.');
// Clean out extra whitespace
$name = $this->strip_excess_whitespace(trim($name));
// Try to parse into forenames, main name, suffix
$parts = explode(' ', $name);
if (count($parts) == 1) {
// Must be the main name
$name_main = array_pop($parts);
$name_fname = false;
$name_suffix = false;
} else {
// We have more than one part to parse
// Is the last part a suffix?
// We assume name can have only one suffix
$part = array_pop($parts);
$normalised_part = strtolower($part);
if (array_key_exists($normalised_part, $suffixes)) {
// Last part is a suffix
$name_main = array_pop($parts);
$name_suffix = $suffixes[$normalised_part];
} else {
// Last part is the main name
$name_main = $part;
$name_suffix = false;
}
}
// Anything left is a salutation, initial or forname
if (count($parts) > 0) {
$name_fnames = $parts;
} else {
$name_fnames = false;
}
// We build the name from first to last:
$new_name = array();
// Set case for the forenames
if ($name_fnames) {
foreach ($name_fnames as $fname) {
$parts = array();
$fname = strtolower($fname);
// Do hypenated parts separately
$exploded_fname = explode('-', $fname);
foreach ($exploded_fname as $part) {
// If it is one of our special case prefixes
// we use the appropriate value
// Else, we capitalise
if (array_key_exists($part, $prefixes)) {
if ($is_capitalise_prefix !== false) {
$parts[] = $prefixes[$part]['upper'];
} else {
$parts[] = $prefixes[$part]['lower'];
}
} else {
// It is a normal forename, salutation or initial
// We capitalise it.
$parts[] = ucfirst($part);
}
}
$new_name[] = implode('-', $parts);
}
}
// Set case for the main name
$name_main_original = $name_main;
$name_main = strtolower($name_main);
// Do hypenated parts separately
$exploded_main_original = explode('-', $name_main_original);
$exploded_main = explode('-', $name_main);
$parts = array();
foreach ($exploded_main as $key => $part) {
$part_original = $exploded_main_original[$key];
if (substr($part, 0, 2) == 'mc') {
// Do "Mc"
// Uppercase the 3rd character
$a = substr($part, 2);
$parts[] = 'Mc' . ucfirst($a);
} elseif (substr($part, 0, 3) == 'mac') {
// Do "Mac"
// Lowercase the 3rd character
// unless user has submitted
// a correct looking name
if (preg_match('|^Mac[A-Z][a-z]*$|', $part_original)) {
$parts[] = $part_original;
} else {
$parts[] = ucfirst($part);
}
} elseif (substr($part, 0, 2) == "o'") {
// Do O'
// Uppercase the 3rd character
$a = substr($part, 2);
$parts[] = "O'" . ucwords($a);
} else {
// It is a plain-jane name
$parts[] = ucfirst($part);
}
}
$new_name[] = implode('-', $parts);
if ($name_suffix !== false) {
$new_name[] = $name_suffix;
}
// Assemble the new name
$output = implode(' ', $new_name);
return $output;
}