Passed
Pull Request — master (#150)
by Sebastian
10:47 queued 03:08
created

Name::isEtAl()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 6
c 2
b 0
f 0
nc 6
nop 2
dl 0
loc 8
ccs 7
cts 7
cp 1
crap 6
rs 9.2222
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
        return 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
262
    /**
263
     * @param  $data
264
     * @param  $text
265
     * @param  $resultNames
266
     * @return string
267
     */
268 111
    protected function appendEtAl($data, $text, $resultNames)
269
    {
270
        //append et al abbreviation
271 111
        if ($this->isEtAl($data, $resultNames)) {
272
            /* By default, when a name list is truncated to a single name, the name and the “et-al” (or “and others”)
273
            term are separated by a space (e.g. “Doe et al.”). When a name list is truncated to two or more names, the
274
            name delimiter is used (e.g. “Doe, Smith, et al.”). This behavior can be changed with the
275
            delimiter-precedes-et-al attribute. */
276
277 14
            switch ($this->delimiterPrecedesEtAl) {
278 14
                case 'never':
279 5
                    $text = $text . " " . $this->etAl;
280 5
                    break;
281 9
                case 'always':
282 1
                    $text = $text . $this->delimiter . $this->etAl;
283 1
                    break;
284 9
                case 'contextual':
285
                default:
286 9
                    if (count($resultNames) === 1) {
287 4
                        $text .= " " . $this->etAl;
288
                    } else {
289 5
                        $text .= $this->delimiter . $this->etAl;
290
                    }
291
            }
292
        }
293 111
        return $text;
294
    }
295
296
    /**
297
     * @param  $resultNames
298
     * @return array
299
     */
300 111
    protected function prepareAbbreviation($resultNames)
301
    {
302 111
        $cnt = count($resultNames);
303
        /* Use of et-al-min and et-al-user-first enables et-al abbreviation. If the number of names in a name variable
304
        matches or exceeds the number set on et-al-min, the rendered name list is truncated after reaching the number of
305
        names set on et-al-use-first.  */
306
307 111
        if (isset($this->etAlMin) && isset($this->etAlUseFirst)) {
308 55
            if ($this->etAlMin <= $cnt) {
309 17
                if ($this->etAlUseLast && $this->etAlMin - $this->etAlUseFirst >= 2) {
310
                    /* et-al-use-last: When set to “true” (the default is “false”), name lists truncated by et-al
311
                    abbreviation are followed by the name delimiter, the ellipsis character, and the last name of the
312
                    original name list. This is only possible when the original name list has at least two more names
313
                    than the truncated name list (for this the value of et-al-use-first/et-al-subsequent-min must be at
314
                    least 2 less than the value of et-al-min/et-al-subsequent-use-first).*/
315
316 3
                    $lastName = array_pop($resultNames); //remove last Element and remember in $lastName
317
                }
318 17
                for ($i = $this->etAlUseFirst; $i < $cnt; ++$i) {
319 17
                    unset($resultNames[$i]);
320
                }
321
322 17
                $resultNames = array_values($resultNames);
323
324 17
                if (!empty($lastName)) { // append $lastName if exist
325 3
                    $resultNames[] = $lastName;
326
                }
327
328 17
                if ($this->parent->hasEtAl()) {
329
                    $this->etAl = $this->parent->getEtAl()->render(null);
330
                    return $resultNames;
331
                } else {
332 17
                    $this->etAl = CiteProc::getContext()->getLocale()->filter('terms', 'et-al')->single;
333 17
                    return $resultNames;
334
                }
335
            }
336 46
            return $resultNames;
337
        }
338 59
        return $resultNames;
339
    }
340
341
    /**
342
     * @param  $data
343
     * @param  stdClass $preceding
344
     * @return array
345
     * @throws CiteProcException
346
     */
347 3
    protected function renderSubsequentSubstitution($data, $preceding)
348
    {
349 3
        $resultNames = [];
350 3
        $subsequentSubstitution = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstitute();
351 3
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstituteRule();
352
353
        /**
354
         * @var string $type
355
         * @var stdClass $name
356
         */
357 3
        foreach ($data as $rank => $name) {
358
            switch ($subsequentSubstitutionRule) {
359
                /* “partial-each” - when one or more rendered names in the name variable match those in the preceding
360
                bibliographic entry, the value of subsequent-author-substitute substitutes for each matching name.
361
                Matching starts with the first name, and continues up to the first mismatch. */
362 3
                case SubsequentAuthorSubstituteRule::PARTIAL_EACH:
363 1
                    if (NameHelper::precedingHasAuthor($preceding, $name)) {
364 1
                        $resultNames[] = $subsequentSubstitution;
365
                    } else {
366 1
                        $resultNames[] = $this->formatName($name, $rank);
367
                    }
368 1
                    break;
369
                 /* “partial-first” - as “partial-each”, but substitution is limited to the first name of the name
370
                variable. */
371 2
                case SubsequentAuthorSubstituteRule::PARTIAL_FIRST:
372 1
                    if ($rank === 0) {
373 1
                        if ($preceding->author[0]->family === $name->family) {
374 1
                            $resultNames[] = $subsequentSubstitution;
375
                        } else {
376 1
                            $resultNames[] = $this->formatName($name, $rank);
377
                        }
378
                    } else {
379 1
                        $resultNames[] = $this->formatName($name, $rank);
380
                    }
381 1
                    break;
382
383
                 /* “complete-each” - requires a complete match like “complete-all”, but now the value of
384
                subsequent-author-substitute substitutes for each rendered name. */
385 1
                case SubsequentAuthorSubstituteRule::COMPLETE_EACH:
386
                    try {
387 1
                        if (NameHelper::identicalAuthors($preceding, $data)) {
388 1
                            $resultNames[] = $subsequentSubstitution;
389
                        } else {
390 1
                            $resultNames[] = $this->formatName($name, $rank);
391
                        }
392
                    } catch (CiteProcException $e) {
393
                        $resultNames[] = $this->formatName($name, $rank);
394
                    }
395 1
                    break;
396
            }
397
        }
398 3
        return $resultNames;
399
    }
400
401
    /**
402
     * @param  array $data
403
     * @param  int   $citationNumber
404
     * @return array
405
     * @throws CiteProcException
406
     */
407 111
    private function handleSubsequentAuthorSubstitution($data, $citationNumber)
408
    {
409 111
        $hasPreceding = CiteProc::getContext()->getCitationData()->hasKey($citationNumber - 1);
410 111
        $subsequentSubstitution = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstitute();
411 111
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationData()->getSubsequentAuthorSubstituteRule();
412 111
        $preceding = CiteProc::getContext()->getCitationData()->get($citationNumber - 1);
413
414
415 111
        if ($hasPreceding && !is_null($subsequentSubstitution) && !empty($subsequentSubstitutionRule)) {
416
            /**
417
             * @var stdClass $preceding
418
             */
419 8
            if ($subsequentSubstitutionRule == SubsequentAuthorSubstituteRule::COMPLETE_ALL) {
0 ignored issues
show
introduced by
The condition $subsequentSubstitutionR...ituteRule::COMPLETE_ALL is always false.
Loading history...
420
                try {
421 5
                    if (NameHelper::identicalAuthors($preceding, $data)) {
422 2
                        return [];
423
                    } else {
424 4
                        $resultNames = $this->getFormattedNames($data);
425
                    }
426 1
                } catch (CiteProcException $e) {
427 5
                    $resultNames = $this->getFormattedNames($data);
428
                }
429
            } else {
430 8
                $resultNames = $this->renderSubsequentSubstitution($data, $preceding);
431
            }
432
        } else {
433 111
            $resultNames = $this->getFormattedNames($data);
434
        }
435 111
        return $resultNames;
436
    }
437
438
439
    /**
440
     * @param  array $data
441
     * @return array
442
     * @throws CiteProcException
443
     */
444 111
    protected function getFormattedNames($data)
445
    {
446 111
        $resultNames = [];
447 111
        foreach ($data as $rank => $name) {
448 111
            $formatted = $this->formatName($name, $rank);
449 111
            $resultNames[] = NameHelper::addExtendedMarkup($this->variable, $name, $formatted);
450
        }
451 111
        return $resultNames;
452
    }
453
454
    /**
455
     * @param  $resultNames
456
     * @return string
457
     */
458 15
    protected function renderDelimiterPrecedesLastNever($resultNames)
459
    {
460 15
        $text = "";
461 15
        if (!$this->etAlUseLast) {
462 13
            if (count($resultNames) === 1) {
463 10
                $text = $resultNames[0];
464 10
            } elseif (count($resultNames) === 2) {
465 8
                $text = implode(" ", $resultNames);
466
            } else { // >2
467 7
                $lastName = array_pop($resultNames);
468 7
                $text = implode($this->delimiter, $resultNames)." ".$lastName;
469
            }
470
        }
471 15
        return $text;
472
    }
473
474
    /**
475
     * @param  $resultNames
476
     * @return string
477
     */
478 16
    protected function renderDelimiterPrecedesLastContextual($resultNames)
479
    {
480 16
        if (count($resultNames) === 1) {
481 9
            $text = $resultNames[0];
482 8
        } elseif (count($resultNames) === 2) {
483 7
            $text = implode(" ", $resultNames);
484
        } else {
485 1
            $text = implode($this->delimiter, $resultNames);
486
        }
487 16
        return $text;
488
    }
489
490
    /**
491
     * @param $resultNames
492
     */
493 111
    protected function addAnd(&$resultNames)
494
    {
495 111
        $count = count($resultNames);
496 111
        if (!empty($this->and) && $count > 1 && empty($this->etAl)) {
497 31
            $new = $this->and.' '.end($resultNames); // add and-prefix of the last name if "and" is defined
498
            // set prefixed last name at the last position of $resultNames array
499 31
            $resultNames[count($resultNames) - 1] = $new;
500
        }
501 111
    }
502
503
    /**
504
     * @param  $resultNames
505
     * @return array|string
506
     */
507 111
    protected function renderDelimiterPrecedesLast($resultNames)
508
    {
509 111
        $text = "";
510 111
        if (!empty($this->and) && empty($this->etAl)) {
511 56
            switch ($this->delimiterPrecedesLast) {
512 56
                case 'after-inverted-name':
513
                    //TODO: implement
514
                    break;
515 56
                case 'always':
516 30
                    $text = implode($this->delimiter, $resultNames);
517 30
                    break;
518 31
                case 'never':
519 15
                    $text = $this->renderDelimiterPrecedesLastNever($resultNames);
520 15
                    break;
521 16
                case 'contextual':
522
                default:
523 16
                    $text = $this->renderDelimiterPrecedesLastContextual($resultNames);
524
            }
525
        }
526 111
        return $text;
527
    }
528
529
530
    /**
531
     * @param stdClass $data
532
     * @param integer  $rank
533
     *
534
     * @return string
535
     * @throws CiteProcException
536
     */
537 111
    private function nameOrder($data, $rank)
538
    {
539 111
        $nameAsSortOrder = (($this->nameAsSortOrder === "first" && $rank === 0) || $this->nameAsSortOrder === "all");
540 111
        $demoteNonDroppingParticle = CiteProc::getContext()->getGlobalOptions()->getDemoteNonDroppingParticles();
541 111
        $normalizedName = NameHelper::normalizeName($data);
542 111
        if (StringHelper::isLatinString($normalizedName) || StringHelper::isCyrillicString($normalizedName)) {
543 110
            if ($this->form === "long"
544 110
                && $nameAsSortOrder
545 50
                && ((string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::NEVER
546 110
                || (string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::SORT_ONLY)
547
            ) {
548
                // [La] [Fontaine], [Jean] [de], [III]
549 31
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
550 31
                NameHelper::appendParticleTo($data, "given", "dropping-particle");
551
552 31
                list($family, $given) = $this->renderNameParts($data);
553
554 31
                $text = $family.(!empty($given) ? $this->sortSeparator.$given : "");
555 31
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
556 84
            } elseif ($this->form === "long"
557 84
                && $nameAsSortOrder
558 19
                && (is_null($demoteNonDroppingParticle)
559 84
                || (string) $demoteNonDroppingParticle === DemoteNonDroppingParticle::DISPLAY_AND_SORT)
560
            ) {
561
                // [Fontaine], [Jean] [de] [La], [III]
562 19
                NameHelper::appendParticleTo($data, "given", "dropping-particle");
563 19
                NameHelper::appendParticleTo($data, "given", "non-dropping-particle");
564 19
                list($family, $given) = $this->renderNameParts($data);
565 19
                $text = $family;
566 19
                $text .= !empty($given) ? $this->sortSeparator.$given : "";
567 19
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
568 75
            } elseif ($this->form === "long" && $nameAsSortOrder && empty($demoteNonDroppingParticle)) {
569
                list($family, $given) = $this->renderNameParts($data);
570
                $text = $family;
571
                $text .= !empty($given) ? $this->delimiter.$given : "";
572
                $text .= !empty($data->suffix) ? $this->sortSeparator.$data->suffix : "";
573 75
            } elseif ($this->form === "short") {
574
                // [La] [Fontaine]
575 24
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
576 24
                $text = $data->family;
577
            } else {// form "long" (default)
578
                // [Jean] [de] [La] [Fontaine] [III]
579 53
                NameHelper::prependParticleTo($data, "family", "non-dropping-particle");
580 53
                NameHelper::prependParticleTo($data, "family", "dropping-particle");
581 53
                NameHelper::appendParticleTo($data, "family", "suffix");
582 53
                list($family, $given) = $this->renderNameParts($data);
583 110
                $text = !empty($given) ? $given." ".$family : $family;
584
            }
585 1
        } elseif (StringHelper::isAsianString(NameHelper::normalizeName($data))) {
586 1
            $text = $this->form === "long" ? $data->family . $data->given : $data->family;
587
        } else {
588
            $text = $this->form === "long" ? $data->family . " " . $data->given : $data->family;
589
        }
590 111
        return $text;
591
    }
592
593
    /**
594
     * @param  $data
595
     * @return array
596
     */
597 91
    private function renderNameParts($data)
598
    {
599 91
        $given = "";
600 91
        if (array_key_exists("family", $this->nameParts)) {
601 2
            $family = $this->nameParts["family"]->render($data);
602
        } else {
603 89
            $family = $data->family;
604
        }
605 91
        if (isset($data->given)) {
606 89
            if (array_key_exists("given", $this->nameParts)) {
607 2
                $given = $this->nameParts["given"]->render($data);
608
            } else {
609 87
                $given = $data->given;
610
            }
611
        }
612 91
        return [$family, $given];
613
    }
614
615
616
    /**
617
     * @return string
618
     */
619 6
    public function getForm()
620
    {
621 6
        return $this->form;
622
    }
623
624
    /**
625
     * @return string
626
     */
627
    public function isNameAsSortOrder()
628
    {
629
        return $this->nameAsSortOrder;
630
    }
631
632
    /**
633
     * @return string
634
     */
635
    public function getDelimiter()
636
    {
637
        return $this->delimiter;
638
    }
639
640
    /**
641
     * @param mixed $delimiter
642
     */
643 111
    public function setDelimiter($delimiter)
644
    {
645 111
        $this->delimiter = $delimiter;
646 111
    }
647
648
    /**
649
     * @return Names
650
     */
651
    public function getParent()
652
    {
653
        return $this->parent;
654
    }
655
}
656