Passed
Push — master ( d2184e...ee1eb5 )
by Sebastian
04:46
created

Name::cloneNamePOSC()   A

Complexity

Conditions 6
Paths 32

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 6

Importance

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