Passed
Pull Request — develop (#148)
by
unknown
05:16
created

Name::isEtAl()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 8
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 13
ccs 9
cts 9
cp 1
crap 7
rs 8.8333
1
<?php
2
/*
3
 * citeproc-php
4
 *
5
 * @link        http://github.com/seboettg/citeproc-php for the source repository
6
 * @copyright   Copyright (c) 2016 Sebastian Böttger.
7
 * @license     https://opensource.org/licenses/MIT
8
 */
9
10
namespace Seboettg\CiteProc\Rendering\Name;
11
12
use Seboettg\CiteProc\CiteProc;
13
use Seboettg\CiteProc\Exception\CiteProcException;
14
use Seboettg\CiteProc\Exception\InvalidStylesheetException;
15
use Seboettg\CiteProc\Rendering\HasParent;
16
use Seboettg\CiteProc\Style\InheritableNameAttributesTrait;
17
use Seboettg\CiteProc\Style\Options\DemoteNonDroppingParticle;
18
use Seboettg\CiteProc\Style\Options\SubsequentAuthorSubstituteRule;
19
use Seboettg\CiteProc\Styles\AffixesTrait;
20
use Seboettg\CiteProc\Styles\DelimiterTrait;
21
use Seboettg\CiteProc\Styles\FormattingTrait;
22
use Seboettg\CiteProc\Util\CiteProcHelper;
23
use Seboettg\CiteProc\Util\Factory;
24
use Seboettg\CiteProc\Util\NameHelper;
25
use Seboettg\CiteProc\Util\StringHelper;
26
use SimpleXMLElement;
27
use stdClass;
28
29
/**
30
 * Class Name
31
 *
32
 * The cs:name element, an optional child element of cs:names, can be used to describe the formatting of individual
33
 * names, and the separation of names within a name variable.
34
 *
35
 * @package Seboettg\CiteProc\Rendering\Name
36
 *
37
 * @author Sebastian Böttger <[email protected]>
38
 */
39
class Name implements HasParent
40
{
41
    use InheritableNameAttributesTrait,
0 ignored issues
show
Bug introduced by
The trait Seboettg\CiteProc\Styles\AffixesTrait requires the property $single which is not provided by Seboettg\CiteProc\Rendering\Name\Name.
Loading history...
42
        FormattingTrait,
43
        AffixesTrait,
44
        DelimiterTrait;
45
46
    /**
47
     * @var array
48
     */
49
    protected $nameParts;
50
51
    /**
52
     * Specifies the text string used to separate names in a name variable. Default is ”, ” (e.g. “Doe, Smith”).
53
     *
54
     * @var
55
     */
56
    private $delimiter = ", ";
57
58
    /**
59
     * @var Names
60
     */
61
    private $parent;
62
63
    /**
64
     * @var SimpleXMLElement
65
     */
66
    private $node;
67
68
    /**
69
     * @var string
70
     */
71
    private $etAl;
72
73
    /**
74
     * @var string
75
     */
76
    private $variable;
77
78
    /**
79
     * Name constructor.
80
     *
81
     * @param  SimpleXMLElement $node
82
     * @param  Names            $parent
83
     * @throws InvalidStylesheetException
84
     */
85 128
    public function __construct(SimpleXMLElement $node, Names $parent)
86
    {
87 128
        $this->node = $node;
88 128
        $this->parent = $parent;
89
90 128
        $this->nameParts = [];
91
92
        /**
93
         * @var SimpleXMLElement $child
94
*/
95 128
        foreach ($node->children() as $child) {
96 3
            switch ($child->getName()) {
97 3
                case "name-part":
98
                    /** @var NamePart $namePart */
99 3
                    $namePart = Factory::create($child, $this);
100 3
                    $this->nameParts[$namePart->getName()] = $namePart;
101
            }
102
        }
103
104 128
        foreach ($node->attributes() as $attribute) {
105 112
            switch ($attribute->getName()) {
106 112
                case 'form':
107 65
                    $this->form = (string) $attribute;
108 65
                    break;
109
            }
110
        }
111
112 128
        $this->initFormattingAttributes($node);
113 128
        $this->initAffixesAttributes($node);
114 128
        $this->initDelimiterAttributes($node);
115 128
    }
116
117
    /**
118
     * @param  stdClass     $data
119
     * @param  string       $var
120
     * @param  integer|null $citationNumber
121
     * @return string
122
     * @throws CiteProcException
123
     */
124 111
    public function render($data, $var, $citationNumber = null)
125
    {
126 111
        $this->variable = $var;
127 111
        $name = $data->{$var};
128 111
        if (!$this->attributesInitialized) {
129 111
            $this->initInheritableNameAttributes($this->node);
130
        }
131 111
        if ("text" === $this->and) {
132 29
            $this->and = CiteProc::getContext()->getLocale()->filter('terms', 'and')->single;
133 93
        } elseif ('symbol' === $this->and) {
134 29
            $this->and = '&#38;';
135
        }
136
137 111
        $resultNames = $this->handleSubsequentAuthorSubstitution($name, $citationNumber);
138
139 111
        if (empty($resultNames)) {
140 2
            return CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstitute();
141
        }
142
143 111
        $resultNames = $this->prepareAbbreviation($resultNames);
144
145
        /* When set to “true” (the default is “false”), name lists truncated by et-al abbreviation are followed by
146
        the name delimiter, the ellipsis character, and the last name of the original name list. This is only
147
        possible when the original name list has at least two more names than the truncated name list (for this
148
        the value of et-al-use-first/et-al-subsequent-min must be at least 2 less than the value of
149
        et-al-min/et-al-subsequent-use-first). */
150 111
        if ($this->etAlUseLast && $this->isEtAl($name, $resultNames)) {
151 3
            $this->and = "…"; // set "and"
152 3
            $this->etAl = null; //reset $etAl;
153
        }
154
155
        /* add "and" */
156 111
        $this->addAnd($resultNames);
157
158 111
        $text = $this->renderDelimiterPrecedesLast($resultNames);
159
160 111
        if (empty($text)) {
161 67
            $text = implode($this->delimiter, $resultNames);
162
        }
163
164 111
        $text = $this->appendEtAl($name, $text, $resultNames);
165
166
        /* A third value, “count”, returns the total number of names that would otherwise be rendered by the use of the
167
        cs:names element (taking into account the effects of et-al abbreviation and editor/translator collapsing),
168
        which allows for advanced sorting. */
169 111
        if ($this->form == 'count') {
170 6
            return (int) count($resultNames);
171
        }
172
173 106
        return $text;
174
    }
175
176
    /**
177
     * @param  stdClass $nameItem
178
     * @param  int      $rank
179
     * @return string
180
     * @throws CiteProcException
181
     */
182 111
    private function formatName($nameItem, $rank)
183
    {
184 111
        $nameObj = $this->cloneNamePOSC($nameItem);
185
186 111
        $useInitials = $this->initialize && !is_null($this->initializeWith) && $this->initializeWith !== false;
187 111
        if ($useInitials && isset($nameItem->given)) {
188 32
            $nameObj->given = StringHelper::initializeBySpaceOrHyphen($nameItem->given, $this->initializeWith);
189
        }
190
191 111
        $renderedResult = $this->getNamesString($nameObj, $rank);
192 111
        CiteProcHelper::applyAdditionMarkupFunction($nameItem, $this->parent->getVariables()[0], $renderedResult);
193 111
        return trim($renderedResult);
194
    }
195
196
    /**
197
     * @param  stdClass $name
198
     * @param  int      $rank
199
     * @return string
200
     * @throws CiteProcException
201
     */
202 111
    private function getNamesString($name, $rank)
203
    {
204 111
        $text = "";
205
206 111
        if (!isset($name->family)) {
207
            return $text;
208
        }
209
210 111
        $text = $this->nameOrder($name, $rank);
211
212
        //contains nbsp prefixed by normal space or followed by normal space?
213 111
        $text = htmlentities($text);
214 111
        if (strpos($text, " &nbsp;") !== false || strpos($text, "&nbsp; ") !== false) {
215
            $text = preg_replace("/[\s]+/", "", $text); //remove normal spaces
216
            return preg_replace("/&nbsp;+/", " ", $text);
217
        }
218 111
        $text = html_entity_decode(preg_replace("/[\s]+/", " ", $text));
219 111
        return $this->format(trim($text));
220
    }
221
222
    /**
223
     * @param  stdClass $name
224
     * @return stdClass
225
     */
226 111
    private function cloneNamePOSC($name)
227
    {
228 111
        $nameObj = new stdClass();
229 111
        if (isset($name->family)) {
230 111
            $nameObj->family = $name->family;
231
        }
232 111
        if (isset($name->given)) {
233 109
            $nameObj->given = $name->given;
234
        }
235 111
        if (isset($name->{'non-dropping-particle'})) {
236 8
            $nameObj->{'non-dropping-particle'} = $name->{'non-dropping-particle'};
237
        }
238 111
        if (isset($name->{'dropping-particle'})) {
239 8
            $nameObj->{'dropping-particle'} = $name->{'dropping-particle'};
240
        }
241 111
        if (isset($name->{'suffix'})) {
242 18
            $nameObj->{'suffix'} = $name->{'suffix'};
243
        }
244 111
        return $nameObj;
245
    }
246
247
    /**
248
     * @param $data
249
     * @param $resultNames
250
     * @return bool
251
     */
252 111
    protected function isEtAl($data, $resultNames): bool
253
    {
254 111
        if (count($data) > 1
255 111
            && !empty($resultNames)
256 111
            && !empty($this->etAl)
257 111
            && !empty($this->etAlMin)
258 111
            && !empty($this->etAlUseFirst)
259 111
            && count($data) != count($resultNames)
260
        ) {
261 17
            return true;
262
        }
263
264 107
        return false;
265
    }
266
267
    /**
268
     * @param  $data
269
     * @param  $text
270
     * @param  $resultNames
271
     * @return string
272
     */
273 111
    protected function appendEtAl($data, $text, $resultNames)
274
    {
275
        //append et al abbreviation
276 111
        if ($this->isEtAl($data, $resultNames)) {
277
            /* By default, when a name list is truncated to a single name, the name and the “et-al” (or “and others”)
278
            term are separated by a space (e.g. “Doe et al.”). When a name list is truncated to two or more names, the
279
            name delimiter is used (e.g. “Doe, Smith, et al.”). This behavior can be changed with the
280
            delimiter-precedes-et-al attribute. */
281
282 14
            switch ($this->delimiterPrecedesEtAl) {
283 14
                case 'never':
284 5
                    $text = $text . " " . $this->etAl;
285 5
                    break;
286 9
                case 'always':
287 1
                    $text = $text . $this->delimiter . $this->etAl;
288 1
                    break;
289 9
                case 'contextual':
290
                default:
291 9
                    if (count($resultNames) === 1) {
292 4
                        $text .= " " . $this->etAl;
293
                    } else {
294 5
                        $text .= $this->delimiter . $this->etAl;
295
                    }
296
            }
297
        }
298 111
        return $text;
299
    }
300
301
    /**
302
     * @param  $resultNames
303
     * @return array
304
     */
305 111
    protected function prepareAbbreviation($resultNames)
306
    {
307 111
        $cnt = count($resultNames);
308
        /* Use of et-al-min and et-al-user-first enables et-al abbreviation. If the number of names in a name variable
309
        matches or exceeds the number set on et-al-min, the rendered name list is truncated after reaching the number of
310
        names set on et-al-use-first.  */
311
312 111
        if (isset($this->etAlMin) && isset($this->etAlUseFirst)) {
313 55
            if ($this->etAlMin <= $cnt) {
314 17
                if ($this->etAlUseLast && $this->etAlMin - $this->etAlUseFirst >= 2) {
315
                    /* et-al-use-last: When set to “true” (the default is “false”), name lists truncated by et-al
316
                    abbreviation are followed by the name delimiter, the ellipsis character, and the last name of the
317
                    original name list. This is only possible when the original name list has at least two more names
318
                    than the truncated name list (for this the value of et-al-use-first/et-al-subsequent-min must be at
319
                    least 2 less than the value of et-al-min/et-al-subsequent-use-first).*/
320
321 3
                    $lastName = array_pop($resultNames); //remove last Element and remember in $lastName
322
                }
323 17
                for ($i = $this->etAlUseFirst; $i < $cnt; ++$i) {
324 17
                    unset($resultNames[$i]);
325
                }
326
327 17
                $resultNames = array_values($resultNames);
328
329 17
                if (!empty($lastName)) { // append $lastName if exist
330 3
                    $resultNames[] = $lastName;
331
                }
332
333 17
                if ($this->parent->hasEtAl()) {
334
                    $this->etAl = $this->parent->getEtAl()->render(null);
335
                    return $resultNames;
336
                } else {
337 17
                    $this->etAl = CiteProc::getContext()->getLocale()->filter('terms', 'et-al')->single;
338 17
                    return $resultNames;
339
                }
340
            }
341 46
            return $resultNames;
342
        }
343 59
        return $resultNames;
344
    }
345
346
    /**
347
     * @param  $data
348
     * @param  stdClass $preceding
349
     * @return array
350
     * @throws CiteProcException
351
     */
352 3
    protected function renderSubsequentSubstitution($data, $preceding)
353
    {
354 3
        $resultNames = [];
355 3
        $subsequentSubstitution = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstitute();
356 3
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstituteRule();
357
358
        /**
359
         * @var string $type
360
         * @var stdClass $name
361
         */
362 3
        foreach ($data as $rank => $name) {
363
            switch ($subsequentSubstitutionRule) {
364
                /* “partial-each” - when one or more rendered names in the name variable match those in the preceding
365
                bibliographic entry, the value of subsequent-author-substitute substitutes for each matching name.
366
                Matching starts with the first name, and continues up to the first mismatch. */
367 3
                case SubsequentAuthorSubstituteRule::PARTIAL_EACH:
368 1
                    if (NameHelper::precedingHasAuthor($preceding, $name)) {
369 1
                        $resultNames[] = $subsequentSubstitution;
370
                    } else {
371 1
                        $resultNames[] = $this->formatName($name, $rank);
372
                    }
373 1
                    break;
374
                 /* “partial-first” - as “partial-each”, but substitution is limited to the first name of the name
375
                variable. */
376 2
                case SubsequentAuthorSubstituteRule::PARTIAL_FIRST:
377 1
                    if ($rank === 0) {
378 1
                        if ($preceding->author[0]->family === $name->family) {
379 1
                            $resultNames[] = $subsequentSubstitution;
380
                        } else {
381 1
                            $resultNames[] = $this->formatName($name, $rank);
382
                        }
383
                    } else {
384 1
                        $resultNames[] = $this->formatName($name, $rank);
385
                    }
386 1
                    break;
387
388
                 /* “complete-each” - requires a complete match like “complete-all”, but now the value of
389
                subsequent-author-substitute substitutes for each rendered name. */
390 1
                case SubsequentAuthorSubstituteRule::COMPLETE_EACH:
391
                    try {
392 1
                        if (NameHelper::identicalAuthors($preceding, $data)) {
393 1
                            $resultNames[] = $subsequentSubstitution;
394
                        } else {
395 1
                            $resultNames[] = $this->formatName($name, $rank);
396
                        }
397
                    } catch (CiteProcException $e) {
398
                        $resultNames[] = $this->formatName($name, $rank);
399
                    }
400 1
                    break;
401
            }
402
        }
403 3
        return $resultNames;
404
    }
405
406
    /**
407
     * @param  array $data
408
     * @param  int   $citationNumber
409
     * @return array
410
     * @throws CiteProcException
411
     */
412 111
    private function handleSubsequentAuthorSubstitution($data, $citationNumber)
413
    {
414 111
        $hasPreceding = CiteProc::getContext()->getCitationData()->hasKey($citationNumber - 1);
415 111
        $subsequentSubstitution = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstitute();
416 111
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstituteRule();
417 111
        $preceding = CiteProc::getContext()->getCitationData()->get($citationNumber - 1);
418
419
420 111
        if ($hasPreceding && !is_null($subsequentSubstitution) && !empty($subsequentSubstitutionRule)) {
421
            /**
422
             * @var stdClass $preceding
423
             */
424 8
            if ($subsequentSubstitutionRule == SubsequentAuthorSubstituteRule::COMPLETE_ALL) {
0 ignored issues
show
introduced by
The condition $subsequentSubstitutionR...ituteRule::COMPLETE_ALL is always false.
Loading history...
425
                try {
426 5
                    if (NameHelper::identicalAuthors($preceding, $data)) {
427 2
                        return [];
428
                    } else {
429 4
                        $resultNames = $this->getFormattedNames($data);
430
                    }
431 1
                } catch (CiteProcException $e) {
432 5
                    $resultNames = $this->getFormattedNames($data);
433
                }
434
            } else {
435 8
                $resultNames = $this->renderSubsequentSubstitution($data, $preceding);
436
            }
437
        } else {
438 111
            $resultNames = $this->getFormattedNames($data);
439
        }
440 111
        return $resultNames;
441
    }
442
443
444
    /**
445
     * @param  array $data
446
     * @return array
447
     * @throws CiteProcException
448
     */
449 111
    protected function getFormattedNames($data)
450
    {
451 111
        $resultNames = [];
452 111
        foreach ($data as $rank => $name) {
453 111
            $formatted = $this->formatName($name, $rank);
454 111
            $resultNames[] = NameHelper::addExtendedMarkup($this->variable, $name, $formatted);
455
        }
456 111
        return $resultNames;
457
    }
458
459
    /**
460
     * @param  $resultNames
461
     * @return string
462
     */
463 15
    protected function renderDelimiterPrecedesLastNever($resultNames)
464
    {
465 15
        $text = "";
466 15
        if (!$this->etAlUseLast) {
467 13
            if (count($resultNames) === 1) {
468 10
                $text = $resultNames[0];
469 10
            } elseif (count($resultNames) === 2) {
470 8
                $text = implode(" ", $resultNames);
471
            } else { // >2
472 7
                $lastName = array_pop($resultNames);
473 7
                $text = implode($this->delimiter, $resultNames)." ".$lastName;
474
            }
475
        }
476 15
        return $text;
477
    }
478
479
    /**
480
     * @param  $resultNames
481
     * @return string
482
     */
483 16
    protected function renderDelimiterPrecedesLastContextual($resultNames)
484
    {
485 16
        if (count($resultNames) === 1) {
486 9
            $text = $resultNames[0];
487 8
        } elseif (count($resultNames) === 2) {
488 7
            $text = implode(" ", $resultNames);
489
        } else {
490 1
            $text = implode($this->delimiter, $resultNames);
491
        }
492 16
        return $text;
493
    }
494
495
    /**
496
     * @param $resultNames
497
     */
498 111
    protected function addAnd(&$resultNames)
499
    {
500 111
        $count = count($resultNames);
501 111
        if (!empty($this->and) && $count > 1 && empty($this->etAl)) {
502 31
            $new = $this->and.' '.end($resultNames); // add and-prefix of the last name if "and" is defined
503
            // set prefixed last name at the last position of $resultNames array
504 31
            $resultNames[count($resultNames) - 1] = $new;
505
        }
506 111
    }
507
508
    /**
509
     * @param  $resultNames
510
     * @return array|string
511
     */
512 111
    protected function renderDelimiterPrecedesLast($resultNames)
513
    {
514 111
        $text = "";
515 111
        if (!empty($this->and) && empty($this->etAl)) {
516 56
            switch ($this->delimiterPrecedesLast) {
517 56
                case 'after-inverted-name':
518
                    //TODO: implement
519
                    break;
520 56
                case 'always':
521 30
                    $text = implode($this->delimiter, $resultNames);
522 30
                    break;
523 31
                case 'never':
524 15
                    $text = $this->renderDelimiterPrecedesLastNever($resultNames);
525 15
                    break;
526 16
                case 'contextual':
527
                default:
528 16
                    $text = $this->renderDelimiterPrecedesLastContextual($resultNames);
529
            }
530
        }
531 111
        return $text;
532
    }
533
534
535
    /**
536
     * @param stdClass $data
537
     * @param integer  $rank
538
     *
539
     * @return string
540
     * @throws CiteProcException
541
     */
542 111
    private function nameOrder($data, $rank)
543
    {
544 111
        $nameAsSortOrder = (($this->nameAsSortOrder === "first" && $rank === 0) || $this->nameAsSortOrder === "all");
545 111
        $demoteNonDroppingParticle = CiteProc::getContext()->getGlobalOptions()->getDemoteNonDroppingParticles();
546 111
        $normalizedName = NameHelper::normalizeName($data);
547 111
        if (StringHelper::isLatinString($normalizedName) || StringHelper::isCyrillicString($normalizedName)) {
548 110
            if ($this->form === "long"
549 110
                && $nameAsSortOrder
550 50
                && ((string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::NEVER
551 110
                || (string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::SORT_ONLY)
552
            ) {
553
                // [La] [Fontaine], [Jean] [de], [III]
554 31
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
555 31
                NameHelper::appendParticleTo($data, "given", "dropping-particle");
556
557 31
                list($family, $given) = $this->renderNameParts($data);
558
559 31
                $text = $family.(!empty($given) ? $this->sortSeparator.$given : "");
560 31
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
561 84
            } elseif ($this->form === "long"
562 84
                && $nameAsSortOrder
563 19
                && (is_null($demoteNonDroppingParticle)
564 84
                || (string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::DISPLAY_AND_SORT)
565
            ) {
566
                // [Fontaine], [Jean] [de] [La], [III]
567 19
                NameHelper::appendParticleTo($data, "given", "dropping-particle");
568 19
                NameHelper::appendParticleTo($data, "given", "non-dropping-particle");
569 19
                list($family, $given) = $this->renderNameParts($data);
570 19
                $text = $family;
571 19
                $text .= !empty($given) ? $this->sortSeparator.$given : "";
572 19
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
573 75
            } elseif ($this->form === "long" && $nameAsSortOrder && empty($demoteNonDroppingParticle)) {
574
                list($family, $given) = $this->renderNameParts($data);
575
                $text = $family;
576
                $text .= !empty($given) ? $this->delimiter.$given : "";
577
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
578 75
            } elseif ($this->form === "short") {
579
                // [La] [Fontaine]
580 24
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
581 24
                $text = $data->family;
582
            } else {// form "long" (default)
583
                // [Jean] [de] [La] [Fontaine] [III]
584 53
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
585 53
                NameHelper::prependParticleTo($data, "family", "dropping-particle");
586 53
                NameHelper::appendParticleTo($data, "family", "suffix");
587 53
                list($family, $given) = $this->renderNameParts($data);
588 110
                $text = !empty($given) ? $given." ".$family : $family;
589
            }
590 1
        } elseif (StringHelper::isAsianString(NameHelper::normalizeName($data))) {
591 1
            $text = $this->form === "long" ? $data->family . $data->given : $data->family;
592
        } else {
593
            $text = $this->form === "long" ? $data->family . " " . $data->given : $data->family;
594
        }
595 111
        return $text;
596
    }
597
598
    /**
599
     * @param  $data
600
     * @return array
601
     */
602 91
    private function renderNameParts($data)
603
    {
604 91
        $given = "";
605 91
        if (array_key_exists("family", $this->nameParts)) {
606 2
            $family = $this->nameParts["family"]->render($data);
607
        } else {
608 89
            $family = $data->family;
609
        }
610 91
        if (isset($data->given)) {
611 89
            if (array_key_exists("given", $this->nameParts)) {
612 2
                $given = $this->nameParts["given"]->render($data);
613
            } else {
614 87
                $given = $data->given;
615
            }
616
        }
617 91
        return [$family, $given];
618
    }
619
620
621
    /**
622
     * @return string
623
     */
624 6
    public function getForm()
625
    {
626 6
        return $this->form;
627
    }
628
629
    /**
630
     * @return string
631
     */
632
    public function isNameAsSortOrder()
633
    {
634
        return $this->nameAsSortOrder;
635
    }
636
637
    /**
638
     * @return string
639
     */
640
    public function getDelimiter()
641
    {
642
        return $this->delimiter;
643
    }
644
645
    /**
646
     * @param mixed $delimiter
647
     */
648 111
    public function setDelimiter($delimiter)
649
    {
650 111
        $this->delimiter = $delimiter;
651 111
    }
652
653
    /**
654
     * @return Names
655
     */
656
    public function getParent()
657
    {
658
        return $this->parent;
659
    }
660
}
661