Passed
Push — feature/issue-111-php80-compat... ( 179440 )
by Sebastian
05:37
created

Text::getVariable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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;
11
12
use Seboettg\CiteProc\CiteProc;
13
use Seboettg\CiteProc\Exception\CiteProcException;
14
use Seboettg\CiteProc\RenderingState;
15
use Seboettg\CiteProc\Styles\AffixesTrait;
16
use Seboettg\CiteProc\Styles\ConsecutivePunctuationCharacterTrait;
17
use Seboettg\CiteProc\Styles\DisplayTrait;
18
use Seboettg\CiteProc\Styles\FormattingTrait;
19
use Seboettg\CiteProc\Styles\QuotesTrait;
20
use Seboettg\CiteProc\Styles\TextCaseTrait;
21
use Seboettg\CiteProc\Terms\Locator;
22
use Seboettg\CiteProc\Util\CiteProcHelper;
23
use Seboettg\CiteProc\Util\NumberHelper;
24
use Seboettg\CiteProc\Util\PageHelper;
25
use Seboettg\CiteProc\Util\StringHelper;
26
use SimpleXMLElement;
27
use stdClass;
28
use function Seboettg\CiteProc\ucfirst;
29
30
/**
31
 * Class Term
32
 *
33
 * @package Seboettg\CiteProc\Node\Style
34
 *
35
 * @author Sebastian Böttger <[email protected]>
36
 */
