Completed
Push — master ( 69f162...acb4bc )
by Sebastian
02:58
created

Name::precedingHasAuthor()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.2
c 0
b 0
f 0
cc 4
eloc 5
nc 3
nop 2
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
use Seboettg\CiteProc\CiteProc;
12
use Seboettg\CiteProc\Rendering\HasParent;
13
use Seboettg\CiteProc\Style\InheritableNameAttributesTrait;
14
use Seboettg\CiteProc\Style\SubsequentAuthorSubstituteRule;
15
use Seboettg\CiteProc\Styles\AffixesTrait;
16
use Seboettg\CiteProc\Styles\DelimiterTrait;
17
use Seboettg\CiteProc\Styles\FormattingTrait;
18
use Seboettg\CiteProc\Util\Factory;
19
use Seboettg\CiteProc\Util\StringHelper;
20
21
22
/**
23
 * Class Name
24
 *
25
 * The cs:name element, an optional child element of cs:names, can be used to describe the formatting of individual
26
 * names, and the separation of names within a name variable.
27
 *
28
 * @package Seboettg\CiteProc\Rendering\Name
29
 *
30
 * @author Sebastian Böttger <[email protected]>
31
 */
32
class Name implements HasParent
33
{
34
    use InheritableNameAttributesTrait,
35
        FormattingTrait,
36
        AffixesTrait,
37
        DelimiterTrait;
38
39
    /**
40
     * @var array
41
     */
42
    protected $nameParts;
43
44
    /**
45
     * Specifies the text string used to separate names in a name variable. Default is ”, ” (e.g. “Doe, Smith”).
46
     * @var
47
     */
48
    private $delimiter = ", ";
49
50
    /**
51
     * @var Names
52
     */
53
    private $parent;
54
55
    /**
56
     * @var \SimpleXMLElement
57
     */
58
    private $node;
59
60
    /**
61
     * @var string
62
     */
63
    private $etAl;
64
65
    /**
66
     * Name constructor.
67
     * @param \SimpleXMLElement $node
68
     * @param Names $parent
69
     */
70
    public function __construct(\SimpleXMLElement $node, Names $parent)
71
    {
72
        $this->node = $node;
73
        $this->parent = $parent;
74
75
        $this->nameParts = [];
76
77
        /** @var \SimpleXMLElement $child */
78
        foreach ($node->children() as $child) {
79
80
            switch ($child->getName()) {
81
                case "name-part":
82
                    /** @var NamePart $namePart */
83
                    $namePart = Factory::create($child, $this);
84
                    $this->nameParts[$namePart->getName()] = $namePart;
85
            }
86
        }
87
88
        foreach ($node->attributes() as $attribute) {
89
            switch ($attribute->getName()) {
90
                case 'form':
91
                    $this->form = (string) $attribute;
92
                    break;
93
            }
94
95
        }
96
97
        $this->initFormattingAttributes($node);
98
        $this->initAffixesAttributes($node);
99
        $this->initDelimiterAttributes($node);
100
    }
101
102
    public function render($data, $citationNumber = null)
103
    {
104
        if (!$this->attributesInitialized) {
105
            $this->initInheritableNameAttributes($this->node);
106
        }
107
        if ("text" === $this->and) {
108
            $this->and = CiteProc::getContext()->getLocale()->filter('terms', 'and')->single;
109
        } elseif ('symbol' === $this->and) {
110
            $this->and = '&#38;';
111
        }
112
113
        $lastName = null;
0 ignored issues
show
Unused Code introduced by
$lastName is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
114
115
        $resultNames = [];
116
117
        $hasPreceding = CiteProc::getContext()->getCitationItems()->hasKey($citationNumber-1);
118
        $subsequentSubstitution = CiteProc::getContext()->getCitationItems()->getSubsequentAuthorSubstitute();
119
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationItems()->getSubsequentAuthorSubstituteRule();
120
        $useSubseqSubstitution = !empty($subsequentSubstitution) && !empty($subsequentSubstitutionRule);
121
        $preceding = CiteProc::getContext()->getCitationItems()->get($citationNumber-1);
122
123
124
        if ($hasPreceding && $useSubseqSubstitution) {
125
            /** @var \stdClass $preceding */
126
            $identicalAuthors = $this->identicalAuthors($preceding, $data);
127
            if ($subsequentSubstitutionRule == SubsequentAuthorSubstituteRule::COMPLETE_ALL) {
128
                if ($identicalAuthors) {
129
                    return $subsequentSubstitution;
130
                } else {
131
                    $resultNames = $this->getFormattedNames($data, $resultNames);
132
                }
133
            } else {
134
                $resultNames = $this->renderSubsequentSubstitution($data, $preceding);
135
            }
136
        } else {
137
            $resultNames = $this->getFormattedNames($data, $resultNames);
138
        }
139
140
        $resultNames = $this->prepareAbbreviation($resultNames);
141
142
        if ($this->etAlUseLast) {
143
            /* When set to “true” (the default is “false”), name lists truncated by et-al abbreviation are followed by
144
            the name delimiter, the ellipsis character, and the last name of the original name list. This is only
145
            possible when the original name list has at least two more names than the truncated name list (for this
146
            the value of et-al-use-first/et-al-subsequent-min must be at least 2 less than the value of
147
            et-al-min/et-al-subsequent-use-first). */
148
            $this->and = "…"; // set "and"
149
            $this->etAl = null; //reset $etAl;
150
        }
151
152
        /* add "and" */
153
        $count = count($resultNames);
154
        if (!empty($this->and) && $count > 1 && empty($this->etAl)) {
155
            $new = $this->and . ' ' . end($resultNames); // add and-prefix of the last name if "and" is defined
156
            $resultNames[count($resultNames) - 1] = $new; //set prefixed last name at the last position of $resultNames array
157
        }
158
159
        if (!empty($this->and) && empty($this->etAl)) {
160
            switch ($this->delimiterPrecedesLast) {
161
                case 'after-inverted-name':
162
                    //TODO: implement
163
                    break;
164
                case 'always':
165
                    $text = implode($this->delimiter, $resultNames);
166
                    break;
167
                case 'never':
168
                    if (!$this->etAlUseLast) {
169
                        if (count($resultNames) === 1) {
170
                            $text = $resultNames[0];
171 View Code Duplication
                        } else if (count($resultNames) === 2) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
                            $text = implode(" ", $resultNames);
173
                        } else { // >2
174
                            $lastName = array_pop($resultNames);
175
                            $text = implode($this->delimiter, $resultNames) . " " . $lastName;
176
                        }
177
                    } /*else {
0 ignored issues
show
Unused Code Comprehensibility introduced by
51% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
178
                        if (count($resultNames) === 1) {
179
                            $text = $resultNames[0];
180
                        } else if (count($resultNames) === 2) {
181
                            $text = implode(" ", $resultNames);
182
                        } else { // >2
183
                            $lastName = array_pop($resultNames);
184
                            $text = implode($this->delimiter, $resultNames) . ", " . $lastName;
185
                        }
186
                    }*/
187
188
                    break;
189
                case 'contextual':
190
                default:
191 View Code Duplication
                    if (count($resultNames) === 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
                        $text = $resultNames[0];
193
                    } else if (count($resultNames) === 2) {
194
                        $text = implode(" ", $resultNames);
195
                    } else {
196
                        $text = implode($this->delimiter, $resultNames);
197
                    }
198
            }
199
        } else {
200
            $text = implode($this->delimiter, $resultNames);
201
        }
202
203
204
205
        //append et al abbreviation
206
        if (count($data) > 1 &&
207
            !empty($resultNames) &&
208
            !empty($this->etAl) &&
209
            !empty($this->etAlMin) &&
210
            !empty($this->etAlUseFirst)) {
211
212
            $text = $this->appendEtAl($text, $resultNames);
0 ignored issues
show
Bug introduced by
The variable $text does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
213
        }
214
215
        /* A third value, “count”, returns the total number of names that would otherwise be rendered by the use of the
216
        cs:names element (taking into account the effects of et-al abbreviation and editor/translator collapsing),
217
        which allows for advanced sorting. */
218
219
        if ($this->form == 'count') {
220
            return (int)count($resultNames);
221
        }
222
223
        return $text;
224
    }
