Passed
Push — new-api ( f151f9...5a646f )
by Sebastian
04:44
created

Position   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 61
Duplicated Lines 0 %

Test Coverage

Coverage 76.92%

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 61
ccs 10
cts 13
cp 0.7692
rs 10
c 0
b 0
f 0
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getPosition() 0 8 4
A validate() 0 14 6
A isOnLastPosition() 0 4 2
A __construct() 0 5 1
1
<?php
2
declare(strict_types=1);
3
/*
4
 * citeproc-php
5
 *
6
 * @link        http://github.com/seboettg/citeproc-php for the source repository
7
 * @copyright   Copyright (c) 2016 Sebastian Böttger.
8
 * @license     https://opensource.org/licenses/MIT
9
 */
10
11
namespace Seboettg\CiteProc\Constraint;
12
13
use Seboettg\CiteProc\CiteProc;
14
use Seboettg\CiteProc\Config\RenderingMode;
15
use Seboettg\CiteProc\Rendering\Observer\RenderingObserver;
16
use Seboettg\CiteProc\Rendering\Observer\RenderingObserverTrait;
17
use stdClass;
18
19
/**
20
 * Class Position
21
 *
22
 * Tests whether the cite position matches the given positions (terminology: citations consist of one or more cites to
23
 * individual items). When called within the scope of cs:bibliography, position tests “false”. The positions that can
24
 * be tested are:
25
 *   - “first”: position of cites that are the first to reference an item
26
 *   - “ibid”/”ibid-with-locator”/”subsequent”: cites referencing previously cited items have the “subsequent” position.
27
 *     Such cites may also have the “ibid” or “ibid-with-locator” position when:
28
 *     a) the current cite immediately follows on another cite, within the same citation, that references the
29
 *        same item, or
30
 *     b) the current cite is the first cite in the citation, and the previous citation consists of a single cite
31
 *        referencing the same item
32
 *     If either requirement is met, the presence of locators determines which position is assigned:
33
 *     -  Preceding cite does not have a locator: if the current cite has a locator, the position of the current cite is
34
 *        “ibid-with-locator”. Otherwise the position is “ibid”.
35
 *     -  Preceding cite does have a locator: if the current cite has the same locator, the position of the current cite
36
 *        is “ibid”. If the locator differs the position is “ibid-with-locator”. If the current cite lacks a locator
37
 *        its only position is “subsequent”.
38
 *   - “near-note”: position of a cite following another cite referencing the same item. Both cites have to be located
39
 *     in foot or endnotes, and the distance between both cites may not exceed the maximum distance (measured in number
40
 *     of foot or endnotes) set with the near-note-distance option.
41
 *
42
 * Whenever position=”ibid-with-locator” tests true, position=”ibid” also tests true. And whenever position=”ibid” or
43
 * position=”near-note” test true, position=”subsequent” also tests true.
44
 *
45
 * @package Seboettg\CiteProc\Constraint
46
 */
47
class Position implements Constraint, RenderingObserver
48
{
49
    use RenderingObserverTrait;
50
51
    const FIRST = "first";
52
    const IBID = "ibid";
53
    const IBID_WITH_LOCATOR = "ibid-with-locator";
54
    const SUBSEQUENT = "subsequent";
55
    const NEAR_NOTE = "near-note";
56
57
    private $value;
58
59
    private $match;
60
61 3
    public function __construct($value, $match = "all")
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$match" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$match"; expected 0 but found 1
Loading history...
62
    {
63 3
        $this->value = $value;
64 3
        $this->match = $match;
65 3
        $this->initObserver();
66 3
    }
67
68
    /**
69
     * @codeCoverageIgnore
70
     * @param stdClass $value
71
     * @param int|null $citationNumber
72
     * @return bool
73
     */
74
    public function validate(stdClass $value, int $citationNumber = null): bool
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$citationNumber" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$citationNumber"; expected 0 but found 1
Loading history...
75
    {
76
        if ($this->mode->equals(RenderingMode::BIBLIOGRAPHY())) {
77
            return false;
78
        }
79
        switch ($this->value) {
80
            case self::FIRST:
81
                return $this->getPosition($value) === null;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getPosition($value) targeting Seboettg\CiteProc\Constr...Position::getPosition() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
82
            case self::IBID:
83
            case self::IBID_WITH_LOCATOR:
84
            case self::SUBSEQUENT:
85
                return $this->isOnLastPosition($value);
86
        }
87
        return true;
88
    }
89
90 1
    private function getPosition(stdClass $object): ?int
91
    {
92 1
        foreach ($this->citedItems as $key => $value) {
93 1
            if (!empty($value->{'id'}) && $value->{'id'} === $object->{'id'}) {
94 1
                return $key;
95
            }
96
        }
97 1
        return null;
98
    }
99
100
    /**
101
     * @param stdClass $object
102
     * @return bool
103
     */
104
    private function isOnLastPosition(stdClass $object): bool
105
    {
106
        $lastCitedItem = $this->citedItems->last();
107
        return !empty($lastCitedItem) ? $lastCitedItem->{'id'} === $object->{'id'} : false;
108
    }
109
}
110