Passed
Push — feature/locators-issue-82 ( f7cde7...464c3c )
by Sebastian
04:57
created

Text::__construct()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 5
nop 1
dl 0
loc 17
ccs 13
cts 13
cp 1
crap 4
rs 9.8666
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
29
/**
30
 * Class Term
31
 *
32
 * @package Seboettg\CiteProc\Node\Style
33
 *
34
 * @author Sebastian Böttger <[email protected]>
35
 */
36
class Text implements Rendering
37
{
38
    use FormattingTrait,
0 ignored issues
show
Bug introduced by
The trait Seboettg\CiteProc\Styles\QuotesTrait requires the property $single which is not provided by Seboettg\CiteProc\Rendering\Text.
Loading history...
Bug introduced by
The trait Seboettg\CiteProc\Styles\AffixesTrait requires the property $single which is not provided by Seboettg\CiteProc\Rendering\Text.
Loading history...
39
        AffixesTrait,
40
        TextCaseTrait,
41
        DisplayTrait,
42
        ConsecutivePunctuationCharacterTrait,
43
        QuotesTrait;
44
45
    /**
46
     * @var string
47
     */
48
    private $toRenderType;
49
50
    /**
51
     * @var string
52
     */
53
    private $toRenderTypeValue;
54
55
    /**
56
     * @var string
57
     */
58
    private $form = "long";
59
60
    /**
61
     * Text constructor.
62
     *
63
     * @param SimpleXMLElement $node
64
     */
65 108
    public function __construct(SimpleXMLElement $node)
66
    {
67 108
        foreach ($node->attributes() as $attribute) {
68 108
            $name = $attribute->getName();
69 108
            if (in_array($name, ['value', 'variable', 'macro', 'term'])) {
70 108
                $this->toRenderType = $name;
71 108
                $this->toRenderTypeValue = (string) $attribute;
72
            }
73 108
            if ($name === "form") {
74 108
                $this->form = (string) $attribute;
75
            }
76
        }
77 108
        $this->initFormattingAttributes($node);
78 108
        $this->initDisplayAttributes($node);
79 108
        $this->initTextCaseAttributes($node);
80 108
        $this->initAffixesAttributes($node);
81 108
        $this->initQuotesAttributes($node);
82 108
    }
83
84
    /**
85
     * @param  stdClass $data
86
     * @param  int|null $citationNumber
87
     * @return string
88
     */
89 92
    public function render($data, $citationNumber = null)
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...
90
    {
91 92
        $lang = (isset($data->language) && $data->language != 'en') ? $data->language : 'en';
92
93 92
        $renderedText = "";
94 92
        switch ($this->toRenderType) {
95 92
            case 'value':
96 22
                $renderedText = $this->applyTextCase($this->toRenderTypeValue, $lang);
97 22
                break;
98 85
            case 'variable':
99 75
                if ($this->toRenderTypeValue === "locator" && CiteProc::getContext()->isModeCitation()) {
100 7
                    $renderedText = $this->renderLocator($data, $citationNumber);
101
                // for test sort_BibliographyCitationNumberDescending.json
102 75
                } elseif ($this->toRenderTypeValue === "citation-number") {
103 13
                    $renderedText = $this->renderCitationNumber($data, $citationNumber);
104 13
                    break;
105 71
                } elseif (in_array($this->toRenderTypeValue, ["page", "chapter-number", "folio"])) {
106 28
                    $renderedText = !empty($data->{$this->toRenderTypeValue}) ?
107 28
                        $this->renderPage($data->{$this->toRenderTypeValue}) : '';
108
                } else {
109 67
                    $renderedText = $this->renderVariable($data, $lang);
110
                }
111 73
                if (CiteProc::getContext()->getRenderingState()->getValue() === RenderingState::SUBSTITUTION) {
112 7
                    unset($data->{$this->toRenderTypeValue});
113
                }
114 73
                $renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
115 73
                break;
116 60
            case 'macro':
117 53
                $renderedText = $this->renderMacro($data);
118 53
                break;
119 26
            case 'term':
120 26
                $term = CiteProc::getContext()
121 26
                    ->getLocale()
122 26
                    ->filter("terms", $this->toRenderTypeValue, $this->form)
123 26
                    ->single;
124 26
                $renderedText = !empty($term) ? $this->applyTextCase($term, $lang) : "";
125
        }
126 92
        if (!empty($renderedText)) {
127 92
            $renderedText = $this->formatRenderedText($renderedText);
128
        }
129 92
        return $renderedText;
130
    }
131
132
    /**
133
     * @return string
134
     */
135 59
    public function getSource()
136
    {
137 59
        return $this->toRenderType;
138
    }
139
140
    /**
141
     * @return string
142
     */
143 59
    public function getVariable()
144
    {
145 59
        return $this->toRenderTypeValue;
146
    }
147
148 17
    private function renderPage($page)
149
    {
150 17
        if (preg_match(NumberHelper::PATTERN_COMMA_AMPERSAND_RANGE, $page)) {
151 15
            $page = $this->normalizeDateRange($page);
152 15
            $ranges = preg_split("/[-–]/", trim($page));
153 15
            if (count($ranges) > 1) {
0 ignored issues
show
Bug introduced by
It seems like $ranges can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

153
            if (count(/** @scrutinizer ignore-type */ $ranges) > 1) {
Loading history...
154 14
                if (!empty(CiteProc::getContext()->getGlobalOptions())
155 14
                    && !empty(CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat())
156
                ) {
157 7
                    return PageHelper::processPageRangeFormats(
158 7
                        $ranges,
0 ignored issues
show
Bug introduced by
It seems like $ranges can also be of type false; however, parameter $ranges of Seboettg\CiteProc\Util\P...ocessPageRangeFormats() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

158
                        /** @scrutinizer ignore-type */ $ranges,
Loading history...
159 7
                        CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat()
160
                    );
161
                }
162 7
                list($from, $to) = $ranges;
163 7
                return $from . "–" . $to;
164
            }
165
        }
166 3
        return $page;
167
    }
168
169 7
    private function renderLocator($data, $citationNumber)
170
    {
171 7
        $citationItem = CiteProc::getContext()->getCitationItemById($data->id);
172 7
        if (!empty($citationItem->label)) {
173 3
            $locatorData = new stdClass();
174 3
            $propertyName = Locator::mapLocatorLabelToRenderVariable($citationItem->label);
175 3
            $locatorData->{$propertyName} = trim($citationItem->locator);
176 3
            $renderTypeValueTemp = $this->toRenderTypeValue;
177 3
            $this->toRenderTypeValue = $propertyName;
178 3
            $result = $this->render($locatorData, $citationNumber);
179 3
            $this->toRenderTypeValue = $renderTypeValueTemp;
180 3
            return $result;
181
        }
182 4
        return isset($citationItem->locator) ? trim($citationItem->locator) : '';
183
    }
184
185 15
    private function normalizeDateRange($page)
186
    {
187 15
        if (preg_match("/^(\d+)\s?--?\s?(\d+)$/", trim($page), $matches)) {
188 14
            return $matches[1]."-".$matches[2];
189
        }
190 1
        return $page;
191
    }
192
193
    /**
194
     * @param  $data
195
     * @param  $renderedText
196
     * @return mixed
197
     */
198 75
    private function applyAdditionalMarkupFunction($data, $renderedText)
199
    {
200 75
        return CiteProcHelper::applyAdditionMarkupFunction($data, $this->toRenderTypeValue, $renderedText);
201
    }
202
203
    /**
204
     * @param  $data
205
     * @param  $lang
206
     * @return string
207
     */
208 67
    private function renderVariable($data, $lang)
209
    {
210
        // check if there is an attribute with prefix short or long e.g. shortTitle or longAbstract
211
        // test case group_ShortOutputOnly.json
212 67
        $renderedText = "";
213 67
        if (in_array($this->form, ["short", "long"])) {
214 67
            $attrWithPrefix = $this->form.ucfirst($this->toRenderTypeValue);
215 67
            $attrWithSuffix = $this->toRenderTypeValue."-".$this->form;
216 67
            if (isset($data->{$attrWithPrefix}) && !empty($data->{$attrWithPrefix})) {
217 1
                $renderedText = $this->applyTextCase(
218 1
                    StringHelper::clearApostrophes(
219 1
                        str_replace(" & ", " &#38; ", $data->{$attrWithPrefix})
220
                    ),
221 1
                    $lang
222
                );
223
            } else {
224 66
                if (isset($data->{$attrWithSuffix}) && !empty($data->{$attrWithSuffix})) {
225 3
                    $renderedText = $this->applyTextCase(
226 3
                        StringHelper::clearApostrophes(
227 3
                            str_replace(" & ", " &#38; ", $data->{$attrWithSuffix})
228
                        ),
229 3
                        $lang
230
                    );
231
                } else {
232 66
                    if (isset($data->{$this->toRenderTypeValue})) {
233 66
                        $renderedText = $this->applyTextCase(
234 66
                            StringHelper::clearApostrophes(
235 66
                                str_replace(" & ", " &#38; ", $data->{$this->toRenderTypeValue})
236
                            ),
237 67
                            $lang
238
                        );
239
                    }
240
                }
241
            }
242
        } else {
243
            if (!empty($data->{$this->toRenderTypeValue})) {
244
                $renderedText = $this->applyTextCase(
245
                    StringHelper::clearApostrophes(
246
                        str_replace(" & ", " &#38; ", $data->{$this->toRenderTypeValue})
247
                    ),
248
                    $lang
249
                );
250
            }
251
        }
252 67
        return $renderedText;
253
    }
254
255
    /**
256
     * @param  $renderedText
257
     * @return string
258
     */
259 92
    private function formatRenderedText($renderedText)
260
    {
261 92
        $text = $this->format($renderedText);
262 92
        $res = $this->addAffixes($text);
263 92
        if (!empty($res)) {
264 92
            $res = $this->removeConsecutiveChars($res);
265
        }
266 92
        $res = $this->addSurroundingQuotes($res);
267 92
        return $this->wrapDisplayBlock($res);
268
    }
269
270
    /**
271
     * @param  $data
272
     * @param  $citationNumber
273
     * @return int|mixed
274
     */
275 13
    private function renderCitationNumber($data, $citationNumber)
276
    {
277 13
        $renderedText = $citationNumber + 1;
278 13
        $renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
279 13
        return $renderedText;
280
    }
281
282
    /**
283
     * @param  $data
284
     * @return string
285
     */
286 53
    private function renderMacro($data)
287
    {
288 53
        $macro = CiteProc::getContext()->getMacro($this->toRenderTypeValue);
289 53
        if (is_null($macro)) {
290
            try {
291 1
                throw new CiteProcException("Macro \"".$this->toRenderTypeValue."\" does not exist.");
292 1
            } catch (CiteProcException $e) {
293 1
                $renderedText = "";
294
            }
295
        } else {
296 53
            $renderedText = $macro->render($data);
297
        }
298 53
        return $renderedText;
299
    }
300
}
301