225
226
    private function formatName($name, $rank)
227
    {
228
        $nameObj = $this->cloneNamePOSC($name);
229
230
        $useInitials = $this->initialize && !empty($this->initializeWith);
231
        if ($useInitials && isset($name->given)) {
232
            $nameObj->given = StringHelper::initializeBySpaceOrHyphen($name->given, $this->initializeWith);
233
        }
234
235
        // format name-parts
236
        if (count($this->nameParts) > 0) {
237
            /** @var NamePart $namePart */
238
            foreach ($this->nameParts as $namePart) {
239
                $nameObj->{$namePart->getName()} =   $namePart->render($name);
240
            }
241
        }
242
243
        $return = $this->getNamesString($nameObj, $rank);
244
245
        return trim($return);
246
    }
247
248
    /**
249
     * @param \stdClass $name
250
     * @param int $rank
251
     * @return string
252
     */
253
    private function getNamesString($name, $rank)
254
    {
255
        $text = "";
256
257
        if (!isset($name->family)) {
258
            return $text;
259
        }
260
261
        $given = !empty($name->given) ? $this->format(trim($name->given)) : "";
262
        $nonDroppingParticle = isset($name->{'non-dropping-particle'}) ? $name->{'non-dropping-particle'} : "";
263
        $droppingParticle = isset($name->{'dropping-particle'}) ? $name->{'dropping-particle'} : "";
264
        $suffix = (isset($name->{'suffix'})) ? $name->{'suffix'} : "";
265
266
        if (isset($name->family)) {
267
            $family = $this->format($name->family);
268
            if ($this->form == 'short') {
269
                $text = (!empty($nonDroppingParticle) ? $nonDroppingParticle . " " : "") . $family;
270
            } else {
271
                switch ($this->nameAsSortOrder) {
272
273
                    case 'all':
274
                    case 'first':
275
                        if ($this->nameAsSortOrder === "first" && $rank !== 0) {
276
                            break;
277
                        }
278
                        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
279
                        use form "[non-dropping particel] family name,
280
                        given name [dropping particle], [suffix]"
281
                        */
282
                        $text  = !empty($nonDroppingParticle) ? "$nonDroppingParticle " : "";
283
                        $text .= $family;
284
                        $text .= !empty($given) ? $this->sortSeparator . $given : "";
285
                        $text .= !empty($droppingParticle) ? " $droppingParticle" : "";
286
                        $text .= !empty($suffix) ? $this->sortSeparator . $suffix : "";
287
288
                        //remove last comma when no suffix exist.
289
                        $text = trim($text);
290
                        $text = substr($text, -1) === $this->sortSeparator ? substr($text, 0, strlen($text) - 1) : $text;
291
                        break;
292
                    default:
293
                        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
294
                        use form "given name [dropping particles] [non-dropping particles] family name [suffix]"
295
                        e.g. [Jean] [de] [La] [Fontaine] [III]
296
                        */
297
                        $text = sprintf(
298
                            "%s %s %s %s %s",
299
                            $given,
300
                            $droppingParticle,
301
                            $nonDroppingParticle,
302
                            $family,
303
                            $suffix);
304
305
                }
306
            }
307
        }
308
309
        //contains nbsp prefixed by normal space or followed by normal space?
310
        $text = htmlentities($text);
311
        if (strpos($text, " &nbsp;") !== false || strpos($text, "&nbsp; ") !== false) {
312
313
            $text = preg_replace("/[\s]+/", "", $text); //remove normal spaces
314
            return preg_replace("/&nbsp;+/", " ", $text);
315
        }
316
        $text = html_entity_decode(preg_replace("/[\s]+/", " ", $text));
317
        return trim($text);
318
    }
