Position::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
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\Collection\ArrayList;
15
use stdClass;
16
17
/**
18
 * Class Position
19
 *
20
 * Tests whether the cite position matches the given positions (terminology: citations consist of one or more cites to
21
 * individual items). When called within the scope of cs:bibliography, position tests “false”. The positions that can
22
 * be tested are:
23
 *   - “first”: position of cites that are the first to reference an item
24
 *   - “ibid”/”ibid-with-locator”/”subsequent”: cites referencing previously cited items have the “subsequent” position.
25
 *     Such cites may also have the “ibid” or “ibid-with-locator” position when:
26
 *     a) the current cite immediately follows on another cite, within the same citation, that references the
27
 *        same item, or
28
 *     b) the current cite is the first cite in the citation, and the previous citation consists of a single cite
29
 *        referencing the same item
30
 *     If either requirement is met, the presence of locators determines which position is assigned:
31
 *     -  Preceding cite does not have a locator: if the current cite has a locator, the position of the current cite is
32
 *        “ibid-with-locator”. Otherwise the position is “ibid”.
33
 *     -  Preceding cite does have a locator: if the current cite has the same locator, the position of the current cite
34
 *        is “ibid”. If the locator differs the position is “ibid-with-locator”. If the current cite lacks a locator
35
 *        its only position is “subsequent”.
36
 *   - “near-note”: position of a cite following another cite referencing the same item. Both cites have to be located
37
 *     in foot or endnotes, and the distance between both cites may not exceed the maximum distance (measured in number
38
 *     of foot or endnotes) set with the near-note-distance option.
39
 *
40
 * Whenever position=”ibid-with-locator” tests true, position=”ibid” also tests true. And whenever position=”ibid” or
41
 * position=”near-note” test true, position=”subsequent” also tests true.
42
 *
43
 */
44
class Position implements Constraint
45
{
46
    const FIRST = "first";
47
    const IBID = "ibid";
48
    const IBID_WITH_LOCATOR = "ibid-with-locator";
49
    const SUBSEQUENT = "subsequent";
50
    const NEAR_NOTE = "near-note";
51
52
    private $position;
53
54
    private $match;
55
56
    public function __construct(string $position, string $match = "all")
57
    {
58
        $this->position = $position;
59
        $this->match = $match;
60
    }
61
62
    /**
63
     * @codeCoverageIgnore
64
     * @param stdClass $data
65
     * @param int|null $citationNumber
66
     * @return bool
67
     */
68
    public function validate(stdClass $data, $citationNumber = null): bool
69
    {
70
        if (CiteProc::getContext()->isModeBibliography()) {
71
            return false;
72
        }
73
        switch ($this->position) {
74
            case self::FIRST:
75
                return $this->getPosition($data) === null;
76
            case self::IBID:
77
            case self::IBID_WITH_LOCATOR:
78
            case self::SUBSEQUENT:
79
                return $this->isOnLastPosition($data);
80
        }
81
        return true;
82
    }
83
84
    private function getPosition(stdClass $data): ?string
85
    {
86
        foreach (CiteProc::getContext()->getCitedItems() as $key => $value) {
87
            if (!empty($value->{'id'}) && $value->{'id'} === $data->{'id'}) {
88
                return $key;
89
            }
90
        }
91
        return null;
92
    }
93
94
    /**
95
     * @param stdClass $data
96
     * @return bool
97
     */
98
    private function isOnLastPosition(stdClass $data): bool
99
    {
100
        $lastCitedItem = CiteProc::getContext()->getCitedItems()->last();
101
        return !empty($lastCitedItem) && $lastCitedItem->{'id'} === $data->{'id'};
102
    }
103
}
104