37
class Text implements Rendering
38
{
39
    use FormattingTrait,
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\Text.
Loading history...
Bug introduced by
The trait Seboettg\CiteProc\Styles\QuotesTrait requires the property $single which is not provided by Seboettg\CiteProc\Rendering\Text.
Loading history...
40
        AffixesTrait,
41
        TextCaseTrait,
42
        DisplayTrait,
43
        ConsecutivePunctuationCharacterTrait,
44
        QuotesTrait;
45
46
    /**
47
     * @var string
48
     */
49
    private $toRenderType;
50
51
    /**
52
     * @var string
53
     */
54
    private $toRenderTypeValue;
55
56
    /**
57
     * @var string
58
     */
59
    private $form = "long";
60
61
    /**
62
     * Text constructor.
63
     *
64
     * @param SimpleXMLElement $node
65
     */
66 118
    public function __construct(SimpleXMLElement $node)
67
    {
68 118
        foreach ($node->attributes() as $attribute) {
69 118
            $name = $attribute->getName();
70 118
            if (in_array($name, ['value', 'variable', 'macro', 'term'])) {
71 118
                $this->toRenderType = $name;
72 118
                $this->toRenderTypeValue = (string) $attribute;
73
            }
74 118
            if ($name === "form") {
75 42
                $this->form = (string) $attribute;
76
            }
77
        }
78 118
        $this->initFormattingAttributes($node);
79 118
        $this->initDisplayAttributes($node);
80 118
        $this->initTextCaseAttributes($node);
81 118
        $this->initAffixesAttributes($node);
82 118
        $this->initQuotesAttributes($node);
83 118
    }
84
85
    /**
86
     * @param  stdClass $data
87
     * @param  int|null $citationNumber
88
     * @return string
89
     */
90 102
    public function render($data, $citationNumber = null)
91
    {
92 102
        $lang = (isset($data->language) && $data->language != 'en') ? $data->language : 'en';
93
94 102
        $renderedText = "";
95 102
        switch ($this->toRenderType) {
96 102
            case 'value':
97 26
                $renderedText = $this->applyTextCase($this->toRenderTypeValue, $lang);
98 26
                break;
99 95
            case 'variable':
100 85
                if ($this->toRenderTypeValue === "locator" && CiteProc::getContext()->isModeCitation()) {
101 8
                    $renderedText = $this->renderLocator($data, $citationNumber);
102
                // for test sort_BibliographyCitationNumberDescending.json
103 85
                } elseif ($this->toRenderTypeValue === "citation-number") {
104 15
                    $renderedText = $this->renderCitationNumber($data, $citationNumber);
105 15
                    break;
106 81
                } elseif (in_array($this->toRenderTypeValue, ["page", "chapter-number", "folio"])) {
107 34
                    $renderedText = !empty($data->{$this->toRenderTypeValue}) ?
108 34
                        $this->renderPage($data->{$this->toRenderTypeValue}) : '';
109
                } else {
110 77
                    $renderedText = $this->renderVariable($data, $lang);
111
                }
112 83
                if (CiteProc::getContext()->getRenderingState()->getValue() === RenderingState::SUBSTITUTION) {
113 7
                    unset($data->{$this->toRenderTypeValue});
114
                }
115 83
                $renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
116 83
                break;
117 69
            case 'macro':
118 62
                $renderedText = $this->renderMacro($data);
119 62
                break;
120 26
            case 'term':
121 26
                $term = CiteProc::getContext()
122 26
                    ->getLocale()
123 26
                    ->filter("terms", $this->toRenderTypeValue, $this->form)
124 26
                    ->single;
125 26
                $renderedText = !empty($term) ? $this->applyTextCase($term, $lang) : "";
126
        }
127 102
        if (!empty($renderedText)) {
128 102
            $renderedText = $this->formatRenderedText($renderedText);
129
        }
130 102
        return $renderedText;
131
    }
132
133
    /**
134
     * @return string
135
     */
136 66
    public function getSource()
137
    {
138 66
        return $this->toRenderType;
139
    }
140
141
    /**
142
     * @return string
143
     */
144 66
    public function getVariable()
145
    {
146 66
        return $this->toRenderTypeValue;
147
    }
148
149 23
    private function renderPage($page)
150
    {
151 23
        if (preg_match(NumberHelper::PATTERN_COMMA_AMPERSAND_RANGE, $page)) {
152 21
            $page = $this->normalizeDateRange($page);
153 21
            $ranges = preg_split("/[-–]/", trim($page));
154 21
            if (count($ranges) > 1) {
155 20
                if (!empty(CiteProc::getContext()->getGlobalOptions())
156 20
                    && !empty(CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat())
157
                ) {
158 9
                    return PageHelper::processPageRangeFormats(
159 9
                        $ranges,
160 9
                        CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat()
161
                    );
162
                }
163 11
                list($from, $to) = $ranges;
164 11
                return $from . "–" . $to;
165
            }
166
        }
167 4
        return $page;
168
    }
169
170 8
    private function renderLocator($data, $citationNumber)
171
    {
172 8
        $citationItem = CiteProc::getContext()->getCitationItemById($data->id);
173 8
        if (!empty($citationItem->label)) {
174 4
            $locatorData = new stdClass();
175 4
            $propertyName = Locator::mapLocatorLabelToRenderVariable($citationItem->label);
176 4
            $locatorData->{$propertyName} = trim($citationItem->locator);
177 4
            $renderTypeValueTemp = $this->toRenderTypeValue;
178 4
            $this->toRenderTypeValue = $propertyName;
179 4
            $result = $this->render($locatorData, $citationNumber);
180 4
            $this->toRenderTypeValue = $renderTypeValueTemp;
181 4
            return $result;
182
        }
183 4
        return isset($citationItem->locator) ? trim($citationItem->locator) : '';
184
    }
185
186 21
    private function normalizeDateRange($page)
187
    {
188 21
        if (preg_match("/^(\d+)\s?--?\s?(\d+)$/", trim($page), $matches)) {
189 20
            return $matches[1]."-".$matches[2];
190
        }
191 1
        return $page;
192
    }
193
194
    /**
195
     * @param  $data
196
     * @param  $renderedText
197
     * @return mixed
198
     */
199 85
    private function applyAdditionalMarkupFunction($data, $renderedText)
200
    {
201 85
        return CiteProcHelper::applyAdditionMarkupFunction($data, $this->toRenderTypeValue, $renderedText);
202
    }
203
204
    /**
205
     * @param  $data
206
     * @param  $lang
207
     * @return string
208
     */
209 77
    private function renderVariable($data, $lang)
210
    {
211
        // check if there is an attribute with prefix short or long e.g. shortTitle or longAbstract
212
        // test case group_ShortOutputOnly.json
213 77
        $value = "";
214 77
        if (in_array($this->form, ["short", "long"])) {
215 77
            $attrWithPrefix = $this->form . ucfirst($this->toRenderTypeValue);
216 77
            $attrWithSuffix = $this->toRenderTypeValue . "-" . $this->form;
217 77
            if (isset($data->{$attrWithPrefix}) && !empty($data->{$attrWithPrefix})) {
218 1
                $value = $data->{$attrWithPrefix};
219
            } else {
220 76
                if (isset($data->{$attrWithSuffix}) && !empty($data->{$attrWithSuffix})) {
221 3
                    $value = $data->{$attrWithSuffix};
222
                } else {
223 76
                    if (isset($data->{$this->toRenderTypeValue})) {
224 77
                        $value = $data->{$this->toRenderTypeValue};
225
                    }
226
                }
227
            }
228
        } else {
229
            if (!empty($data->{$this->toRenderTypeValue})) {
230
                $value = $data->{$this->toRenderTypeValue};
231
            }
232
        }
233 77
        return $this->applyTextCase(
234 77
            StringHelper::clearApostrophes(
235 77
                htmlspecialchars($value, ENT_HTML5)
236
            ),
237
            $lang
238
        );
239
    }
240
241
    /**
242
     * @param  $renderedText
243
     * @return string
244
     */
245 102
    private function formatRenderedText($renderedText)
246
    {
247 102
        $text = $this->format($renderedText);
248 102
        $res = $this->addAffixes($text);
249 102
        if (!empty($res)) {
250 102
            $res = $this->removeConsecutiveChars($res);
251
        }
252 102
        $res = $this->addSurroundingQuotes($res);
253 102
        return $this->wrapDisplayBlock($res);
254
    }
255
256
    /**
257
     * @param  $data
258
     * @param  $citationNumber
259
     * @return int|mixed
260
     */
261 15
    private function renderCitationNumber($data, $citationNumber)
262
    {
263 15
        $renderedText = $citationNumber + 1;
264 15
        $renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
265 15
        return $renderedText;
266
    }
267
268
    /**
269
     * @param  $data
270
     * @return string
271
     */
272 62
    private function renderMacro($data)
273
    {
274 62
        $macro = CiteProc::getContext()->getMacro($this->toRenderTypeValue);
275 62
        if (is_null($macro)) {
276
            try {
277 1
                throw new CiteProcException("Macro \"".$this->toRenderTypeValue."\" does not exist.");
278 1
            } catch (CiteProcException $e) {
279 1
                $renderedText = "";
280
            }
281
        } else {
282 62
            $renderedText = $macro->render($data);
283
        }
284 62
        return $renderedText;
285
    }
286
}
287