319
320
    public function getOptions()
321
    {
322
        $ignore = ["namePart", "parent", "substitute"];
323
        $options = [];
324
        $reflectedName = new \ReflectionClass($this);
325
326
        foreach ($reflectedName->getProperties() as $property) {
327
            $property->setAccessible(true);
328
            if (in_array($property->getName(), $ignore)) {
329
                continue;
330
            } else if ($property->getName() == "and" && $property->getValue($this) === "&#38;") {
331
                $options["and"] = "symbol";
332
            } else {
333
                $propValue = $property->getValue($this);
334
                if (isset($propValue) && !empty($propValue)) {
335
                    $options[StringHelper::camelCase2Hyphen($property->getName())] = $propValue;
336
                }
337
            }
338
        }
339
        return $options;
340
    }
341
342
    /**
343
     * @param $name
344
     * @return \stdClass
345
     */
346
    private function cloneNamePOSC($name)
347
    {
348
        $nameObj = new \stdClass();
349
        if (isset($name->family)) {
350
            $nameObj->family = $name->family;
351
        }
352
        if (isset($name->given)) {
353
            $nameObj->given = $name->given;
354
        }
355
        if (isset($name->{'non-dropping-particle'})) {
356
            $nameObj->{'non-dropping-particle'} = $name->{'non-dropping-particle'};
357
        }
358
        if (isset($name->{'dropping-particle'})) {
359
            $nameObj->{'dropping-particle'} = $name->{'dropping-particle'};
360
        }
361
        if (isset($name->{'suffix'})) {
362
            $nameObj->{'suffix'} = $name->{'suffix'};
363
        }
364
        return $nameObj;
365
    }
366
367
    /**
368
     * @param $text
369
     * @param $resultNames
370
     * @return string
371
     */
372
    protected function appendEtAl($text, $resultNames)
373
    {
374
        /* By default, when a name list is truncated to a single name, the name and the “et-al” (or “and others”)
375
        term are separated by a space (e.g. “Doe et al.”). When a name list is truncated to two or more names, the
376
        name delimiter is used (e.g. “Doe, Smith, et al.”). This behavior can be changed with the
377
        delimiter-precedes-et-al attribute. */
378
379
        switch ($this->delimiterPrecedesEtAl) {
380
            case 'never':
381
                $text = $text . " " . $this->etAl;
382
                break;
383
            case 'always':
384
                $text = $text . $this->delimiter . $this->etAl;
385
                break;
386
            case 'contextual':
387
            default:
388
                if (count($resultNames) === 1) {
389
                    $text .= " " . $this->etAl;
390
                } else {
391
                    $text .= $this->delimiter . $this->etAl;
392
                }
393
        }
394
395
        return $text;
396
    }
397
398
    /**
399
     * @param $resultNames
400
     * @return array
401
     */
402
    protected function prepareAbbreviation($resultNames)
403
    {
404
        $cnt = count($resultNames);
405
        /* Use of et-al-min and et-al-user-first enables et-al abbreviation. If the number of names in a name variable
406
        matches or exceeds the number set on et-al-min, the rendered name list is truncated after reaching the number of
407
        names set on et-al-use-first.  */
408
409
        if (isset($this->etAlMin) && isset($this->etAlUseFirst)) {
410
411
            if ($this->etAlMin <= $cnt) {
412
                if ($this->etAlUseLast && $this->etAlMin - $this->etAlUseFirst >= 2) {
413
                    /* et-al-use-last: When set to “true” (the default is “false”), name lists truncated by et-al
414
                    abbreviation are followed by the name delimiter, the ellipsis character, and the last name of the
415
                    original name list. This is only possible when the original name list has at least two more names
416
                    than the truncated name list (for this the value of et-al-use-first/et-al-subsequent-min must be at
417
                    least 2 less than the value of et-al-min/et-al-subsequent-use-first).*/
418
419
                    $lastName = array_pop($resultNames); //remove last Element and remember in $lastName
420
421
                }
422
                for ($i = $this->etAlUseFirst; $i < $cnt; ++$i) {
423
                    unset($resultNames[$i]);
424
                }
425
426
                $resultNames = array_values($resultNames);
427
428
                if (!empty($lastName)) { // append $lastName if exist
429
                    $resultNames[] = $lastName;
430
                }
431
432
                if ($this->parent->hasEtAl()) {
433
                    $this->etAl = $this->parent->getEtAl()->render(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array|object<Seboettg\CiteProc\Data\DataList>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
434
                    return $resultNames;
435
                } else {
436
                    $this->etAl = CiteProc::getContext()->getLocale()->filter('terms', 'et-al')->single;
437
                    return $resultNames;
438
                }
439
            }
440
            return $resultNames;
441
        }
442
        return $resultNames;
443
    }
444
445
446
    public function getParent()
447
    {
448
        return $this->parent;
449
    }
450
451
    /**
452
     * @param $data
453
     * @param $preceding
454
     * @return array
455
     */
456
    protected function renderSubsequentSubstitution($data, $preceding)
457
    {
458
        $resultNames = [];
459
        $subsequentSubstitution = CiteProc::getContext()->getCitationItems()->getSubsequentAuthorSubstitute();
460
        $subsequentSubstitutionRule = CiteProc::getContext()->getCitationItems()->getSubsequentAuthorSubstituteRule();
461
462
        /**
463
         * @var string $type
464
         * @var array $name
465
         */
466
        foreach ($data as $rank => $name) {
467
468
            switch ($subsequentSubstitutionRule) {
469
470
                /* “partial-each” - when one or more rendered names in the name variable match those in the preceding
471
                bibliographic entry, the value of subsequent-author-substitute substitutes for each matching name.
472
                Matching starts with the first name, and continues up to the first mismatch. */
473 View Code Duplication
                case SubsequentAuthorSubstituteRule::PARTIAL_EACH:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
474
475
                    if ($this->precedingHasAuthor($preceding, $name)) {
476
                        $resultNames[] = $subsequentSubstitution;
477
                    } else {
478
                        $resultNames[] = $this->formatName($name, $rank);
479
                    }
480
                    break;
481
482
483
                /* “partial-first” - as “partial-each”, but substitution is limited to the first name of the name
484
                variable. */
485
                case SubsequentAuthorSubstituteRule::PARTIAL_FIRST:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
486
487
                    if ($rank === 0) {
488
                        if ($preceding->author[0]->family === $name->family) {
489
                            $resultNames[] = $subsequentSubstitution;
490
                        } else {
491
                            $resultNames[] = $this->formatName($name, $rank);
492
                        }
493
                    } else {
494
                        $resultNames[] = $this->formatName($name, $rank);
495
                    }
496
                    break;
497
498
                /* “complete-each” - requires a complete match like “complete-all”, but now the value of
499
                subsequent-author-substitute substitutes for each rendered name. */
500 View Code Duplication
                case SubsequentAuthorSubstituteRule::COMPLETE_EACH:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
501
                    if ($this->identicalAuthors($preceding, $data)) {
502
                        $resultNames[] =  $subsequentSubstitution;
503
                    } else {
504
                        $resultNames[] = $this->formatName($name, $rank);
505
                    }
506
                    break;
507
            }
508
        }
509
        return $resultNames;
510
    }
511
512
    public function precedingHasAuthor($preceding, $name)
513
    {
514
        foreach ($preceding->author as $author) {
515
            if ($author->family === $name->family && $author->given === $name->given) {
516
                return true;
517
            }
518
        }
519
        return false;
520
    }
521
522
    private function identicalAuthors($precedingItem, $currentAuthor)
523
    {
524
        if (count($precedingItem->author) !== count($currentAuthor)) {
525
            return false;
526
        }
527
        foreach ($currentAuthor as $current) {
528
            if ($this->precedingHasAuthor($precedingItem, $current)) {
529
                continue;
530
            }
531
            return false;
532
        }
533
        return true;
534
    }
535
536
    /**
537
     * @param $data
538
     * @param $resultNames
539
     * @return array
540
     */
541
    protected function getFormattedNames($data, $resultNames)
542
    {
543
        foreach ($data as $rank => $name) {
544
            $resultNames[] = $this->formatName($name, $rank);
545
        }
546
        return $resultNames;
547
    }
548
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
549